Scrollbars & Scroll Snap
Scrollbar styling lets you change the appearance of the browser's default scrollbar to better match your design. CSS has dedicated pseudo-elements for WebKit browsers (::-webkit-scrollbar) that allow full customization.
Scroll Snap is a CSS feature that makes scrolling "snap" to specific positions. This is very useful for horizontal galleries, carousels, or section-based scrolling. Each scroll stop will "stick" to the nearest element.
scroll-behavior: smooth makes all scrolling (including anchor links) move smoothly instead of jumping directly.
Code Example
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Arial, sans-serif;
background: #f0f2f5;
color: #333;
scroll-behavior: smooth;
}
.demo-section {
max-width: 800px;
margin: 40px auto;
padding: 30px;
background: white;
border-radius: 12px;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.demo-section h3 {
margin-top: 0;
color: #333;
}
/* Custom Scrollbar - WebKit */
.custom-scrollbar {
width: 100%;
height: 200px;
overflow-y: scroll;
padding: 15px;
background: #fafafa;
border: 1px solid #e0e0e0;
border-radius: 8px;
line-height: 1.7;
}
.custom-scrollbar::-webkit-scrollbar {
width: 10px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: #f0f0f0;
border-radius: 5px;
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #667eea, #764ba2);
border-radius: 5px;
}
.custom-scrollbar::-webkit-scrollbar-thumb:hover {
background: linear-gradient(180deg, #5a6fd6, #6a4292);
}
/* Thin Scrollbar */
.thin-scrollbar {
width: 100%;
height: 200px;
overflow-y: scroll;
padding: 15px;
background: #fafafa;
border: 1px solid #e0e0e0;
border-radius: 8px;
}
.thin-scrollbar::-webkit-scrollbar {
width: 6px;
}
.thin-scrollbar::-webkit-scrollbar-track {
background: transparent;
}
.thin-scrollbar::-webkit-scrollbar-thumb {
background: #ccc;
border-radius: 3px;
}
.thin-scrollbar::-webkit-scrollbar-thumb:hover {
background: #aaa;
}
/* Dark Scrollbar */
.dark-scrollbar {
width: 100%;
height: 200px;
overflow-y: scroll;
padding: 15px;
background: #1a1a2e;
color: #ccc;
border-radius: 8px;
}
.dark-scrollbar::-webkit-scrollbar {
width: 8px;
}
.dark-scrollbar::-webkit-scrollbar-track {
background: #16213e;
}
.dark-scrollbar::-webkit-scrollbar-thumb {
background: #444;
border-radius: 4px;
}
.dark-scrollbar::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* Horizontal Scroll Snap Gallery */
.scroll-gallery {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 15px;
padding: 10px 0;
-webkit-overflow-scrolling: touch;
}
.scroll-gallery::-webkit-scrollbar {
height: 6px;
}
.scroll-gallery::-webkit-scrollbar-track {
background: #f0f0f0;
border-radius: 3px;
}
.scroll-gallery::-webkit-scrollbar-thumb {
background: #667eea;
border-radius: 3px;
}
.gallery-item {
flex: 0 0 250px;
height: 180px;
scroll-snap-align: start;
border-radius: 10px;
overflow: hidden;
position: relative;
}
.gallery-item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.3s;
}
.gallery-item:hover img {
transform: scale(1.05);
}
.gallery-item .caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 10px;
background: linear-gradient(transparent, rgba(0,0,0,0.7));
color: white;
font-size: 0.85em;
}
/* Scroll Snap Sections */
.snap-container {
height: 400px;
overflow-y: scroll;
scroll-snap-type: y mandatory;
border-radius: 8px;
border: 1px solid #e0e0e0;
}
.snap-section {
height: 400px;
scroll-snap-align: start;
display: flex;
align-items: center;
justify-content: center;
font-size: 2em;
font-weight: bold;
color: white;
}
.snap-section:nth-child(1) {
background: linear-gradient(135deg, #667eea, #764ba2);
}
.snap-section:nth-child(2) {
background: linear-gradient(135deg, #f093fb, #f5576c);
}
.snap-section:nth-child(3) {
background: linear-gradient(135deg, #4facfe, #00f2fe);
}
.snap-section:nth-child(4) {
background: linear-gradient(135deg, #43e97b, #38f9d7);
}
/* Smooth Scroll Navigation */
.smooth-nav {
display: flex;
gap: 10px;
margin-bottom: 20px;
position: sticky;
top: 0;
background: white;
padding: 15px 0;
z-index: 10;
border-bottom: 1px solid #eee;
}
.smooth-nav a {
padding: 8px 16px;
background: #667eea;
color: white;
text-decoration: none;
border-radius: 6px;
font-size: 0.9em;
transition: background 0.2s;
}
.smooth-nav a:hover {
background: #5a6fd6;
}
/* Horizontal scroll with mandatory snap */
.snap-mandatory {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 20px;
padding: 10px 0;
}
.snap-mandatory .card {
flex: 0 0 calc(33.333% - 14px);
scroll-snap-align: center;
background: white;
border-radius: 10px;
padding: 25px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
text-align: center;
}
.snap-mandatory .card h4 {
color: #667eea;
margin-bottom: 8px;
}
</style>
</head>
<body>
<div class="demo-section">
<h3>Custom Scrollbar (Gradient)</h3>
<div class="custom-scrollbar">
<p>This is an example of a custom scrollbar with a gradient. This scrollbar only works in WebKit browsers like Chrome, Edge, and Safari.</p>
<p>CSS uses the pseudo-elements ::-webkit-scrollbar, ::-webkit-scrollbar-track, and ::-webkit-scrollbar-thumb to change the appearance.</p>
<p>For Firefox, you can use the `scrollbar-width` and `scrollbar-color` properties, which are more limited but cross-browser.</p>
<p>Tip: Make sure the scrollbar contrast is high enough to remain accessible.</p>
<p>Scrollbars that are too thin may be hard to use for people with limited motor control.</p>
</div>
</div>
<div class="demo-section">
<h3>Thin Scrollbar</h3>
<div class="thin-scrollbar">
<p>This thin scrollbar suits a minimalist interface. Notice how subtle the difference is compared to the default scrollbar default.</p>
<p>Use thin scrollbars when you want to keep a clean appearance without sacrificing scroll functionality.</p>
<p>But be careful: too thin can hurt usability.</p>
</div>
</div>
<div class="demo-section">
<h3>Dark Theme Scrollbar</h3>
<div class="dark-scrollbar">
<p>Scrollbars for a dark theme. The colors are adjusted so they remain visible on a dark background.</p>
<p>Dark themes are increasingly popular and are easier on the eyes in low light.</p>
<p>Make sure all UI elements, including scrollbars, are consistent with the chosen theme.</p>
</div>
</div>
<div class="demo-section">
<h3>Horizontal Scroll Snap Gallery</h3>
<div class="scroll-gallery">
<div class="gallery-item">
<img src="https://picsum.photos/500/360?random=10" alt="Image 1">
<div class="caption">Pegunungan</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/500/360?random=11" alt="Image 2">
<div class="caption">Pantai</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/500/360?random=12" alt="Image 3">
<div class="caption">Hutan</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/500/360?random=13" alt="Image 4">
<div class="caption">City</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/500/360?random=14" alt="Image 5">
<div class="caption">Danau</div>
</div>
<div class="gallery-item">
<img src="https://picsum.photos/500/360?random=15" alt="Image 6">
<div class="caption">Gurun</div>
</div>
</div>
</div>
<div class="demo-section">
<h3>Scroll Snap Sections (Vertical)</h3>
<div class="snap-container">
<div class="snap-section">Section 1</div>
<div class="snap-section">Section 2</div>
<div class="snap-section">Section 3</div>
<div class="snap-section">Section 4</div>
</div>
</div>
</body>
</html>
Code Explanation
::-webkit-scrollbar: Sets the scrollbar's width/height. width: 10px for a vertical scrollbar, height: 6px for a horizontal one.
::-webkit-scrollbar-track: The background track where the scrollbar thumb moves. Can be transparent or colored.
::-webkit-scrollbar-thumb: The draggable part. Can be given a gradient, border-radius, or hover effects.
scroll-snap-type: x mandatory: Makes the container snap to its child elements horizontally. mandatory means always snap, proximity only snaps when close enough.
scroll-snap-align: start: Determines the snap point on the child element. start, center, or end.
scroll-behavior: smooth: Makes all scroll navigation (including anchor links) move smoothly. Applied to a container or to html.
-webkit-overflow-scrolling: touch: Enables momentum scrolling on iOS Safari.
Everyday Use Cases
Image gallery: Horizontal scroll snap for a portfolio gallery or product showcase.
Landing page sections: Vertical scroll snap for full-screen sections on a landing page.
Chat interface: A thin, subtle custom scrollbar for a chat container.
Dashboard sidebar: A dark scrollbar for sidebar navigation in a dark-mode dashboard.
Conclusion
Custom scrollbars give you full control over the appearance of the scroll indicator. WebKit provides the most flexibility via pseudo-elements. Scroll Snap enables snapping behavior for galleries and section-based layouts. Combine it with scroll-behavior: smooth for a more refined user experience. Keep browser compatibility in mind — scrollbar styling only works in WebKit, while scroll snap is already broadly supported.