Slider

Slider

Selections from a range of values.

Sliders let people pick from a range of values. An <input type="range"> is the control. A wrapping .slider — or .range, or a <label> — is the host. The plugin is Expressive.Slider, and Expressive.Range still resolves to it.

Three variants: standard (active from the start), centered (active grows from the midpoint), and range (two handles, active between them). Horizontal or vertical. Five sizes: XS (the default), S, M, L, XL. Optional inset icon, discrete stops, and a value indicator.

Tokens follow the M3 slider spec (Expressive). The handle is a 4dp stop with a 6dp gap to each track. Active is primary; inactive is secondary-container. The end of an inactive track has a 4dp stop. The value label is a 40dp inverse-surface bubble.

Range is not in AutoInit(). Importing the IIFE bundle calls Expressive.Range.Init(), which starts every input[type=range] already in the document and keeps the active track in sync.

<label>
  Volume
  <input type="range" min="0" max="100" value="40">
</label>

Variants

Standard is the default. centered grows the active track from 50%. A range slider is two inputs in one .range host.

<div class="slider">
  <input type="range" min="0" max="100" value="40" aria-label="Standard">
</div>

<div class="slider centered">
  <input type="range" min="0" max="100" value="30" aria-label="Centered">
</div>

<div class="slider">
  <input type="range" min="0" max="100" value="25" aria-label="Range start">
  <input type="range" min="0" max="100" value="75" aria-label="Range end">
</div>

Sizes

Default is XS (16dp track, 44dp handle). s / small is S, m / medium is M, l / large is L, xl is XL. Scope them on the host.

<div class="slider s">…</div>
<div class="slider m">…</div>
<div class="slider l">…</div>
<div class="slider xl">…</div>

Inset icon, stops, value

A leading icon sits in the active track — M, L, and XL are tall enough. stops plus step paints ticks on the active track. Dragging shows the value in a 40dp bubble.

<div class="slider m">
  <span class="material-symbols" aria-hidden="true">volume_up</span>
  <input type="range" min="0" max="100" value="55" aria-label="Volume">
</div>

<div class="slider stops">
  <input type="range" min="0" max="100" step="20" value="40" aria-label="Stops">
</div>

Vertical

vertical stands the track up. Minimum is at the bottom.

<div class="slider vertical m">
  <input type="range" min="0" max="100" value="60" aria-label="Level">
</div>

Disabled

The native disabled attribute drops the control to 38%.

Initialization

Put the script after the inputs, or call init yourself. There are no options. For a slider added after load:

document.addEventListener('DOMContentLoaded', function() {
  const elems = document.querySelectorAll('input[type=range]');
  Expressive.Range.init(elems);
});

Expressive.Range.init(document.querySelector('#volume'));

Methods

const instance = Expressive.Range.getInstance(elem);
instance.destroy();

Destroy the plugin instance, remove the value label, and tear down its event handlers.

  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.