v1.6.x-dev NDS IQ v6

Slider - National Design System

A range input for selecting a single value or a continuous min–max range from a numeric scale, with proportional sizes and full keyboard control.

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

50
<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

25
55
<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.

5000
65000
<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

Auto-initialization

Activates when .nds-slider-container appears on the page. A single delegated listener handles every slider, including those added later through DOM updates.

Single and Range Modes

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.

Keyboard Control

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.

RTL-aware Fill

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.

Skeleton State

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.

Programmatic Control

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-md on 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 step attribute when the underlying value should snap (whole hours, increments of five). Without it, the input snaps to integer steps
  • Add the data-loading attribute 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-label to each input ("Minimum" and "Maximum") so screen readers can distinguish them

Modifier Classes

ClassDescription
nds-mdMedium size on .nds-slider-container: 16 px thumb and 8 px bar. Default is 12 px thumb and 4 px bar
nds-slider-rangeSwitches 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-stackedMoves 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

AttributeDescription
data-loadingSet on .nds-slider-container to force the skeleton state during an async value update. Remove when the new value is ready
min, max, step, valueNative <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

PropertyDefaultDescription
--slider-track-bg--colors-neutral-100 (dark: --colors-neutral-800)Background color of the unfilled portion of the track
--slider-track-fill--background-primaryColor of the filled portion of the track
--slider-thumb-bg--background-primaryBackground color of the thumb at rest
--slider-thumb-bg-hovered--controls-primary-hoveredBackground color of the thumb on hover and focus
--slider-fill-start, --slider-fill-end0%, 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.

// ── Initialize all sliders on the page ─────────────── // Called automatically on DOM ready by the loader. // Idempotent: re-entry is a no-op. NDS.Slider.init(); // ── Repaint a single container or every container ──── // Use after writing to input.value from script, or after // inserting a slider into the DOM. NDS.Slider.reinit(document.querySelector('#mySlider')); NDS.Slider.reinit(); // ── Initialize one container imperatively ──────────── // Equivalent to reinit for a single element; returns the element. const slider = NDS.Slider.create(document.querySelector('#mySlider')); // ── Tear down init state ───────────────────────────── // Removes the init sentinel so a subsequent reinit re-runs // initial paint. The shared input listener stays bound for // the page lifetime. NDS.Slider.destroy(document.querySelector('#mySlider')); NDS.Slider.destroy(); // ── Reading and writing the value ──────────────────── // The native input is the source of truth. After writing, // dispatch an 'input' event OR call reinit to repaint the fill. const input = document.querySelector('#mySlider .nds-slider'); input.value = 75; input.dispatchEvent(new Event('input', { bubbles: true })); // ── Range mode ─────────────────────────────────────── // Read both endpoints from the two inputs. const container = document.querySelector('.nds-slider-range'); const min = +container.querySelector('.nds-slider-min').value; const max = +container.querySelector('.nds-slider-max').value;
Last Modified Date: 30/06/2026 - 11:50 PM
Was this page useful?
60% of users said Yes from 2843 Feedbacks