Carousel
A horizontal, scroll-snap carousel container that lays out its
mdc-carousel-item children in large / medium / small widths.
The carousel is not part of @material/web; it mirrors the Jetpack Compose
Material 3 carousel (HorizontalMultiBrowseCarousel /
HorizontalUncontainedCarousel). For a horizontal carousel the three item
sizes differ only in width and corner roundness — every cell shares one
height and one interaction model.
Elements
| Element | Role |
|---|---|
mdc-carousel |
The container — owns layout, scroll-snap, focus |
mdc-carousel-item |
A sized cell; declares size, tracks active |
Usage
<mdc-carousel>
<mdc-carousel-item size="large">…</mdc-carousel-item>
<mdc-carousel-item size="medium">…</mdc-carousel-item>
<mdc-carousel-item size="small">…</mdc-carousel-item>
<mdc-carousel-item size="large">…</mdc-carousel-item>
</mdc-carousel>
Sizing
Item widths derive from preferred-item-width (default 186px):
| Size | Width | Corner roundness |
|---|---|---|
large |
min(preferred-item-width, container width) |
28px |
medium |
(large + small) / 2 |
20px |
small |
clamp(large / 3, 40px, 56px) |
12px |
Every value is overridable through the --mdc-carousel-* CSS custom
properties below. Widths are recomputed when the container resizes.
Variants
multi-browse(default) — the row mixes large / medium / small items. Items snap to the leading keyline and the row clips at the container edge.uncontained— all items share one width and the row scrolls freely (no snap), with the trailing item peeking at the edge.
Properties
mdc-carousel
| Property | Attribute | Type | Default |
|---|---|---|---|
variant |
variant |
'multi-browse' | 'uncontained' |
'multi-browse' |
preferredItemWidth |
preferred-item-width |
number |
186 |
activeIndex |
(read only) | number |
-1 |
mdc-carousel-item
| Property | Attribute | Type | Default |
|---|---|---|---|
size |
size |
'large' | 'medium' | 'small' |
'medium' |
active |
active |
boolean |
false |
index |
index |
number |
0 |
Events
| Event | Detail | Description |
|---|---|---|
carousel-active-change |
{ item, index } |
Fired when the focal (leading) item changes. |
Methods
scrollToItem(index)— scrolls the item atindexto the leading keyline (smooth). Also driven by←/→/Home/Endwhen the carousel is focused (tabindex="0").
CSS custom properties
| Property | Default |
|---|---|
--mdc-carousel-small-item-width |
computed |
--mdc-carousel-medium-item-width |
computed |
--mdc-carousel-large-item-width |
computed |
--mdc-carousel-*-item-shape-start-start |
28px / 20px / 12px |
--mdc-carousel-*-item-shape-start-end |
28px / 20px / 12px |
--mdc-carousel-*-item-shape-end-start |
28px / 20px / 12px |
--mdc-carousel-*-item-shape-end-end |
28px / 20px / 12px |
--mdc-carousel-item-spacing |
8px |
--mdc-carousel-item-height |
auto (stretched to tallest) |
--mdc-carousel-container-padding-block-start |
8px |
--mdc-carousel-container-padding-block-end |
8px |
--mdc-carousel-container-padding-inline-start |
16px |
--mdc-carousel-container-padding-inline-end |
16px |
* in the shape rows stands for small / medium / large (the item size);
the per-size defaults are the extra-large (28px), large-increased (20px)
and medium (12px) MD3 corners respectively.
Size
Code
<style>
.cds-card {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
height: 180px;
padding: 8px;
font: 500 14px/20px Roboto, system-ui, sans-serif;
color: var(--md-sys-color-on-surface, #1d1b20);
}
.cds-a { background: var(--md-sys-color-surface-container-high, #e6e0e9); }
.cds-b { background: var(--md-sys-color-secondary-container, #e8def8); }
.cds-c { background: var(--md-sys-color-tertiary-container, #ffd8e4); }
</style>
<!-- The three sizes differ only in width and corner roundness; height is shared -->
<mdc-carousel aria-label="Carousel item sizes">
<mdc-carousel-item size="large"><div class="cds-card cds-a">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cds-card cds-b">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cds-card cds-c">Small</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cds-card cds-c">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cds-card cds-a">Small</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cds-card cds-b">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cds-card cds-a">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cds-card cds-b">Small</div></mdc-carousel-item>
</mdc-carousel>Preferred Item Width
Code
<style>
.cdp-card {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
height: 180px;
padding: 8px;
font: 500 14px/20px Roboto, system-ui, sans-serif;
color: var(--md-sys-color-on-surface, #1d1b20);
}
.cdp-a { background: var(--md-sys-color-surface-container-high, #e6e0e9); }
.cdp-b { background: var(--md-sys-color-secondary-container, #e8def8); }
.cdp-c { background: var(--md-sys-color-tertiary-container, #ffd8e4); }
</style>
<!-- preferred-item-width tunes the large item; small ≈ ⅓ of large (40–56px), medium the average -->
<mdc-carousel preferred-item-width="120" aria-label="120px preferred width">
<mdc-carousel-item size="large"><div class="cdp-card cdp-a">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cdp-card cdp-b">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cdp-card cdp-c">Small</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cdp-card cdp-c">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cdp-card cdp-a">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cdp-card cdp-b">Small</div></mdc-carousel-item>
</mdc-carousel>
<!-- default preferred-item-width (186) -->
<mdc-carousel aria-label="Default 186px preferred width">
<mdc-carousel-item size="large"><div class="cdp-card cdp-a">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cdp-card cdp-b">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cdp-card cdp-c">Small</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cdp-card cdp-c">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cdp-card cdp-a">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cdp-card cdp-b">Small</div></mdc-carousel-item>
</mdc-carousel>
<!-- larger preferred width → bigger large item, wider small/medium -->
<mdc-carousel preferred-item-width="260" aria-label="260px preferred width">
<mdc-carousel-item size="large"><div class="cdp-card cdp-a">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cdp-card cdp-b">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cdp-card cdp-c">Small</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cdp-card cdp-c">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cdp-card cdp-a">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cdp-card cdp-b">Small</div></mdc-carousel-item>
</mdc-carousel>Variant
Code
<style>
.cd-card {
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
height: 180px;
padding: 8px;
font: 500 14px/20px Roboto, system-ui, sans-serif;
color: var(--md-sys-color-on-surface, #1d1b20);
}
.cd-a { background: var(--md-sys-color-surface-container-high, #e6e0e9); }
.cd-b { background: var(--md-sys-color-secondary-container, #e8def8); }
.cd-c { background: var(--md-sys-color-tertiary-container, #ffd8e4); }
</style>
<!-- multi-browse (default): mixes large / medium / small items that snap to the leading keyline -->
<mdc-carousel aria-label="Multi-browse carousel">
<mdc-carousel-item size="large"><div class="cd-card cd-a">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cd-card cd-b">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cd-card cd-c">Small</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cd-card cd-c">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cd-card cd-a">Medium</div></mdc-carousel-item>
<mdc-carousel-item size="small"><div class="cd-card cd-b">Small</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cd-card cd-b">Large</div></mdc-carousel-item>
<mdc-carousel-item size="medium"><div class="cd-card cd-c">Medium</div></mdc-carousel-item>
</mdc-carousel>
<!-- uncontained: uniform width, scrolls freely (no snap), trailing item peeks at the edge -->
<mdc-carousel variant="uncontained" aria-label="Uncontained carousel">
<mdc-carousel-item size="large"><div class="cd-card cd-a">One</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cd-card cd-b">Two</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cd-card cd-c">Three</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cd-card cd-a">Four</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cd-card cd-b">Five</div></mdc-carousel-item>
<mdc-carousel-item size="large"><div class="cd-card cd-c">Six</div></mdc-carousel-item>
</mdc-carousel>