Video
A figure whose media is a muted, looping clip with a play and pause button. It plays while on screen and never autoplays for people who prefer reduced motion.
- CSS
css/components/video.css- JS
js/components/video.js
01 — Example
Clip
Replace the artwork with your clip’s <source>. The poster frame shows until it plays.
02 — Usage
Use it for
- Short silent loops: a motion reel, a product in use.
Avoid
- Video with sound or speech. Use a player with controls and captions.
- Several loops playing at once in view.
03 — Accessibility
Notes
- The button’s label follows the state: “Play video” or “Pause video”. Once paused by hand, it stays paused.
- It pauses when scrolled away and never autoplays with reduced motion.
04 — Without Jewel’s JS
What the script does
The script plays the muted clip while it’s on screen, pauses it out of view, never autoplays under reduced motion, and keeps the button in step. The CSS reads only the markup below, so a framework can set it itself and leave out video.js and data-component.
| State | Set this | Notes |
|---|---|---|
| Playing | data-state="playing" on .video | Hides .icon-play, so the pause icon shows. |
| Paused | data-state="paused" on .video | Hides .icon-pause. Always set one of the two, or both icons show. |
| Button label | aria-label="Pause video" while playing, "Play video" while paused | On .video__control. |
| Clip | muted, playsinline and loop on the <video>, and no autoplay | The script sets muted and playsinline and removes autoplay. loop comes from the markup. |
Events and keyboard
- Set
data-statefrom the video’splayandpauseevents, so it stays right however playback changes. - Play when at least 40% of it is in view and pause when it leaves (the script uses an
IntersectionObserver). Don’t autoplay underprefers-reduced-motion, and pause if it turns on. - Once someone pauses it by hand, don’t start it again on scroll.