---
status: implemented
date: 2026-02-09
---
# Slider
Compound, headless slider components for media controls — seek, volume, and future use cases.
## Problem
Media players need sliders for two core interactions:
1. **Time seek** — scrub through video, see buffered range, preview time at pointer
2. **Volume** — adjust volume level, often vertical
Both share mechanics (drag, keyboard, pointer tracking) but differ in what they control and what they display. A time slider needs buffered progress, formatted time values, and thumbnail previews. A volume slider just needs a fill bar.
Requirements:
- Compound and composable — users assemble parts, omit what they don't need
- Headless — no baked-in styles, CSS custom properties for positioning
- Accessible — `role="slider"`, full keyboard support, `aria-valuetext`
- Treeshakeable — domain sliders (time, volume) import only what they use
- Cross-platform — same core logic drives React components and HTML custom elements
## Anatomy
### React
```tsx
import { TimeSlider } from '@videojs/react';
```
```tsx
import { VolumeSlider } from '@videojs/react';
```
### HTML
```html
```
```html
```
## CSS Custom Properties
Sliders expose continuous values as CSS custom properties on the root element. Users style parts using these — no inline styles are applied.
| Property | Example | Description |
| -------- | ------- | ----------- |
| `--media-slider-fill` | `45.000%` | Current value as percentage of range |
| `--media-slider-pointer` | `62.500%` | Pointer position as percentage of track |
| `--media-slider-buffer` | `78.000%` | Buffered range as percentage (set by domain roots that have a buffer concept) |
## Data Attributes
State is exposed through data attributes for CSS targeting. Applied to the root element **and all children** (Track, Fill, Buffer, Thumb, Preview, Value).
| Attribute | Values | When |
| --------- | ------ | ---- |
| `data-dragging` | present/absent | User is dragging the slider |
| `data-pointing` | present/absent | Pointer is over the slider |
| `data-interactive` | present/absent | Hovering, focused, or dragging |
| `data-orientation` | `horizontal` / `vertical` | Always present |
| `data-disabled` | present/absent | Slider is disabled |
Time slider adds:
| Attribute | Values | When |
| --------- | ------ | ---- |
| `data-seeking` | present/absent | Media is seeking |
## Keyboard
Keyboard events are handled by the **Thumb** element (the focusable `role="slider"` element). Defaults match YouTube's seek behavior. All step values are customizable via `step` and `largeStep` props on Root. `Shift+Arrow` is an ergonomic shortcut for `Page Up/Down` — same step size.
| Key | Time Slider | Volume Slider |
| --- | ----------- | ------------- |
| `ArrowRight` / `ArrowUp` | Seek forward 5 seconds | Increase volume 5% |
| `ArrowLeft` / `ArrowDown` | Seek backward 5 seconds | Decrease volume 5% |
| `Shift + Arrow` | Seek forward/backward 10 seconds | Increase/decrease volume 10% |
| `PageUp` / `PageDown` | Seek forward/backward 10 seconds | Increase/decrease volume 10% |
| `Home` / `End` | Seek to beginning / end | Set to minimum / maximum |
| `0`–`9` | Jump to 0%–90% of duration | Jump to 0%–90% of range |
## Accessibility
The **Thumb** element carries `role="slider"` and is the keyboard focus target. Root handles pointer events (click-to-seek on track area). This follows the [WAI-ARIA Slider Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/slider/) and the [Media Seek Slider Example](https://www.w3.org/WAI/ARIA/apg/patterns/slider/examples/slider-seek/).
### Thumb Is Always Present
Users who want a "thumbless" visual slider hide it with CSS — the element remains focusable and announced by screen readers. Without Thumb, there's no element to receive focus or announce the slider to assistive technology.
### No Hidden ``
Media player sliders are never form fields. Time seek and volume control don't participate in form submission. `role="slider"` with proper ARIA attributes is the correct semantic. If a generic `Slider.Root` form use case emerges later, hidden input support can be added without touching domain sliders.
### Thumb Alignment: Center and Edge Modes
`thumbAlignment` prop on Root: `'center'` (default) or `'edge'`.
- **Center** — Thumb center aligns with track edge at min/max. Half the thumb visually overflows at 0%/100%. Standard media player visual.
- **Edge** — Thumb stays fully within the track. Uses `ResizeObserver` on Thumb to measure size and compute adjusted `--media-slider-fill`.
### Domain ARIA Labels
Domain cores set `aria-label` and `aria-valuetext`. The `label` prop allows customization and localization.
**Time slider `aria-valuetext`** uses human-readable phrases from `formatTimeAsPhrase()`. On init/focus: `"{currentTime} of {duration}"`. During changes: `"{currentTime}"` only — omitting duration reduces screen reader verbosity per [APG seek slider guidance](https://www.w3.org/WAI/ARIA/apg/patterns/slider/examples/slider-seek/#accessibilityfeatures).
**Volume slider `aria-valuetext`** when muted: `"{volume} percent, muted"`. `aria-valuenow` reflects the actual underlying volume (not 0), so users know what they'll hear when unmuting.
### `aria-live="off"` on Slider Value
`Slider.Value` renders `