Chapter 16: Scrollbars, Cursors & Interactions
Small details often have the biggest impact on how "native" or "polished" a web application feels. Default scrollbars can be clunky, and the default arrow cursor is often too generic for specialized interactive elements. This chapter covers how to refine these micro-interactions using modern CSS.
1. Customizing Scrollbars
Standard scrollbars often look out of place in a modern, minimal design. While CSS scrollbar styling used to require complex vendor prefixes, the modern standard is becoming much simpler.
Scrollbar Anatomy
A scrollbar consists of two main parts: the Track (the background) and the Thumb (the draggable part).
The Modern Standard (scrollbar-width and scrollbar-color)
.custom-scroll {
scrollbar-width: thin; /* auto, thin, or none */
scrollbar-color: #94a3b8 transparent; /* thumb color, track color */
}
The Legacy Webkit Syntax (for fine-grained control)
/* Width of the scrollbar */
.webkit-scroll::-webkit-scrollbar {
width: 10px;
}
/* Draggable thumb */
.webkit-scroll::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #94a3b8, #64748b);
border-radius: 10px;
border: 2px solid #f1f5f9; /* Creates a gap around the thumb */
}
/* Track background */
.webkit-scroll::-webkit-scrollbar-track {
background: #f1f5f9;
}
2. Preventing Layout Shift with scrollbar-gutter
A common issue in web apps is the "jumping" effect when a scrollbar appears or disappears, shifting the content slightly to the left. scrollbar-gutter: stable prevents this by reserving space for the scrollbar even if it isn't needed.
.stable-container {
scrollbar-gutter: stable;
overflow-y: auto;
}
3. Refining the Cursor
The cursor provides immediate feedback about an element's functionality. Beyond the standard pointer, modern apps use specialized cursors for specific tasks.
crosshair: Perfect for drawing apps or precision selection.move: Indicates an element can be moved in any direction.copy: Shows that an item will be duplicated if dropped.help: Indicates that more information is available.
.precision-tool {
cursor: crosshair;
}
.help-icon {
cursor: help;
}
.expandable-image {
cursor: zoom-in;
}
4. Accent Colors & Highlight Control
You can brand native UI elements and control how text is selected to match your design system.
/* Change colors of checkboxes, radios, and range inputs */
form {
accent-color: #3b82f6;
}
/* Custom text selection color */
::selection {
background: rgba(59, 130, 246, 0.2);
color: #1e40af;
}
/* Prevent text selection on buttons */
.button-icon {
user-select: none;
}
5. Practical Interaction Pattern
Combining these properties creates a high-quality interactive row, like you would see in a file manager or email client.
.data-row {
cursor: pointer;
user-select: none;
scrollbar-gutter: stable;
transition: background 0.2s ease;
}
.data-row:hover {
background: #f1f5f9;
}
.data-row:active {
cursor: grabbing; /* Feedback for dragging */
}
6. Debugging Checklist
- Is the custom scrollbar making the content area smaller? (Use
scrollbar-gutter: stable). - Is the
not-allowedcursor confusing users? (Ensure the element also looks disabled). - Is
user-select: nonepreventing users from copying important information? - Are
::-webkit-scrollbarstyles not showing in Firefox? (Firefox only supportsscrollbar-widthandscrollbar-color). - Is the
pointercursor missing from an element that behaves like a button?