Skillversitas

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.