A dependency-free, zero-JavaScript carousel system. Everything below runs on
:checked state changes and CSS animations only — no scripts, no
build step. One stylesheet (cssvars-carousel-final.css) covers
every variant on this page.
Radio button name grouping is global to the whole document, not
scoped to whatever container they sit in. Every carousel below uses its own
unique prefix on its name/id values (e.g.
dots-, xfade-, link-) — that's the only
thing you need to change per instance to safely repeat any of these on the
same page. Class names (.carousel-fixed, radio-1,
etc.) are always safe to reuse as-is.
.carousel-fixed, classic dotsManual click only. Uses a CSS variable + calc() instead of
hardcoded per-slide percentages, so supporting more slides is a one-line
addition (see the CSS comments) rather than a math redo.
carousel-fixed → the outer wrapper <div>slides → the <ul> holding the slidesslidesNavigation → the <div> wrapping the dot <label>s<li>s, the radios, the labels) needs no class at all — just correct id/for/name pairing..slidesNavigation-flexEach link is a <label> (invisible, just the click target)
wrapping a <div> you fully design — any content, any
styling. The wrapper itself carries no position, so you place and lay it out
however you want with ordinary utility classes.
carousel-fixed → the outer wrapper <div>slides → the <ul>slidesNavigation-flex → the <div> wrapping the <label> links, in place of slidesNavigation<label>, the <div> is yours — style it however you want (below it just uses the framework's own button class)Additional classes on the slidesNavigation-flex wrapper for this
positioning: position-absolute, top-0,
bottom-0, right-1 (span the full height near the
right edge), flex-column + justify-content-center
(center the buttons vertically, no transform needed), gap-1,
z-floating. All existing cssvars utilities — nothing new to
learn.
.carousel-crossfade / .zoomOpt-in add-on classes, same mechanism underneath. Durations ride on
--duration-slow/--easing, so
prefers-reduced-motion is respected automatically.
carousel-crossfade → added alongside carousel-fixed on the same wrapper <div> (i.e. class="carousel-fixed carousel-crossfade")zoom → added on top of that, same wrapper, for the Ken Burns version (class="carousel-fixed carousel-crossfade zoom")slide-media → required on the content <div> inside each <li> — this is what the zoom animation actually targets, so captions/text on top of it stay stillA <label for="..."> works anywhere, including inside a
slide's own content. Prev/Next needs one pair per slide, each pointing at
its actual neighbor (wraparound included) — CSS can't compute
"current + 1" dynamically.
carousel-fixed + slides → same as the base carousel, no changeslide-prev → on a <label> placed inside a slide's <li>, pointing (for) at the previous slide's radioslide-next → same idea, pointing at the next slide's radioslide-cta → on any <label> inside a slide's content that should jump to a specific other slide (combine with button for the framework's own button look, as below).carousel-autoplayNo radios, no clicking — a looping @keyframes animation
advances the slides on its own. Hover or focus pauses it (fixed: both
the animation-name and play-state now use longhand properties, so the
per-count classes can never silently reset play-state back to
"running").
carousel-autoplay → the outer wrapper <div>slides-2 slides-3 slides-4 slides-5 slides-6 → same wrapper, alongside carousel-autoplay — picks which pre-built timing/keyframes to use for that slide countslides → the <ul>, same as always.carousel-autoplay-linkedDots track the current slide automatically (synced @keyframes
per dot, not :checked). Click one to jump there — the cycle
keeps going automatically from that point, rather than freezing.
carousel-autoplay-linked → the outer wrapper <div> (built for 4 slides — see the CSS comments for extending it)slides → the <ul>slidesNavigation → the <div> wrapping the dot <label>s — same class as the classic static dots, no separate name for this variant| Class | What it does | Trade-off |
|---|---|---|
.carousel-fixed | Manual, click-driven | No autoplay |
.slidesNavigation | Classic dot links | Fixed dot design |
.slidesNavigation-flex | Fully custom div-based links | None — most flexible option |
.carousel-crossfade | Fade instead of slide | None |
.zoom | Ken Burns zoom (needs .slide-media wrapper) | Requires .carousel-crossfade |
.slide-prev / .slide-next | Per-slide prev/next arrows | One pair per slide, authored manually |
.carousel-autoplay | Automatic, no clicking | Can't also click-to-jump |
.carousel-autoplay-linked | Automatic + clickable, resumes on click | O(N²) CSS size — best for ≤4-6 slides |
Built with love by Kim Majali, EITO team, and contributors.