Carousel
The Carousel component displays sequential content items inside a horizontally scrolling viewport
with built-in navigation arrows, pagination indicators and an optional autoplay control.
Slides are provided as DhlCarouselSlide children.
The Carousel has two size variants:
- Default — shows navigation arrows, pagination indicator and (optionally) the play button.
- Compact — shows only the pagination indicator for a slimmer control bar.
Import
- React
- Angular
- Vue.js
// with @dhl-official/react-library:
import { DhlCarousel, DhlCarouselSlide } from "@dhl-official/react-library"
// with @dhl-official/ui-libraries/react-library:
import { DhlCarousel, DhlCarouselSlide } from "@dhl-official/ui-libraries/react-library"
If the DUIL has been installed, you can use the web component directly:
<dhl-carousel></dhl-carousel>
<dhl-carousel-slide></dhl-carousel-slide>
// with @dhl-official/vue-library:
import { DhlCarousel, DhlCarouselSlide } from "@dhl-official/vue-library"
// with @dhl-official/ui-libraries/vue-library:
import { DhlCarousel, DhlCarouselSlide } from "@dhl-official/ui-libraries/vue-library"
Accessibility
The Carousel is rendered as an ARIA region with the accessible name provided via the
label prop. Each DhlCarouselSlide should provide its own descriptive label so screen
readers can announce the slide content. Autoplay is paused automatically when the carousel
receives keyboard focus or when the tab is hidden.
Notes
- Set
intervalto0to disable autoplay entirely. In that case, the play button is hidden. - Set
slideWidthto a value smaller than100%(e.g."80%") to make adjacent slides partially visible at the edges of the viewport (peek effect). - Use
slideGapto control the spacing between slides whenslideWidthis less than100%. - Use the
next(),previous(),goTo(index),play()andpause()methods to control the carousel programmatically.
Code
- React
- Angular
- Vue.js
<DhlCarousel>
<DhlCarouselSlide label="First image">
<img src="/images/one.jpg" alt="" />
</DhlCarouselSlide>
<DhlCarouselSlide label="Second image">
<img src="/images/two.jpg" alt="" />
</DhlCarouselSlide>
<DhlCarouselSlide label="Third image">
<img src="/images/three.jpg" alt="" />
</DhlCarouselSlide>
</DhlCarousel>
<dhl-carousel>
<dhl-carousel-slide label="First image">
<img src="assets/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Second image">
<img src="assets/two.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Third image">
<img src="assets/three.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel>
<dhl-carousel-slide label="First image">
<img src="assets/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Second image">
<img src="assets/two.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Third image">
<img src="assets/three.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
Interactive Demo
Variants
Compact
Slim control bar that shows only the pagination indicator. Useful when the surrounding layout already provides navigation context.
- React
- Angular
- Vue.js
<DhlCarousel size="compact">
<DhlCarouselSlide label="First image">
<img src="/images/one.jpg" alt="" />
</DhlCarouselSlide>
<DhlCarouselSlide label="Second image">
<img src="/images/two.jpg" alt="" />
</DhlCarouselSlide>
</DhlCarousel>
<dhl-carousel size="compact">
<dhl-carousel-slide label="First image">
<img src="assets/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Second image">
<img src="assets/two.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel size="compact">
<dhl-carousel-slide label="First image">
<img src="assets/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Second image">
<img src="assets/two.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
Peek adjacent slides
When slideWidth is less than 100%, adjacent slides become partially visible at the
edges of the viewport — useful for hinting that more content is available.
- React
- Angular
- Vue.js
<DhlCarousel slideWidth="80%">
<DhlCarouselSlide label="Product 1">
<img src="/images/one.jpg" alt="" />
</DhlCarouselSlide>
<DhlCarouselSlide label="Product 2">
<img src="/images/two.jpg" alt="" />
</DhlCarouselSlide>
<DhlCarouselSlide label="Product 3">
<img src="/images/three.jpg" alt="" />
</DhlCarouselSlide>
</DhlCarousel>
<dhl-carousel slide-width="80%">
<dhl-carousel-slide label="Product 1">
<img src="assets/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Product 2">
<img src="assets/two.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Product 3">
<img src="assets/three.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel slide-width="80%">
<dhl-carousel-slide label="Product 1">
<img src="assets/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Product 2">
<img src="assets/two.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Product 3">
<img src="assets/three.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
Multiple visible slides
Setting a smaller slideWidth allows several slides to appear at once. Combine with
interval="0" and loop="false" for a static, card-strip layout.
- React
- Angular
- Vue.js
<DhlCarousel slideWidth="33%" interval={0} loop={false}>
<DhlCarouselSlide label="Card 1"><div>Card 1</div></DhlCarouselSlide>
<DhlCarouselSlide label="Card 2"><div>Card 2</div></DhlCarouselSlide>
<DhlCarouselSlide label="Card 3"><div>Card 3</div></DhlCarouselSlide>
<DhlCarouselSlide label="Card 4"><div>Card 4</div></DhlCarouselSlide>
<DhlCarouselSlide label="Card 5"><div>Card 5</div></DhlCarouselSlide>
</DhlCarousel>
<dhl-carousel slide-width="33%" interval="0" loop="false">
<dhl-carousel-slide label="Card 1"><div>Card 1</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 2"><div>Card 2</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 3"><div>Card 3</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 4"><div>Card 4</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 5"><div>Card 5</div></dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel slide-width="33%" interval="0" :loop="false">
<dhl-carousel-slide label="Card 1"><div>Card 1</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 2"><div>Card 2</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 3"><div>Card 3</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 4"><div>Card 4</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 5"><div>Card 5</div></dhl-carousel-slide>
</dhl-carousel>
Without play button
Hide the autoplay toggle when the carousel should not start playback from user interaction.
- React
- Angular
- Vue.js
<DhlCarousel showPlayButton={false}>
<DhlCarouselSlide><img src="/images/one.jpg" alt="" /></DhlCarouselSlide>
<DhlCarouselSlide><img src="/images/two.jpg" alt="" /></DhlCarouselSlide>
</DhlCarousel>
<dhl-carousel show-play-button="false">
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel :show-play-button="false">
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
Autoplay disabled
Set interval to 0 to disable autoplay entirely. The play button is hidden when autoplay
is disabled.
- React
- Angular
- Vue.js
<DhlCarousel interval={0}>
<DhlCarouselSlide><img src="/images/one.jpg" alt="" /></DhlCarouselSlide>
<DhlCarouselSlide><img src="/images/two.jpg" alt="" /></DhlCarouselSlide>
</DhlCarousel>
<dhl-carousel interval="0">
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel interval="0">
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
Loop disabled
By default, advancing past the last slide wraps around to the first. Disable looping to make navigation stop at the boundaries.
- React
- Angular
- Vue.js
<DhlCarousel loop={false}>
<DhlCarouselSlide><img src="/images/one.jpg" alt="" /></DhlCarouselSlide>
<DhlCarouselSlide><img src="/images/two.jpg" alt="" /></DhlCarouselSlide>
</DhlCarousel>
<dhl-carousel loop="false">
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel :loop="false">
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
Controlling the carousel programmatically
Use the componentOnReady() lifecycle hook and the exposed goTo(), next(), previous(),
play() and pause() methods to drive the carousel from outside.
- React
- Angular
- Vue.js
const ref = useRef(null);
useEffect(() => {
ref.current?.goTo(2);
}, []);
return (
<DhlCarousel ref={ref}>
<DhlCarouselSlide><img src="/images/one.jpg" alt="" /></DhlCarouselSlide>
<DhlCarouselSlide><img src="/images/two.jpg" alt="" /></DhlCarouselSlide>
<DhlCarouselSlide><img src="/images/three.jpg" alt="" /></DhlCarouselSlide>
</DhlCarousel>
);
<dhl-carousel #carousel>
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/three.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
<dhl-carousel ref="carousel">
<dhl-carousel-slide><img src="assets/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/two.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="assets/three.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
Readme
Usage
Dhl-carousel
Snippets of code in HTML and JavaScript to show some of the use cases for the component. The code is not meant to be executed, but to be used as a reference for the usage of the component. Angular, React and Vue usages are not included in this documentation, but can be easily derived from the html and javascript code.
default usage
<dhl-carousel>
<dhl-carousel-slide label="First image">
<img src="/images/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Second image">
<img src="/images/two.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Third image">
<img src="/images/three.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
peek adjacent slides (slideWidth 80%)
When slide-width is less than 100%, adjacent slides become partially
visible at the edges of the viewport.
<dhl-carousel slide-width="80%">
<dhl-carousel-slide label="Product 1">
<img src="/images/one.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Product 2">
<img src="/images/two.jpg" alt="" />
</dhl-carousel-slide>
<dhl-carousel-slide label="Product 3">
<img src="/images/three.jpg" alt="" />
</dhl-carousel-slide>
</dhl-carousel>
multiple visible slides (slideWidth 33%)
Setting a smaller slide-width lets several slides appear at once.
<dhl-carousel slide-width="33%" interval="0" loop="false">
<dhl-carousel-slide label="Card 1"><div>Card 1</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 2"><div>Card 2</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 3"><div>Card 3</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 4"><div>Card 4</div></dhl-carousel-slide>
<dhl-carousel-slide label="Card 5"><div>Card 5</div></dhl-carousel-slide>
</dhl-carousel>
half-width slides (slideWidth 50%)
<dhl-carousel slide-width="50%">
<dhl-carousel-slide label="A"><div>Slide A</div></dhl-carousel-slide>
<dhl-carousel-slide label="B"><div>Slide B</div></dhl-carousel-slide>
<dhl-carousel-slide label="C"><div>Slide C</div></dhl-carousel-slide>
<dhl-carousel-slide label="D"><div>Slide D</div></dhl-carousel-slide>
</dhl-carousel>
compact size
<dhl-carousel size="compact">
<dhl-carousel-slide><img src="/images/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/two.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/three.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
compact with peek
<dhl-carousel size="compact" slide-width="80%">
<dhl-carousel-slide><img src="/images/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/two.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/three.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
without play button
<dhl-carousel show-play-button="false">
<dhl-carousel-slide><img src="/images/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
custom autoplay interval
<dhl-carousel interval="3000">
<dhl-carousel-slide><img src="/images/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
autoplay disabled
<dhl-carousel interval="0">
<dhl-carousel-slide><img src="/images/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
loop disabled
<dhl-carousel loop="false">
<dhl-carousel-slide><img src="/images/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/two.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
controlling the carousel programmatically
<dhl-carousel id="my-carousel">
<dhl-carousel-slide><img src="/images/one.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/two.jpg" alt="" /></dhl-carousel-slide>
<dhl-carousel-slide><img src="/images/three.jpg" alt="" /></dhl-carousel-slide>
</dhl-carousel>
<script type="module">
const carousel = document.getElementById("my-carousel");
carousel.componentOnReady().then(async () => {
await carousel.goTo(2);
await carousel.play();
});
</script>
Properties
| Property | Attribute | Description | Type | Default |
|---|---|---|---|---|
activeIndex | active-index | An optional prop. The index of the currently visible slide. | number | 0 |
dataClassName | data-class-name | An optional class name prop for the component. | string | undefined |
dataId | data-id | An optional prop. Gives a valid HTML ID attribute value for the component. | string | `dhl-carousel-${getRandomString()}` |
dataTestid | data-testid | An optional prop. The test id attached to the component as a data-testid attribute. | string | undefined |
interval | interval | An optional autoplay interval in milliseconds. Set to 0 to disable autoplay entirely (the play button is hidden in that case). | number | DHL_CAROUSEL.DEFAULT_INTERVAL |
label | label | An optional prop. The accessible label applied to the carousel region. | string | "Carousel" |
loop | loop | An optional prop. When true, advancing past the last slide wraps to the first slide and going back from the first wraps to the last. When false, navigation stops at the boundaries. | boolean | true |
showPlayButton | show-play-button | An optional prop to show or hide the playback control button. Has no effect when size is "compact" or when interval is 0. | boolean | true |
size | size | An optional prop to select a component design variant. "default" shows arrows, pagination indicator and (optionally) the play button. "compact" shows only the pagination indicator. | "compact" | "default" | DHL_CAROUSEL.SIZE.DEFAULT |
slideGap | slide-gap | An optional prop. The gap between slides as a CSS length (e.g. "16px", "1rem"). Only applies when slideWidth is less than "100%". Defaults to "0px". | string | "0px" |
slideWidth | slide-width | An optional prop. The width of each slide as a CSS percentage (e.g. "80%", "33%"). Defaults to "100%". When less than 100%, adjacent slides become partially visible. | string | "100%" |
Events
| Event | Description | Type |
|---|---|---|
dhlPlayStateChange | Emitted whenever autoplay is started or stopped. | CustomEvent<{ playing: boolean; }> |
dhlSlideChange | Emitted whenever the active slide changes. | CustomEvent<{ index: number; previousIndex: number; }> |
Methods
goTo(index: number) => Promise<void>
Jump directly to the slide at the given index.
Parameters
| Name | Type | Description |
|---|---|---|
index | number |
Returns
Type: Promise<void>
next() => Promise<void>
Advance to the next slide. Wraps to the first slide when loop is
enabled.
Returns
Type: Promise<void>
pause() => Promise<void>
Stop autoplay.
Returns
Type: Promise<void>
play() => Promise<void>
Start autoplay (no-op when autoplay is disabled).
Returns
Type: Promise<void>
previous() => Promise<void>
Move to the previous slide. Wraps to the last slide when loop is
enabled.
Returns
Type: Promise<void>
Slots
| Slot | Description |
|---|---|
"unnamed" | unnamed children slot intended for DhlCarouselSlide component(s) |
Dependencies
Depends on
Graph
Built by DHL User Interface Library Team!