Skip to content

Carousel

<caos-carousel>

a run of pictures shown one at a time, moved by hand or on a timer, that holds still for a reader who asked for less motion

May be placed on an app’s home page and a page inside an app.

Name Attribute Description Type Default Required
images property only The images, as { src, alt, heading?, description?, href? } objects, in the order they are shown. src is the picture and alt is what it shows for somebody who cannot see it — an empty alt marks a picture that carries no meaning of its own. A heading and a description are drawn over the picture when they are given, and an href makes the whole slide a link. An entry with no src is dropped. json none declared Optional
autoplay autoplay, markup only Moves to the next image on a timer. Off unless set, and it never starts for a reader whose system asks for reduced motion, however this is set. The timer runs only while the carousel is on the page and there is more than one image to move between. boolean false Optional
interval interval, markup only How long each image holds before autoplay moves on, in milliseconds. Only read when autoplay is set. A value that is not a positive number leaves the carousel still rather than moving at some invented speed. number 5000 Optional
noPauseOnHover no-pause-on-hover, markup only Keeps autoplay running while a reader is engaged. Left unset, pointing at the carousel or moving focus into it stops the timer, and leaving starts it again, because a gallery that keeps moving under somebody reading it is the complaint this exists to answer. Declared as a negative, like noBorder and noIcon, because a page writes a yes/no as present-or-absent and a positive input that was on by default would have no reachable way to turn it off. boolean false Optional
label label, markup only What a screen reader calls this carousel, for a page holding more than one. Left unset it is announced as “Carousel”, which is enough when there is only the one. text none declared Optional
Name When it fires What it carries
caos-carousel-change The image shown has changed — a previous or next press, an arrow key, a dot, autoplay moving on, or a goTo call. Not raised when the carousel is first drawn, and not raised when a move lands on the image already shown. { index, count } — the image now shown, counting from zero, and how many there are.

Not documented yet — this piece has not said.

Design token What it controls
--caos-color-surface The ground behind a picture that has not loaded, and the caption band.
--caos-color-surface-2 The viewport behind the images.
--caos-color-border The edge of the previous and next controls and of a dot.
--caos-color-text The heading on a slide and the glyph on a control.
--caos-color-text-muted The description under a heading.
--caos-color-accent The dot marking the image being shown.
--caos-font The typeface of the headings and descriptions.
--caos-space-1 The padding inside a previous or next control.
--caos-space-2 The gap between the viewport and the controls, and between the dots.
--caos-space-3 The padding inside the caption band.
--caos-radius The corners of the viewport.
--caos-radius-pill The shape of the previous and next controls and of a dot.
--caos-state-hover-bg A previous or next control under the pointer.
--caos-focus-ring The ring drawn on a control reached by keyboard.
--caos-duration-base How long one image takes to give way to the next.
--caos-ease-standard The curve of that change.
Name Description Arguments
next() Move forward one image, wrapping from the last to the first. Returns false when nothing changed. takes none
previous() Move back one image, wrapping from the first to the last. Returns false when nothing changed. takes none
goTo() Show a particular image. Returns false when nothing changed — the index is outside the list, or it is the image already shown. index: number
play() Start the autoplay timer, as setting the attribute does. It does nothing for a reader who has asked for reduced motion, which is the one thing no caller can override. takes none
pause() Stop the autoplay timer, leaving the image that is showing on screen. takes none
Name Type What it tells you
index number The image shown now, counting from zero.
count number How many images the carousel is holding.
playing boolean Whether the autoplay timer is running now. False while it is paused for a hover, for focus, or for a reduced-motion preference, so it answers “is this moving” rather than “was it asked to”.
Part Which piece of it When it is there
::part(carousel) the whole gallery, viewport and controls together Always
::part(viewport) the window the images are shown in Always
::part(slide) one image and its caption Always
::part(image) the picture itself Always
::part(caption) the band over a picture holding its heading and description the image carries a heading or a description
::part(heading) the line of display text on a slide the image carries a heading
::part(description) the sentence under a heading the image carries a description
::part(controls) the row holding the previous and next controls and the dots Always
::part(previous) the control that goes back one image Always
::part(next) the control that goes forward one image Always
::part(dots) the run of marks, one per image Always
::part(dot) one mark, which moves to the image it names when pressed Always

A short run of pictures that lead a page — four or five, each worth a moment on its own, where a reader is invited rather than asked to compare. If somebody needs to see them together, or to find a particular one, a grid is the honest answer: a carousel hides everything except the slide showing.

  • CardGrid — The reader needs to see the set at once and compare it, or to pick a particular one out of it.
  • TabStrip — There are a few named faces of one subject and the reader chooses between them, with nothing moving on its own.

The carousel is a region announced as a carousel, and each slide is a group labelled with its position, so a screen reader says which of how many is showing. The slides not showing are hidden rather than merely out of sight, so they are out of the tab order and the accessibility tree and a reader never tabs into a picture nobody can see. Previous and next are real buttons, each dot is a button naming the image it goes to, and Arrow Left and Arrow Right move between images while Home and End go to the first and the last. A polite status region reports the new position on a move somebody made, and is silenced while autoplay is running so a reader is not interrupted every few seconds by motion they did not ask for. Reduced motion is honoured in behaviour and not only in paint: autoplay does not start, the gallery rests on the first image, and moving by hand still works. What is left to the author: an alt for every picture that carries meaning, and an empty one for every picture that does not.

