Carousel
A slideshow built on a list. The server sends slides in a horizontally scrolling track with scroll snapping, dots as plain anchor links and hidden buttons; that already works everywhere. On init the dots become tabs, the slides become panels, the buttons appear and the track is driven by transforms: slide with a parallax caption, crossfade, or a cinema mode that slowly zooms the active media. Autoplay draws a progress bar, pauses on hover, focus and hidden tabs, and never starts when the reader prefers reduced motion.
<section class="iv-carousel" data-iv-component="carousel" aria-roledescription="carousel" aria-label="Sample work. The four projects below are made up for this demo.">
<div class="iv-carousel__viewport">
<ul class="iv-carousel__track">
<li class="iv-carousel__slide" id="cw-aurora">
<figure class="iv-carousel__media">
<svg role="img" aria-label="Abstract artwork: a green glow rising behind two long arcs on a dark green field." viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="cw-a1" x1="0" y1="0" x2="1600" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#094D63"/><stop offset=".6" stop-color="#04070F"/><stop offset="1" stop-color="#0C1330"/>
</linearGradient>
<radialGradient id="cw-a2" cx="420" cy="620" r="700" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#73DFFF" stop-opacity=".65"/><stop offset="1" stop-color="#73DFFF" stop-opacity="0"/>
</radialGradient>
</defs>
<rect width="1600" height="900" fill="url(#cw-a1)"/>
<rect width="1600" height="900" fill="url(#cw-a2)"/>
<circle cx="1230" cy="240" r="190" fill="#2266D8" fill-opacity=".38"/>
<path d="M-60 560C320 300 660 760 1660 340" fill="none" stroke="#66B1FF" stroke-opacity=".55" stroke-width="4"/>
<path d="M-60 660C360 430 720 880 1660 460" fill="none" stroke="#73DFFF" stroke-opacity=".3" stroke-width="10"/>
</svg>
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Case study</span>
<h3>Aurora energy dashboard</h3>
<p>A control room for a fictional grid operator, built with iVOLT tokens, layout primitives and no runtime dependencies.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cw-harbour">
<figure class="iv-carousel__media">
<svg role="img" aria-label="Abstract artwork: blue bands crossing a dark field with a soft green halo." viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="cw-b1" x1="1600" y1="0" x2="0" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0C1330"/><stop offset=".5" stop-color="#04070F"/><stop offset="1" stop-color="#171A45"/>
</linearGradient>
<radialGradient id="cw-b2" cx="1180" cy="300" r="640" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#2266D8" stop-opacity=".75"/><stop offset="1" stop-color="#2266D8" stop-opacity="0"/>
</radialGradient>
</defs>
<rect width="1600" height="900" fill="url(#cw-b1)"/>
<rect width="1600" height="900" fill="url(#cw-b2)"/>
<path d="M0 620 1600 380 1600 520 0 760Z" fill="#8B95FF" fill-opacity=".2"/>
<path d="M0 700 1600 460 1600 500 0 740Z" fill="#66B1FF" fill-opacity=".35"/>
<circle cx="360" cy="250" r="140" fill="#8B95FF" fill-opacity=".3"/>
</svg>
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Field report</span>
<h3>Harbour logistics board</h3>
<p>Sample data only: berths, tides and crane slots on one dense table that still reads on a phone.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cw-kit">
<figure class="iv-carousel__media">
<svg role="img" aria-label="Abstract artwork: concentric green rings over a deep carbon background." viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="cw-c1" x1="0" y1="900" x2="1600" y2="0" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#04070F"/><stop offset="1" stop-color="#172F7A"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#cw-c1)"/>
<circle cx="820" cy="470" r="420" fill="none" stroke="#66B1FF" stroke-opacity=".5" stroke-width="3"/>
<circle cx="820" cy="470" r="300" fill="none" stroke="#66B1FF" stroke-opacity=".35" stroke-width="6"/>
<circle cx="820" cy="470" r="170" fill="#66B1FF" fill-opacity=".22"/>
<path d="M-40 840C420 700 560 220 1640 120" fill="none" stroke="#66B1FF" stroke-opacity=".45" stroke-width="4"/>
</svg>
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Product</span>
<h3>Voltage design kit</h3>
<p>Every surface in this made-up kit is a token: change one value and the whole slideshow follows.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cw-tidal">
<figure class="iv-carousel__media">
<svg role="img" aria-label="Abstract artwork: a wide green wave breaking across a dark blue horizon." viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="cw-d1" x1="0" y1="0" x2="0" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0C1330"/><stop offset="1" stop-color="#0C1330"/>
</linearGradient>
<radialGradient id="cw-d2" cx="760" cy="880" r="760" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#8FE3FF" stop-opacity=".55"/><stop offset="1" stop-color="#8FE3FF" stop-opacity="0"/>
</radialGradient>
</defs>
<rect width="1600" height="900" fill="url(#cw-d1)"/>
<path d="M-40 500C400 340 700 700 1640 400L1640 900-40 900Z" fill="#2266D8" fill-opacity=".45"/>
<rect width="1600" height="900" fill="url(#cw-d2)"/>
<circle cx="1320" cy="180" r="110" fill="#FBBF24" fill-opacity=".3"/>
</svg>
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Research</span>
<h3>Tidal turbine telemetry</h3>
<p>Invented readings from an imaginary estuary, plotted with nothing but CSS gradients and inline SVG.</p>
</div>
</li>
</ul>
</div>
<nav class="iv-carousel__dots" aria-label="Slides">
<a href="#cw-aurora"><span class="iv-u-sr-only">Slide 1: Aurora energy dashboard</span></a>
<a href="#cw-harbour"><span class="iv-u-sr-only">Slide 2: Harbour logistics board</span></a>
<a href="#cw-kit"><span class="iv-u-sr-only">Slide 3: Voltage design kit</span></a>
<a href="#cw-tidal"><span class="iv-u-sr-only">Slide 4: Tidal turbine telemetry</span></a>
</nav>
<div class="iv-carousel__controls">
<button class="iv-button iv-carousel__prev" type="button" aria-label="Previous slide" hidden>←</button>
<button class="iv-button iv-carousel__next" type="button" aria-label="Next slide" hidden>→</button>
</div>
</section>Cinema effect with autoplay
data-iv-effect="cinema" crossfades the slides and adds a slow zoom on the active media while the caption rises. With data-iv-autoplay the component adds a large counter and a progress bar that fills over the interval; the play/pause button exposes its state with aria-pressed.
<section class="iv-carousel iv-carousel--contained" data-iv-component="carousel" data-iv-effect="cinema" data-iv-autoplay="6000" aria-roledescription="carousel" aria-label="Night shift. The three stories below are invented for this demo.">
<div class="iv-carousel__viewport">
<ul class="iv-carousel__track">
<li class="iv-carousel__slide" id="cc-observatory">
<figure class="iv-carousel__media">
<svg role="img" aria-label="Abstract artwork: a pale green dome of light rising over a dark ridge." viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="cc-a1" x1="0" y1="0" x2="0" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#04070F"/><stop offset="1" stop-color="#094D63"/>
</linearGradient>
<radialGradient id="cc-a2" cx="800" cy="900" r="820" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#73DFFF" stop-opacity=".7"/><stop offset="1" stop-color="#73DFFF" stop-opacity="0"/>
</radialGradient>
</defs>
<rect width="1600" height="900" fill="url(#cc-a1)"/>
<rect width="1600" height="900" fill="url(#cc-a2)"/>
<circle cx="1180" cy="200" r="90" fill="#66B1FF" fill-opacity=".55"/>
<path d="M-40 900C300 640 620 720 1640 420L1640 900Z" fill="#0C1330" fill-opacity=".9"/>
</svg>
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Chapter one</span>
<h3>The observatory</h3>
<p>A made-up night watch over an imaginary ridge, told in three slides that advance on their own every six seconds.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cc-signal">
<figure class="iv-carousel__media">
<svg role="img" aria-label="Abstract artwork: concentric blue rings spreading from a bright point." viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="cc-b1" x1="1600" y1="0" x2="0" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0C1330"/><stop offset="1" stop-color="#04070F"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#cc-b1)"/>
<circle cx="1100" cy="420" r="120" fill="#66B1FF" fill-opacity=".5"/>
<circle cx="1100" cy="420" r="260" fill="none" stroke="#2266D8" stroke-opacity=".7" stroke-width="6"/>
<circle cx="1100" cy="420" r="420" fill="none" stroke="#2266D8" stroke-opacity=".45" stroke-width="4"/>
<circle cx="1100" cy="420" r="600" fill="none" stroke="#8B95FF" stroke-opacity=".25" stroke-width="3"/>
</svg>
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Chapter two</span>
<h3>A signal at 03:40</h3>
<p>Fictional telemetry: the pan and zoom you see is CSS, driven by the same interval as the progress bar.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cc-dawn">
<figure class="iv-carousel__media">
<svg role="img" aria-label="Abstract artwork: a warm band of light breaking over layered green hills." viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice">
<defs>
<linearGradient id="cc-c1" x1="0" y1="0" x2="0" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#0F1D4D"/><stop offset=".55" stop-color="#172F7A"/><stop offset="1" stop-color="#04070F"/>
</linearGradient>
</defs>
<rect width="1600" height="900" fill="url(#cc-c1)"/>
<circle cx="420" cy="300" r="150" fill="#FBBF24" fill-opacity=".45"/>
<path d="M-40 620C380 480 700 700 1640 520L1640 900-40 900Z" fill="#0F1D4D" fill-opacity=".85"/>
<path d="M-40 760C420 640 780 840 1640 700L1640 900-40 900Z" fill="#04070F" fill-opacity=".9"/>
</svg>
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Chapter three</span>
<h3>Dawn over the valley</h3>
<p>Pointing at the slideshow, or moving focus into it, holds the rotation; the buttons stop it for good.</p>
</div>
</li>
</ul>
</div>
<nav class="iv-carousel__dots" aria-label="Slides">
<a href="#cc-observatory"><span class="iv-u-sr-only">Slide 1: The observatory</span></a>
<a href="#cc-signal"><span class="iv-u-sr-only">Slide 2: A signal at 03:40</span></a>
<a href="#cc-dawn"><span class="iv-u-sr-only">Slide 3: Dawn over the valley</span></a>
</nav>
<div class="iv-carousel__controls">
<button class="iv-button iv-carousel__prev" type="button" aria-label="Previous slide" hidden>←</button>
<button class="iv-button iv-carousel__next" type="button" aria-label="Next slide" hidden>→</button>
<button class="iv-button iv-carousel__toggle" type="button" hidden>Pause</button>
</div>
</section>// data-iv-component="carousel"
{
effect: "cinema",
autoplay: 6000,
}Thumbnails
Give the dots the iv-carousel__dots--thumbs class and put a small image in each anchor: they become thumbnail tabs. This example uses the fade effect.
<section class="iv-carousel" data-iv-component="carousel" data-iv-effect="fade" aria-roledescription="carousel" aria-label="Field guides. The four volumes below are invented for this demo.">
<div class="iv-carousel__viewport">
<ul class="iv-carousel__track">
<li class="iv-carousel__slide" id="cf-atlas">
<figure class="iv-carousel__media">
<img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201600%20900'%20preserveAspectRatio='xMidYMid%20slice'%3E%3Cdefs%3E%3ClinearGradient%20id='g'%20x1='0'%20y1='0'%20x2='1600'%20y2='900'%20gradientUnits='userSpaceOnUse'%3E%3Cstop%20offset='0'%20stop-color='%2304301F'/%3E%3Cstop%20offset='1'%20stop-color='%23081310'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1600'%20height='900'%20fill='url%28%23g%29'/%3E%3Cpath%20d='M520%20-40%20980%20-40%20700%20940%20240%20940Z'%20fill='%2329F59A'%20fill-opacity='.28'/%3E%3Ccircle%20cx='1220'%20cy='300'%20r='240'%20fill='%231D5FB8'%20fill-opacity='.45'/%3E%3C/svg%3E" alt="Abstract artwork: a tall green beam of light crossing a dark carbon field.">
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Volume one</span>
<h3>Atlas of quiet places</h3>
<p>A made-up field guide. Each cover is an inline SVG served as a data URI, so nothing is fetched from the network.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cf-currents">
<figure class="iv-carousel__media">
<img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201600%20900'%20preserveAspectRatio='xMidYMid%20slice'%3E%3Cdefs%3E%3ClinearGradient%20id='h'%20x1='1600'%20y1='0'%20x2='0'%20y2='900'%20gradientUnits='userSpaceOnUse'%3E%3Cstop%20offset='0'%20stop-color='%2312201A'/%3E%3Cstop%20offset='1'%20stop-color='%2304301F'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1600'%20height='900'%20fill='url%28%23h%29'/%3E%3Cpath%20d='M-40%20560C420%20380%20780%20720%201640%20460L1640%20900-40%20900Z'%20fill='%231D5FB8'%20fill-opacity='.5'/%3E%3Cpath%20d='M-40%20700C460%20560%20820%20840%201640%20660L1640%20900-40%20900Z'%20fill='%2329F59A'%20fill-opacity='.3'/%3E%3C/svg%3E" alt="Abstract artwork: two wide blue currents sweeping under a green horizon.">
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Volume two</span>
<h3>Currents and crossings</h3>
<p>Invented crossings, plotted as gradients. The thumbnails below are the tab list of this carousel.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cf-signal">
<figure class="iv-carousel__media">
<img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201600%20900'%20preserveAspectRatio='xMidYMid%20slice'%3E%3Crect%20width='1600'%20height='900'%20fill='%23081310'/%3E%3Ccircle%20cx='800'%20cy='450'%20r='330'%20fill='none'%20stroke='%2329F59A'%20stroke-opacity='.55'%20stroke-width='10'/%3E%3Ccircle%20cx='800'%20cy='450'%20r='180'%20fill='%2329F59A'%20fill-opacity='.25'/%3E%3Ccircle%20cx='300'%20cy='740'%20r='200'%20fill='%231D5FB8'%20fill-opacity='.4'/%3E%3C/svg%3E" alt="Abstract artwork: a bright green ring glowing over a deep carbon background.">
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Volume three</span>
<h3>Signals after midnight</h3>
<p>Fictional readings. Switching tabs cross-fades the covers: no slide travels sideways in this variant.</p>
</div>
</li>
<li class="iv-carousel__slide" id="cf-harvest">
<figure class="iv-carousel__media">
<img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%201600%20900'%20preserveAspectRatio='xMidYMid%20slice'%3E%3Cdefs%3E%3ClinearGradient%20id='j'%20x1='0'%20y1='900'%20x2='1600'%20y2='0'%20gradientUnits='userSpaceOnUse'%3E%3Cstop%20offset='0'%20stop-color='%23081310'/%3E%3Cstop%20offset='1'%20stop-color='%230A6A43'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1600'%20height='900'%20fill='url%28%23j%29'/%3E%3Ccircle%20cx='1120'%20cy='260'%20r='170'%20fill='%23FFB84D'%20fill-opacity='.4'/%3E%3Ccircle%20cx='520'%20cy='620'%20r='260'%20fill='%2329F59A'%20fill-opacity='.25'/%3E%3Cpath%20d='M-40%20780C400%20700%20900%20860%201640%20740L1640%20900-40%20900Z'%20fill='%2304301F'%20fill-opacity='.9'/%3E%3C/svg%3E" alt="Abstract artwork: warm amber circles scattered over layered green bands.">
</figure>
<span class="iv-carousel__scrim" aria-hidden="true"></span>
<div class="iv-carousel__caption">
<span class="iv-badge iv-badge--primary iv-badge--solid">Volume four</span>
<h3>Harvest of small things</h3>
<p>Sample copy only. Every colour here comes from the iVOLT palette tokens, light theme and dark theme alike.</p>
</div>
</li>
</ul>
</div>
<nav class="iv-carousel__dots iv-carousel__dots--thumbs" aria-label="Slides">
<a href="#cf-atlas">
<svg aria-hidden="true" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"><rect width='1600' height='900' fill='#094D63'/><path d='M520 0 980 0 700 900 240 900Z' fill='#73DFFF' fill-opacity='.5'/><circle cx='1220' cy='300' r='240' fill='#2266D8' fill-opacity='.6'/></svg>
<span class="iv-u-sr-only">Slide 1: Atlas of quiet places</span>
</a>
<a href="#cf-currents">
<svg aria-hidden="true" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"><rect width='1600' height='900' fill='#0C1330'/><path d='M-40 560C420 380 780 720 1640 460L1640 900-40 900Z' fill='#2266D8' fill-opacity='.7'/><path d='M-40 700C460 560 820 840 1640 660L1640 900-40 900Z' fill='#8B95FF' fill-opacity='.5'/></svg>
<span class="iv-u-sr-only">Slide 2: Currents and crossings</span>
</a>
<a href="#cf-signal">
<svg aria-hidden="true" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"><rect width='1600' height='900' fill='#04070F'/><circle cx='800' cy='450' r='330' fill='none' stroke='#66B1FF' stroke-opacity='.7' stroke-width='24'/><circle cx='800' cy='450' r='180' fill='#66B1FF' fill-opacity='.4'/></svg>
<span class="iv-u-sr-only">Slide 3: Signals after midnight</span>
</a>
<a href="#cf-harvest">
<svg aria-hidden="true" viewBox="0 0 1600 900" preserveAspectRatio="xMidYMid slice"><rect width='1600' height='900' fill='#1C2544'/><circle cx='1120' cy='260' r='170' fill='#FBBF24' fill-opacity='.6'/><circle cx='520' cy='620' r='260' fill='#8FE3FF' fill-opacity='.45'/></svg>
<span class="iv-u-sr-only">Slide 4: Harvest of small things</span>
</a>
</nav>
<div class="iv-carousel__controls">
<button class="iv-button iv-carousel__prev" type="button" aria-label="Previous volume" hidden>←</button>
<button class="iv-button iv-carousel__next" type="button" aria-label="Next volume" hidden>→</button>
</div>
</section>// data-iv-component="carousel"
{
effect: "fade",
}With photographs
Real images from Unsplash (credited in the captions), the cinema effect and a seven-second autoplay. The images live with the documentation, not in the package.
<section class="iv-carousel" data-iv-component="carousel" data-iv-effect="cinema" data-iv-autoplay="7000" aria-roledescription="carousel" aria-label="Photographs from Unsplash, used as a demo">
<div class="iv-carousel__viewport">
<ul class="iv-carousel__track">
<li class="iv-carousel__slide" id="cp-ridge">
<figure class="iv-carousel__media"><img src="/photos/p1015.jpg" width="1280" height="800" alt="A river winding between forested mountains under a pale sky" loading="lazy"></figure>
<div class="iv-carousel__scrim"></div>
<div class="iv-carousel__caption"><span class="iv-badge iv-badge--primary">Landscape</span><h3>The valley opens</h3><p>Photograph by Alexey Topolyanskiy on Unsplash. Cinema effect: a slow zoom on the active image, captions rising in.</p></div>
</li>
<li class="iv-carousel__slide" id="cp-shore">
<figure class="iv-carousel__media"><img src="/photos/p1036.jpg" width="1280" height="800" alt="Snow-covered peaks above a glacial lake" loading="lazy"></figure>
<div class="iv-carousel__scrim"></div>
<div class="iv-carousel__caption"><span class="iv-badge iv-badge--primary">Alpine</span><h3>Above the lake</h3><p>Photograph by Wolfgang Lutz on Unsplash. Autoplay pauses while you hover or focus the carousel.</p></div>
</li>
<li class="iv-carousel__slide" id="cp-sea">
<figure class="iv-carousel__media"><img src="/photos/p1050.jpg" width="1280" height="800" alt="Sea stacks rising over turquoise water" loading="lazy"></figure>
<div class="iv-carousel__scrim"></div>
<div class="iv-carousel__caption"><span class="iv-badge iv-badge--primary">Coast</span><h3>Out along the pier</h3><p>Photograph by Joseph Barrientos on Unsplash. Every image carries real alt text; the scrim keeps the caption readable.</p></div>
</li>
<li class="iv-carousel__slide" id="cp-forest">
<figure class="iv-carousel__media"><img src="/photos/p1080.jpg" width="1280" height="800" alt="Crates of strawberries on a market stall" loading="lazy"></figure>
<div class="iv-carousel__scrim"></div>
<div class="iv-carousel__caption"><span class="iv-badge iv-badge--primary">Forest</span><h3>Looking up</h3><p>Photograph by veeterzy on Unsplash. Under reduced motion the crossfade shortens and the zoom stops.</p></div>
</li>
</ul>
</div>
<nav class="iv-carousel__dots" aria-label="Slides">
<a href="#cp-ridge"><span class="iv-u-sr-only">The valley opens</span></a>
<a href="#cp-shore"><span class="iv-u-sr-only">Above the lake</span></a>
<a href="#cp-sea"><span class="iv-u-sr-only">Out along the pier</span></a>
<a href="#cp-forest"><span class="iv-u-sr-only">Looking up</span></a>
</nav>
<div class="iv-carousel__controls">
<button class="iv-button iv-carousel__prev" type="button" hidden><span class="iv-u-sr-only">Previous slide</span><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 5l-7 7 7 7"/></svg></button>
<button class="iv-button iv-carousel__next" type="button" hidden><span class="iv-u-sr-only">Next slide</span><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M9 5l7 7-7 7"/></svg></button>
<button class="iv-button iv-carousel__toggle" type="button" hidden>Pause</button>
</div>
</section>// data-iv-component="carousel"
{
effect: "cinema",
autoplay: 7000,
}Options
| Option | Attribute | Default | Effect |
|---|---|---|---|
effect | data-iv-effect | slide | slide, fade or cinema. |
autoplay | data-iv-autoplay | 0 | Milliseconds between slides; 0 disables autoplay. Never starts under reduced motion. |
loop | data-iv-loop | true | Wrap around at both ends. |
pauseOnHover | data-iv-pause-on-hover | true | Pause autoplay while the pointer is over the carousel. |
swipe | data-iv-swipe | true | Pointer drag changes the slide (40 px threshold). |
duration | data-iv-duration | 600 | Transition length in milliseconds. |
pauseText, playText | data-iv-pause-text, data-iv-play-text | Pause, Play | Labels of the toggle button. |
Methods and events
next(), prev(), goTo(index), play(), pause(), destroy(); read index, count, isPlaying and slides. Events on the root element: iv:change (cancelable, detail.index, previousIndex, reason) then iv:changed; iv:play and iv:pause with a reason.
Keyboard, gestures and assistive technology
Left and Right move between slides from the tabs or from the viewport, Home and End jump, Enter and Space activate a tab. Dragging with a pointer changes the slide. The markup follows the tabbed carousel pattern: each slide is a panel labelled "n of N", non-visible slides are inert in the fade and cinema effects, and the viewport is a live region only while autoplay is paused, so the reader is not interrupted by every change.
Without JavaScript
The track scrolls horizontally and snaps to each slide, the dots are anchor links that scroll the matching slide into view, and the buttons stay hidden. Captions sit on a gradient scrim so the text stays readable on any media.
Common mistakes
- Media without
alttext or anaria-label: every slide needs a name. - Autoplay on a carousel with links and forms inside: readers lose their place. Prefer manual navigation or a long interval.
- Using the carousel for essential content: nothing important should only exist on slide four.
Class index
Parts and modifiers of this family that the examples above do not show. The full list per stylesheet lives in the reference.
| Class | What it does |
|---|---|
iv-carousel__scrim | Gradient laid over the slide so a caption stays legible on any photograph; generated by init when the carousel has captions. |