Exhibit 15 of 17
A slideshow that plays itself
It advances on its own every four seconds, stops while you hover it or use its buttons, and stays put if you pick a slide or press Pause.
How it works
The strip of slides moves with one @keyframes that holds each slide, then slides on. Radio buttons pick: Play (checked to start with) runs the animation; a number stops it and translates the strip to that slide. A Pause checkbox, hovering the slides, or keyboard focus on the buttons (:has(.pick:focus-visible)) sets animation-play-state: paused.
The key CSS
Cut from this exhibit’s stylesheet as it is served.
@keyframes slides {
0%, 20% { translate: 0; }
25%, 45% { translate: -25%; }
50%, 70% { translate: -50%; }
75%, 95% { translate: -75%; }
100% { translate: 0; }
}
/* Play: the animation is the slideshow */
.x-slideshow #sl-play:checked ~ .frame .strip { animation: slides 16s ease-in-out infinite; }
/* …held still by a hover, keyboard focus on its controls, or the Pause box */
.x-slideshow .frame:hover .strip,
.x-slideshow .show:has(.pick:focus-visible) .strip,
.x-slideshow #sl-pause:checked ~ .frame .strip { animation-play-state: paused; }
/* a numbered radio stops the animation and shows its slide */
.x-slideshow #sl-2:checked ~ .frame .strip { translate: -25%; }
.x-slideshow #sl-3:checked ~ .frame .strip { translate: -50%; }
.x-slideshow #sl-4:checked ~ .frame .strip { translate: -75%; }
/* reduced motion: never moves on its own */
@media (prefers-reduced-motion: reduce) {
.x-slideshow #sl-play:checked ~ .frame .strip { animation: none; }
.x-slideshow .play, .x-slideshow .pause { display: none; }
}
Accessibility
Auto-advancing content needs a way to stop it (WCAG 2.2.2): that is the Pause box, and under reduced motion it never moves at all. The picks are labelled radios. Because the animation, not a script, chooses the slide, nothing tells a screen reader which slide is showing while it plays.
Browser support
:checked + ~Works in this browser.Not in this browser: Nothing to fall back from; every browser has had it for years. Checked 2026-10-14: Chromium 149 yes, Firefox 141 yes.:has()Works in this browser.Not in this browser: Without :has() it can’t work; the page says so instead of half-working. Checked 2026-10-14: Chromium 149 yes, Firefox 141 yes.
