Video Player
An accessible media player: native controls, synchronized captions, a text transcript, and audio-description support.
Last verified against WCAG 2.2 and WAI-ARIA APG 1.2 on 2026-07-13.
Implementation
Transcript
[No spoken dialogue.] Gentle ambient music plays throughout. A single flower opens in timelapse — the bud swells, the petals unfurl one by one, and the bloom turns slowly toward the light before the shot fades.
Because the clip has no narration, this transcript also serves as the text alternative for its visual content (SC 1.2.3).
<figure>
<video controls preload="metadata" poster="poster.svg"
aria-label="A flower blooming in timelapse, with gentle music">
<source src="flower.mp4" type="video/mp4" />
<source src="flower.webm" type="video/webm" />
<!-- Synchronized captions (WebVTT). `default` turns them on;
`label` names the track in the CC menu. -->
<track kind="captions" src="flower.en.vtt"
srclang="en" label="English" default />
</video>
<figcaption>Sample clip. Captions on by default.</figcaption>
</figure>
<!-- Text transcript — also the media alternative when there is no narration -->
<button aria-expanded="false" aria-controls="transcript">Show transcript</button>
<div id="transcript" role="region" aria-label="Video transcript" hidden>…</div>Reach for the native <video controls> element first — its controls are already keyboard- and screen-reader-accessible. Add a captions <track>, a text transcript, and audio description where the visuals carry meaning the audio doesn't. For testing media in general, see the Media testing guide.
Live demo
Transcript
[No spoken dialogue.] Gentle ambient music plays throughout. A single flower opens in timelapse — the bud swells, the petals unfurl one by one, and the bloom turns slowly toward the light before the shot fades.
Because the clip has no narration, this transcript also serves as the text alternative for its visual content (SC 1.2.3).
Required roles, states & properties
| Element | Attribute | Why |
|---|---|---|
| <video> | controls | Exposes the browser's built-in player, whose controls are keyboard-operable and screen-reader-labelled. Prefer these native controls over hand-built ones unless you can fully re-create their accessibility. |
| <video> | aria-label (or a <figure> + <figcaption>) | Gives the player an accessible name that describes the content, so it isn't announced as a bare, unlabelled “video”. |
| <track> | kind="captions" srclang label default | Adds a synchronized WebVTT caption track. `default` turns it on initially, `label` names it in the CC menu, and captions must include speaker changes and meaningful non-speech sounds — not just dialogue. |
| <track> | kind="descriptions" · kind="subtitles" | Optional extra tracks: `descriptions` for audio-description text, `subtitles` for translations. Captions (same language, incl. sounds) are not the same as subtitles (translated dialogue only). |
| Transcript control | Real <button> with aria-expanded + aria-controls | A hand-coded disclosure that reveals the full text transcript — the alternative for people who can't use captions or audio at all (and the media alternative under SC 1.2.3). |
| <video> | no autoplay (or muted + a pause control) | Audio must not start automatically for more than 3 seconds without a way to stop it (SC 1.4.2). Prefer user-initiated playback. |
Keyboard interaction model
| Key | Behavior |
|---|---|
| Tab / Shift+Tab | Moves to the player, then between its native controls (play, mute, timeline, captions, fullscreen), then to the transcript toggle. |
| Space / Enter | On the player or play button, toggles play/pause; on the captions/fullscreen buttons, activates them. |
| Left / Right Arrow | With the timeline (or player) focused, seeks backward/forward by a few seconds. |
| Up / Down Arrow | With the player/volume focused, raises or lowers the volume. |
| M · F · C | In most browsers, shortcuts for mute, fullscreen, and captions on the focused player. Exact keys vary by browser — the requirement is only that everything is keyboard-operable. |
Native player shortcuts differ between browsers and platforms — do not hard-code them. The conformance requirement (SC 2.1.1) is only that every control is reachable and operable by keyboard, which the native element guarantees.
Focus management rules
- Let the native
<video controls>manage focus among its own controls — don't override it with custom tabindex. - The transcript disclosure keeps focus on its toggle button; the revealed transcript is a labelled region the user reads at their own pace.
- Captions are rendered by the player over the video for the audio track — they aren't in the DOM tab order and aren't read by screen readers, which use the audio itself.
WCAG 2.2 success criteria mapping
| SC | Name | Level | Why it applies |
|---|---|---|---|
| 1.2.1 | Audio-only and Video-only (Prerecorded) | A | Prerecorded audio-only has a transcript; prerecorded video-only has a description or transcript. |
| 1.2.2 | Captions (Prerecorded) | A | Synchronized captions are provided for prerecorded video that has an audio track. |
| 1.2.3 | Audio Description or Media Alternative (Prerecorded) | A | Prerecorded video provides audio description of the visuals, or a full text alternative for the media. |
| 1.2.5 | Audio Description (Prerecorded) | AA | Prerecorded video provides audio description of important visual information not conveyed by the audio. |
| 1.4.2 | Audio Control | A | Audio that plays automatically for more than 3 seconds can be paused, stopped, or muted independently. |
| 2.1.1 | Keyboard | A | All functionality is operable through a keyboard interface with no specific timing. |
| 2.2.2 | Pause, Stop, Hide | A | Moving, blinking, or auto-updating content lasting more than 5 seconds can be paused, stopped, or hidden. |
| 4.1.2 | Name, Role, Value | A | For all UI components, name, role, and value are programmatically determinable; states and changes are announced. |
References
- W3C WAI — Making Audio and Video Media Accessible
- MDN — <video> element
- MDN — <track> element
- MDN — WebVTT (caption format)
- Understanding 1.2.1 Audio-only and Video-only (Prerecorded)
- Understanding 1.2.2 Captions (Prerecorded)
- Understanding 1.2.3 Audio Description or Media Alternative (Prerecorded)
- Understanding 1.2.5 Audio Description (Prerecorded)
- Understanding 1.4.2 Audio Control
- Understanding 2.1.1 Keyboard
- Understanding 2.2.2 Pause, Stop, Hide
- Understanding 4.1.2 Name, Role, Value