DEV Community

WDSEGA
WDSEGA

Posted on

Component Deep Dive #31: Range Slider — From Ugly Default to Fully Custom

Component Deep Dive #31: Range Slider

The native range slider is probably the ugliest form control in the browser.

<input type="range"> comes with a gray track and a blocky thumb, rendered differently in every browser. But its advantages are undeniable: free accessibility, keyboard operability, native touch experience. The correct approach is not to rebuild with divs, but to reskin the native range.

Cross-Browser Style Reset

Key insight: Chrome's thumb needs margin-top: -6px for vertical centering — the thumb is positioned relative to the track top, track height is 6px, thumb height is 18px, offset = (18 - 6) / 2 = 6px. Firefox doesn't need this offset; it auto-centers.

Fill Effect: Highlighted Selected Area

linear-gradient + CSS variable for dynamic fill. Simpler than pseudo-element approaches — pseudo-elements can't follow the thumb position.

Dual-Thumb Range Selection

Native range only supports single values. For "$100 - $500" price ranges, overlay two range inputs:

Core technique: pointer-events: none on the input layer to stop it from blocking mouse events, but pointer-events: auto on the thumb to restore draggability. This lets two inputs stack on top of each other, each only responding to its own thumb.

Preventing Crossover

Enforce a minimum gap of 10. When the user drags min past max, instead of blocking, clamp min to max-10 — feels more natural.

Touch Adaptation

iOS default thumb is only 18x18px, below Apple's recommended 44x44px minimum touch target. Various CSS hacks exist but have browser compatibility issues. The reliable fallback is a JS solution — overlay a transparent div at the thumb position.

Common Pitfalls

  1. Don't forget -webkit-appearance: none — without it, Chrome ignores all thumb styles
  2. Firefox track height must be explicitly set — default is 0, slider disappears
  3. Dual-slider pointer-events: input = none, thumb = auto, order matters
  4. Don't simulate range with JS on mobile — native range has inertia and precise positioning that JS can't replicate

This article was originally published on Deskless Daily.

Top comments (0)