npm package: @loipham/material-slider
Description: The Material Components for the web slider component
Latest version: 14.0.4

<!--docs:
title: "Sliders"
layout: detail
section: components
excerpt: "Sliders allow users to make selections from a range of values."
iconId: slider
path: /catalog/input-controls/sliders/
-->

# Slider

[Sliders](https://material.io/components/sliders/) allow users to make
selections from a range of values.

The MDC Slider implementation supports both single point sliders (one thumb)
and range sliders (two thumbs). It is backed by the browser
`<input type="range">` element, is fully accessible, and is RTL-aware.

**Contents**

*   [Using sliders](#using-sliders)
*   [Sliders](#sliders)
*   [Other variants](#other-variants)
*   [Additional information](#additional-information)
*   [API](#api)

## Using sliders

### Installing sliders

```
npm install @loipham/material-slider
```

### Styles

```scss
@use "@loipham/material-slider/styles";
```

### JavaScript instantiation

```js
import {MDCSlider} from '@loipham/material-slider';

const slider = new MDCSlider(document.querySelector('.mdc-slider'));
```

**Note**: See [Importing the JS component](../../docs/importing-js.md) for more
information on how to import JavaScript.

### Making sliders accessible

Sliders are backed by an `<input>` element, meaning that they are fully
accessible. Unlike the [ARIA-based slider](https://www.w3.org/TR/wai-aria-practices/#slider),
MDC sliders are adjustable using touch-based assistive technologies such as
TalkBack on Android.

Per the spec, ensure that the following attributes are added to the
`input` element(s):

* `value`: Value representing the current value.
* `min`: Value representing the minimum allowed value.
* `max`: Value representing the maximum allowed value.
* `aria-label` or `aria-labelledby`: Accessible label for the slider.

If the value is not user-friendly (e.g. a number to
represent the day of the week), also set the following:

* `aria-valuetext`: Set this input attribute to a string that makes the slider
value understandable, e.g. 'Monday'.
* Add a function to map the slider value to `aria-valuetext` via the
`MDCSlider#setValueToAriaValueTextFn` method.

## Sliders

There are two types of sliders:

1.  [Continuous slider](#continuous-slider)
1.  [Discrete slider](#discrete-slider)

### Continuous slider

Continuous sliders allow users to make meaningful selections that don’t require
a specific value.

Note: The step size for value quantization is, by default, 1. To specify
a custom step size, provide a value for the `step` attribute on the `input`
element.

<img src="images/continuous-slider.png" alt="Continuous slider with a value of 50">

```html
<div class="mdc-slider">
  <input class="mdc-slider__input" type="range" min="0" max="100" value="50" name="volume" aria-label="Continuous slider demo">
  <div class="mdc-slider__track">
    <div class="mdc-slider__track--inactive"></div>
    <div class="mdc-slider__track--active">
      <div class="mdc-slider__track--active_fill"></div>
    </div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__thumb-knob"></div>
  </div>
</div>
```

#### Continuous range slider

Note: By default there's no minimum distance between the two thumbs. To specify
one, provide a value for the `data-min-range` attribute on the root element and
adjust the `min` and `max` attributes on the input elements accordingly.

<img src="images/continuous-range-slider.png" alt="Continuous range slider with values of 30 and 70">

```html
<div class="mdc-slider mdc-slider--range" data-min-range="10">
  <input class="mdc-slider__input" type="range" min="0" max="60" value="30" name="rangeStart" aria-label="Continuous range slider demo">
  <input class="mdc-slider__input" type="range" min="40" max="100" value="70" name="rangeEnd" aria-label="Continuous range slider demo">
  <div class="mdc-slider__track">
    <div class="mdc-slider__track--inactive"></div>
    <div class="mdc-slider__track--active">
      <div class="mdc-slider__track--active_fill"></div>
    </div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__thumb-knob"></div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__thumb-knob"></div>
  </div>
</div>
```

### Discrete slider

Discrete sliders display a numeric value label upon pressing the thumb, which
allows a user to select an exact value.

<img src="images/discrete-slider.png" alt="Discrete slider with a value of 50">

To create a discrete slider, add the following:

*   `mdc-slider--discrete` class on the root element.
*   Value indicator element (`mdc-slider__value-indicator-container`), as shown
    below.

```html
<div class="mdc-slider mdc-slider--discrete">
  <input class="mdc-slider__input" type="range" min="0" max="100" value="50" name="volume" step="10" aria-label="Discrete slider demo">
  <div class="mdc-slider__track">
    <div class="mdc-slider__track--inactive"></div>
    <div class="mdc-slider__track--active">
      <div class="mdc-slider__track--active_fill"></div>
    </div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__value-indicator-container" aria-hidden="true">
      <div class="mdc-slider__value-indicator">
        <span class="mdc-slider__value-indicator-text">
          50
        </span>
      </div>
    </div>
    <div class="mdc-slider__thumb-knob"></div>
  </div>
</div>
```

#### Discrete slider with tick marks

Discrete sliders can optionally display tick marks. Tick marks represent
predetermined values to which the user can move the slider.

<img src="images/discrete-slider-tick-marks.png" alt="Discrete slider (with tick marks), with a value of 50">

To add tick marks to a discrete slider, add the following:

*   `mdc-slider--tick-marks` class on the root element
*   `mdc-slider__tick-marks` element as a child of the `mdc-slider__track`
    element
*   `mdc-slider__tick-mark--active` and `mdc-slider__tick-mark--inactive`
    elements as children of the `mdc-slider__tick-marks` element

```html
<div class="mdc-slider mdc-slider--discrete mdc-slider--tick-marks">
  <input class="mdc-slider__input" type="range" min="0" max="100" value="50" name="volume" step="10" aria-label="Discrete slider with tick marks demo">
  <div class="mdc-slider__track">
    <div class="mdc-slider__track--inactive"></div>
    <div class="mdc-slider__track--active">
      <div class="mdc-slider__track--active_fill"></div>
    </div>
    <div class="mdc-slider__tick-marks">
      <div class="mdc-slider__tick-mark--active"></div>
      <div class="mdc-slider__tick-mark--active"></div>
      <div class="mdc-slider__tick-mark--active"></div>
      <div class="mdc-slider__tick-mark--active"></div>
      <div class="mdc-slider__tick-mark--active"></div>
      <div class="mdc-slider__tick-mark--active"></div>
      <div class="mdc-slider__tick-mark--inactive"></div>
      <div class="mdc-slider__tick-mark--inactive"></div>
      <div class="mdc-slider__tick-mark--inactive"></div>
      <div class="mdc-slider__tick-mark--inactive"></div>
      <div class="mdc-slider__tick-mark--inactive"></div>
    </div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__value-indicator-container" aria-hidden="true">
      <div class="mdc-slider__value-indicator">
        <span class="mdc-slider__value-indicator-text">
          50
        </span>
      </div>
    </div>
    <div class="mdc-slider__thumb-knob"></div>
  </div>
</div>
```

#### Discrete range slider

```html
<div class="mdc-slider mdc-slider--range mdc-slider--discrete">
  <input class="mdc-slider__input" type="range" min="0" max="50" value="20" step="10" name="rangeStart" aria-label="Discrete range slider demo">
  <input class="mdc-slider__input" type="range" min="20" max="100" value="50" step="10" name="rangeEnd" aria-label="Discrete range slider demo">
  <div class="mdc-slider__track">
    <div class="mdc-slider__track--inactive"></div>
    <div class="mdc-slider__track--active">
      <div class="mdc-slider__track--active_fill"></div>
    </div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__value-indicator-container" aria-hidden="true">
      <div class="mdc-slider__value-indicator">
        <span class="mdc-slider__value-indicator-text">
          20
        </span>
      </div>
    </div>
    <div class="mdc-slider__thumb-knob"></div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__value-indicator-container" aria-hidden="true">
      <div class="mdc-slider__value-indicator">
        <span class="mdc-slider__value-indicator-text">
          50
        </span>
      </div>
    </div>
    <div class="mdc-slider__thumb-knob"></div>
  </div>
</div>
```

## Other variants

### Disabled slider

To disable a slider, add the following:

*   `mdc-slider--disabled` class on the root element
*   `disabled` attribute on the input element

```html
<div class="mdc-slider mdc-slider--disabled">
  <input class="mdc-slider__input" type="range" min="0" max="100" value="50" step="10" disabled name="volume" aria-label="Disabled slider demo">
  <div class="mdc-slider__track">
    <div class="mdc-slider__track--inactive"></div>
    <div class="mdc-slider__track--active">
      <div class="mdc-slider__track--active_fill"></div>
    </div>
  </div>
  <div class="mdc-slider__thumb">
    <div class="mdc-slider__thumb-knob"></div>
  </div>
</div>
```

## Additional information

### Initialization with custom ranges and values

When `MDCSlider` is initialized, it reads the input element's `min`,
`max`, and `value` attributes if present, using them to set
the component's internal `min`, `max`, and `value` properties.

Use these attributes to initialize the slider with a custom range and values,
as shown below:

```html
<div class="mdc-slider">
  <input class="mdc-slider__input" aria-label="Slider demo" min="0" max="100" value="75">
  <!-- ... -->
</div>
```

### Setting slider position before component initialization

When `MDCSlider` is initialized, it updates the slider track and thumb
positions based on the internal value(s). To set the correct track and thumb
positions before component initialization, mark up the DOM as follows:

- Calculate `rangePercentDecimal`, the active track range as a percentage of
  the entire track, i.e. `(valueEnd - valueStart) / (max - min)`.
  Set `transform:scaleX(<rangePercentDecimal>)` as an inline style on the
  `mdc-slider__track--active_fill` element.
- Calculate `thumbEndPercent`, the initial position of the end thumb as a
  percentage of the entire track. Set `left:calc(<thumbEndPercent>% - 24px)`
  as an inline style on the end thumb (`mdc-slider__thumb`) element
  (or `right` for RTL layouts).
- *[Range sliders only]* Calculate `thumbStartPercent`, the initial position
  of the start thumb as a percentage of the entire track. Set
  `left:calc(<thumbStartPercent>% - 24px)` as an inline style on the
  start thumb (`mdc-slider__thumb`) element (or `right` for RTL layouts).
- *[Range sliders only]* Using the previously calculated `thumbStartPercent`,
  set `left:<thumbStartPercent>%` as an inline style on the
  `mdc-slider__track--active_fill` element (or `right` for RTL layouts).

Additionally, the MDCSlider component should be initialized with
`skipInitialUIUpdate` set to true.

#### Range slider example

This is an example of a range slider with internal values of
`[min, max] = [0, 100]` and `[start, end] = [30, 70]`, and a minimum range of
10.

```html
<div class="mdc-slider mdc-slider--range" data-min-range="10">
  <input class="mdc-slider__input" type="range" min="0" max="60" value="30" name="rangeStart" aria-label="Range slider demo">
  <input class="mdc-slider__input" type="range" min="40" max="100" value="70" name="rangeEnd" aria-label="Range slider demo">
  <div class="mdc-slider__track">
    <div class="mdc-slider__track--inactive"></div>
    <div class="mdc-slider__track--active">
      <div class="mdc-slider__track--active_fill"
           style="transform:scaleX(.4); left:30%"></div>
    </div>
  </div>
  <div class="mdc-slider__thumb" style="left:calc(30%-24px)">
    <div class="mdc-slider__thumb-knob"></div>
  </div>
  <div class="mdc-slider__thumb" style="left:calc(70%-24px)">
    <div class="mdc-slider__thumb-knob"></div>
  </div>
</div>
```

## API

### Sass mixins

Mixin | Description
--- | ---
`track-active-color($color)` | Sets the color of the active track.
`track-inactive-color($color, $opacity)` | Sets the color and opacity of the inactive track.
`thumb-color($color)` | Sets the color of the thumb.
`thumb-ripple-color($color)` | Sets the color of the thumb ripple.
`tick-mark-active-color($color)` | Sets the color of tick marks on the active track.
`tick-mark-inactive-color($color)` | Sets the color of tick marks on the inactive track.
`value-indicator-color($color, $opaicty)` | Sets the color and opacity of the value indicator.
`value-indicator-text-color($color, $opaicty)` | Sets the color of the value indicator text.

### `MDCSlider` events

Event name | `event.detail` | Description
--- | --- | ---
`MDCSlider:change` | `MDCSliderChangeEventDetail` | Emitted when a value has been changed and committed from a user event. Mirrors the native `change` event: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event
`MDCSlider:input` | `MDCSliderChangeEventDetail` | Emitted when a value has been changed from a user event. Mirrors the native `input` event: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event

### `MDCSlider` methods

Method Signature | Description
--- | ---
`getValueStart() => number` | Gets the value of the start thumb (only applicable for range sliders).
`setValueStart(valueStart: number) => void` | Sets the value of the start thumb (only applicable for range sliders).
`getValue() => number` | Gets the value of the thumb (for single point sliders), or the end thumb (for range sliders).
`setValue(value: number) => void` | Sets the value of the thumb (for single point sliders), or the end thumb (for range sliders).
`getDisabled() => boolean` | Gets the disabled state of the slider.
`setDisabled(disabled: boolean) => void` | Sets the disabled state of the slider.
`setValueToAriaValueTextFn((mapFn: ((value: number) => string) \| null) => void` | Sets a function that maps the slider value to value of the `aria-valuetext` attribute on the thumb element. If not set, the `aria-valuetext` attribute is unchanged when the value changes.

### Usage within frameworks

If you are using a JavaScript framework such as React or Angular, you can create a slider for your framework. Depending on your needs, you can use the _Simple Approach: Wrapping MDC Web Vanilla Components_, or the _Advanced Approach: Using Foundations and Adapters_. Please follow the instructions [here](../../docs/integrating-into-frameworks.md).

See [MDCSliderAdapter](./adapter.ts) and [MDCSliderFoundation](./foundation.ts) for up-to-date code documentation of slider foundation API's.