The ordinary case: three pictures, moved by the controls or the arrow keys. Nothing moves on its own, because autoplay was not asked for.

{
"id": "example",
"section": "A run of pictures",
"columns": 1,
"items": [
{
"id": "carousel_1",
"type": "component",
"key": "carousel",
"inputs": {
"label": "Platform highlights",
"images": [
{
"src": "https://images.example.com/workspace.jpg",
"alt": "A workspace with several records open side by side"
},
{
"src": "https://images.example.com/builder.jpg",
"alt": "A page being assembled from the component palette"
},
{
"src": "https://images.example.com/community.jpg",
"alt": "People at a community meet-up around a long table"
}
]
}
}
]
}
<caos-carousel id="carousel1" label="Platform highlights"></caos-carousel>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const carousel1 = document.getElementById('carousel1');
carousel1.images = [
{
"src": "https://images.example.com/workspace.jpg",
"alt": "A workspace with several records open side by side"
},
{
"src": "https://images.example.com/builder.jpg",
"alt": "A page being assembled from the component palette"
},
{
"src": "https://images.example.com/community.jpg",
"alt": "People at a community meet-up around a long table"
}
];

Autoplay set with a four-second hold. Pointing at it or moving focus into it stops the timer, and leaving starts it again.

{
"id": "example",
"section": "Moving on a timer",
"columns": 1,
"items": [
{
"id": "carousel_1",
"type": "component",
"key": "carousel",
"inputs": {
"label": "What the platform does",
"autoplay": true,
"interval": 4000,
"images": [
{
"src": "https://images.example.com/workspace.jpg",
"alt": "A workspace with several records open side by side"
},
{
"src": "https://images.example.com/builder.jpg",
"alt": "A page being assembled from the component palette"
},
{
"src": "https://images.example.com/academy.jpg",
"alt": "A lesson page open at a short exercise"
}
]
}
}
]
}
<caos-carousel id="carousel1" label="What the platform does" autoplay interval="4000"></caos-carousel>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const carousel1 = document.getElementById('carousel1');
carousel1.images = [
{
"src": "https://images.example.com/workspace.jpg",
"alt": "A workspace with several records open side by side"
},
{
"src": "https://images.example.com/builder.jpg",
"alt": "A page being assembled from the component palette"
},
{
"src": "https://images.example.com/academy.jpg",
"alt": "A lesson page open at a short exercise"
}
];

The same element under a reduced-motion preference — the timer never starts and the gallery rests on the first picture. Turn the setting on and this is what the example above becomes.

{
"id": "example",
"section": "The same gallery, reduced motion",
"columns": 1,
"items": [
{
"id": "carousel_1",
"type": "component",
"key": "carousel",
"inputs": {
"label": "What the platform does",
"autoplay": true,
"interval": 4000,
"images": [
{
"src": "https://images.example.com/workspace.jpg",
"alt": "A workspace with several records open side by side"
},
{
"src": "https://images.example.com/builder.jpg",
"alt": "A page being assembled from the component palette"
},
{
"src": "https://images.example.com/academy.jpg",
"alt": "A lesson page open at a short exercise"
}
]
}
}
]
}
<caos-carousel id="carousel1" label="What the platform does" autoplay interval="4000"></caos-carousel>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const carousel1 = document.getElementById('carousel1');
carousel1.images = [
{
"src": "https://images.example.com/workspace.jpg",
"alt": "A workspace with several records open side by side"
},
{
"src": "https://images.example.com/builder.jpg",
"alt": "A page being assembled from the component palette"
},
{
"src": "https://images.example.com/academy.jpg",
"alt": "A lesson page open at a short exercise"
}
];

Each picture carrying a heading, a sentence under it, and a link, so a slide leads somewhere instead of only being looked at.

{
"id": "example",
"section": "Headings, descriptions and links",
"columns": 1,
"items": [
{
"id": "carousel_1",
"type": "component",
"key": "carousel",
"inputs": {
"label": "Where to start",
"images": [
{
"src": "https://images.example.com/academy.jpg",
"alt": "A lesson page open at a short exercise",
"heading": "Learn the platform",
"description": "Short lessons that build one working app end to end.",
"href": "/academy"
},
{
"src": "https://images.example.com/community.jpg",
"alt": "People at a community meet-up around a long table",
"heading": "Meet the community",
"description": "Questions answered by the people who build on this every day.",
"href": "/community"
},
{
"src": "https://images.example.com/careers.jpg",
"alt": "Two colleagues talking at a desk by a window",
"heading": "Work with us",
"description": "The roles open right now, and what each team is building.",
"href": "/careers"
}
]
}
}
]
}
<caos-carousel id="carousel1" label="Where to start"></caos-carousel>
// What an attribute cannot hold, set as a property — the same values the preview is drawn with.
const carousel1 = document.getElementById('carousel1');
carousel1.images = [
{
"src": "https://images.example.com/academy.jpg",
"alt": "A lesson page open at a short exercise",
"heading": "Learn the platform",
"description": "Short lessons that build one working app end to end.",
"href": "/academy"
},
{
"src": "https://images.example.com/community.jpg",
"alt": "People at a community meet-up around a long table",
"heading": "Meet the community",
"description": "Questions answered by the people who build on this every day.",
"href": "/community"
},
{
"src": "https://images.example.com/careers.jpg",
"alt": "Two colleagues talking at a desk by a window",
"heading": "Work with us",
"description": "The roles open right now, and what each team is building.",
"href": "/careers"
}
];