# Slider

> Selections from a range of values.

## Anatomy

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](https://m3.material.io/components/sliders/specs) (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.

Volume 

```
<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%.

Locked 

## 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.
