Single Slider
One thumb for selecting a single value along the track. Drag, arrow keys, Home, End, and Page Up/Down all adjust the value
<div class="nds-slider-container nds-form-container">
<div class="nds-form-header">
<label for="slider-default-1">
<span class="nds-label">Volume</span>
<span class="nds-info">Drag the thumb or use the arrow keys</span>
</label>
</div>
<div class="nds-form-control">
<div class="nds-slider-track">
<input type="range" id="slider-default-1" class="nds-slider" min="0" max="100" value="50">
</div>
<output for="slider-default-1" class="nds-slider-value">50</output>
</div>
<div class="nds-form-footer" data-feedback-target>
<span class="nds-feedback nds-outline nds-sm" data-status="neutral" data-permanent>
<span class="nds-feedback-icon">
<i class="nds-icon" aria-hidden="true"></i>
</span>
<span class="nds-feedback-message">Changes apply instantly</span>
</span>
</div>
</div>
Range Slider
Two thumbs for selecting a min and max value. Use when the user picks a continuous span, like a price or date range
<div class="nds-slider-container nds-form-container nds-slider-range">
<div class="nds-form-header">
<label>
<span class="nds-label">Age range</span>
<span class="nds-info">Tab to either thumb and adjust independently</span>
</label>
</div>
<div class="nds-form-control">
<output class="nds-slider-value nds-slider-value-min">25</output>
<div class="nds-slider-track">
<input type="range" class="nds-slider nds-slider-min" min="18" max="80" value="25" aria-label="Minimum age">
<input type="range" class="nds-slider nds-slider-max" min="18" max="80" value="55" aria-label="Maximum age">
</div>
<output class="nds-slider-value nds-slider-value-max">55</output>
</div>
<div class="nds-form-footer" data-feedback-target>
<span class="nds-feedback nds-outline nds-sm" data-status="neutral" data-permanent>
<span class="nds-feedback-icon">
<i class="nds-icon" aria-hidden="true"></i>
</span>
<span class="nds-feedback-message">Whole years only</span>
</span>
</div>
</div>
Price Range with SAR Currency
Combine a range slider with the Numbers utility to show thousand-separated values and the official Saudi Riyal symbol next to each thumb. Add nds-number-format and data-currency="SAR" to each output — the slider applies toLocaleString() automatically on every update and the currency icon is rendered as a CSS pseudo-element.
<div class="nds-slider-container nds-form-container nds-slider-range nds-stacked" id="price-range-1">
<div class="nds-form-header">
<label>
<span class="nds-label">Budget</span>
<span class="nds-info">Drag either thumb to set the minimum and maximum spend</span>
</label>
</div>
<div class="nds-form-control">
<output class="nds-slider-value nds-slider-value-min nds-number-format" data-currency="SAR">5000</output>
<div class="nds-slider-track">
<input type="range" class="nds-slider nds-slider-min" min="0" max="100000" step="500" value="5000" aria-label="Minimum price">
<input type="range" class="nds-slider nds-slider-max" min="0" max="100000" step="500" value="65000" aria-label="Maximum price">
</div>
<output class="nds-slider-value nds-slider-value-max nds-number-format" data-currency="SAR">65000</output>
</div>
<div class="nds-form-footer" data-feedback-target>
<span class="nds-feedback nds-outline nds-sm" data-status="neutral" data-permanent>
<span class="nds-feedback-icon">
<i class="nds-icon" aria-hidden="true"></i>
</span>
<span class="nds-feedback-message">Prices include VAT</span>
</span>
</div>
</div>
Built-in Features
Activates when .nds-slider-container appears on the page. A single delegated listener handles every slider, including those added later through DOM updates.
One markup pattern for picking a value, a second for picking a min–max span. Add nds-slider-range to switch from single to dual thumbs.
Arrow keys step the value, Home and End jump to min and max, Page Up and Page Down move by larger increments. The focused thumb gets a visible bullseye ring on keyboard focus only.
The fill direction flips with the page direction: in Arabic the bar fills from the right toward the thumb, in English from the left. Thumb position, fill window, and value display all align without extra markup.
The track paints as a shimmer placeholder until init lands and during any data-loading period, so a value pulled from an async source does not flash an incorrect fill.
Reinit, destroy, and create methods on NDS.Slider let you wire sliders inside dynamically added containers without a full page rescan.
Usage Guidelines
Best Practices
- Use a single slider when the user picks one value from a continuous numeric range where the exact number is less important than the approximate position (volume, brightness, zoom, opacity)
- Use a range slider when the user filters a list or report by a min–max window (price range, age range, date range)
- Do not use a slider when the user needs an exact integer or when the valid set is short (under ten options). Use a Number Input for precise integers or a Radio Button group for a small discrete set
- Do not use a slider for binary on/off settings. Use a Switch instead
- Pair the slider with a visible value display so users can confirm the exact number. The
<output>element next to the input updates automatically as the thumb moves - Choose
nds-mdon touch-first surfaces where a 12 px thumb is hard to grab. The default 12 px reads cleanly on desktop and inside dense forms - Set a meaningful
stepattribute when the underlying value should snap (whole hours, increments of five). Without it, the input snaps to integer steps - Add the
data-loadingattribute on the container while fetching bounds or an initial value from a remote source, so the skeleton holds the space and no incorrect fill flashes when the response lands - Always provide an accessible name. A standard label is enough; for a range slider, add
aria-labelto each input ("Minimum" and "Maximum") so screen readers can distinguish them
Modifier Classes
| Class | Description |
|---|---|
nds-md | Medium size on .nds-slider-container: 16 px thumb and 8 px bar. Default is 12 px thumb and 4 px bar |
nds-slider-range | Switches the container from single to dual-thumb mode. Requires the range markup with .nds-slider-track, two inputs (.nds-slider-min, .nds-slider-max), and two value outputs |
nds-stacked | Moves the value output(s) to a row above the bar so the bar spans the full width. Use for wide or formatted values (currency, large numbers) where the default beside-the-bar layout would crush the bar on narrow screens/containers |
Data Attributes
| Attribute | Description |
|---|---|
data-loading | Set on .nds-slider-container to force the skeleton state during an async value update. Remove when the new value is ready |
min, max, step, value | Native <input type="range"> attributes that control the numeric range, step granularity, and starting value. The component reads value on init to paint the initial fill |
CSS Custom Properties
| Property | Default | Description |
|---|---|---|
--slider-track-bg | --colors-neutral-100 (dark: --colors-neutral-800) | Background color of the unfilled portion of the track |
--slider-track-fill | --background-primary | Color of the filled portion of the track |
--slider-thumb-bg | --background-primary | Background color of the thumb at rest |
--slider-thumb-bg-hovered | --controls-primary-hovered | Background color of the thumb on hover and focus |
--slider-fill-start, --slider-fill-end | 0%, 100% | Track bar fill endpoints, set on .nds-slider-track by the component on every input event. Single mode sets only --slider-fill-end (start stays 0%); range sets both. Consumers should not set these directly |
JavaScript API
The NDS.Slider API initializes sliders, repaints the fill after value changes, and tears down state. Auto-initialization activates on page load; call NDS.Slider.reinit() after dynamically inserting a slider or after writing to input.value from script.