Range Slider

v1.0.0

Native range inputs with values, progress, marks and states.

Default

Apply .range-slider-input to a labelled native range input. Its output supplements the native value.

40%
<div class="range-slider">
	<div class="range-slider-header">
		<label class="form-label" for="completion">Completion</label>
		<output class="range-slider-output" for="completion">40%</output>
	</div>
	<input
		class="range-slider-input"
		id="completion"
		name="completion"
		type="range"
		min="0"
		max="100"
		step="5"
		value="40"
		style="--range-slider-progress: 40%" />
	<div class="range-slider-marks" aria-hidden="true">
		<span>0%</span>
		<span>100%</span>
	</div>
</div>

On input, update <output> and set –range-slider-progress to (value - min) / (max - min) * 100%. The package provides no JavaScript.

Marks

Use .range-slider-marks for reference values. Set aria-hidden when native semantics provide the same information.

30 min

Invalid and disabled

For validation, combine .is-invalid, aria-invalid="true" and aria-describedby. Use native disabled.

2
Choose at least three people.
65

Right to left

The fill follows direction; the browser retains native behavior and semantics.

70

Usage

  • Label the native range input.
  • Use native min, max, step, value and disabled; do not add a slider role.
  • Update output and progress without replacing native interaction.
  • Synchronize aria-valuetext only when the spoken value differs.

CSS Variables

--range-slider-gap: var(--spacer-1);
--range-slider-header-gap: var(--spacer-3);
--range-slider-progress: 0%;
--range-slider-target-size: 2.75rem;
--range-slider-track-size: 0.5rem;
--range-slider-track-bg-color: var(--control-border-color);
--range-slider-fill-color: var(--primary);
--range-slider-thumb-size: 1.5rem;
--range-slider-thumb-bg-color: var(--primary);
--range-slider-thumb-border-width: 0.125rem;
--range-slider-thumb-border-color: var(--on-primary);
--range-slider-thumb-box-shadow: var(--shadow-sm);
--range-slider-value-color: var(--text-color);
--range-slider-marker-color: var(--text-muted);
--range-slider-disabled-track-bg-color: var(--disabled-border-color);
--range-slider-disabled-fill-color: var(--disabled-text-color);
--range-slider-disabled-thumb-bg-color: var(--disabled-text-color);
--range-slider-disabled-thumb-border-color: var(--disabled-bg-color);
--range-slider-invalid-color: var(--error);
--range-slider-focus-outline-width: var(--focus-outline-width);
--range-slider-focus-outline-style: var(--focus-outline-style);
--range-slider-focus-outline-color: var(--focus-outline-color);
--range-slider-focus-outline-offset: var(--focus-offset);
--range-slider-transition-duration: var(--transition-duration);
--range-slider-transition-easing: var(--transition-easing);