css
Smooth Scroll CSS & JS
Implement smooth scrolling with CSS and JavaScript, including scroll-to-top and anchor navigation.
#scroll
#animation
#navigation
Smooth scrolling implementations for modern websites.
CSS-Only Smooth Scroll
/* Global smooth scroll */
html {
scroll-behavior: smooth;
}
/* Respect user preferences */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
}
Scroll Padding (Fixed Header)
html {
scroll-behavior: smooth;
scroll-padding-top: 80px; /* Height of fixed header */
}
JavaScript Scroll Functions
// Scroll to element
function scrollToElement(selector: string, offset: number = 0) {
const element = document.querySelector(selector);
if (!element) return;
const top = element.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top, behavior: 'smooth' });
}
// Scroll to top
function scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
// Scroll to bottom
function scrollToBottom() {
window.scrollTo({
top: document.documentElement.scrollHeight,
behavior: 'smooth'
});
}
React Scroll-to-Top Button
import { useState, useEffect } from 'react';
function ScrollToTop() {
const [visible, setVisible] = useState(false);
useEffect(() => {
const toggleVisible = () => {
setVisible(window.scrollY > 300);
};
window.addEventListener('scroll', toggleVisible);
return () => window.removeEventListener('scroll', toggleVisible);
}, []);
const scrollToTop = () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
};
if (!visible) return null;
return (
<button
onClick={scrollToTop}
className="fixed bottom-6 right-6 p-3 bg-blue-500 text-white
rounded-full shadow-lg hover:bg-blue-600
transition-all duration-300"
aria-label="Scroll to top"
>
↑
</button>
);
}
Anchor Navigation Hook
function useScrollToHash() {
useEffect(() => {
const hash = window.location.hash;
if (hash) {
const element = document.querySelector(hash);
if (element) {
setTimeout(() => {
element.scrollIntoView({ behavior: 'smooth' });
}, 100);
}
}
}, []);
}
Intersection Observer for Active Section
function useActiveSection(sectionIds: string[]) {
const [activeId, setActiveId] = useState('');
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setActiveId(entry.target.id);
}
});
},
{ rootMargin: '-50% 0px -50% 0px' }
);
sectionIds.forEach((id) => {
const el = document.getElementById(id);
if (el) observer.observe(el);
});
return () => observer.disconnect();
}, [sectionIds]);
return activeId;
}