Content carousel
Category: Marketing · Tags: carousel, slides, slideshow, features, marketing
What is new in the travel planner
Slide 1 of 4
How to use it
Use for a few equally important highlights that do not all need to be seen, such as feature tours on a landing page. If every item matters, show them as a list or grid instead, since many people never advance a carousel. Keep it to three to five slides, update the "n of 4" labels and the heading when you change the count, and make each slide self-contained.
Accessibility
Follows the WAI-ARIA carousel pattern: the <section> has aria-roledescription="carousel" and is labelled by its heading, each slide is role="group" with aria-roledescription="slide" and an "n of 4" label, and only the current slide is shown (the rest carry hidden). Previous and Next are native <button>s that keep focus while a polite live line reads "Slide 2 of 4". It never autoplays and has no motion, so nothing moves unless the user asks. The heading and position line are #0f172a on #f8fafc (17.06:1), slide text #0f172a and #334155 on white (17.85:1, 10.35:1), buttons white on #1d4ed8 (6.70:1, 8.72:1 hovered) with a 2px #1d4ed8 focus outline.
Source (copy-ready)
<section class="dcl-carousel" aria-roledescription="carousel" aria-labelledby="dcl-carousel-title">
<h2 class="dcl-carousel__title" id="dcl-carousel-title">What is new in the travel planner</h2>
<div class="dcl-carousel__slides" id="dcl-carousel-slides">
<div class="dcl-carousel__slide" role="group" aria-roledescription="slide" aria-label="1 of 4">
<svg class="dcl-carousel__icon" viewBox="0 0 36 32" width="36" height="32" aria-hidden="true" focusable="false"><path d="M4 8l9-4 10 4 9-4v20l-9 4-10-4-9 4z" fill="none" stroke="#1d4ed8" stroke-width="2"/></svg>
<h3 class="dcl-carousel__heading">Offline maps</h3>
<p class="dcl-carousel__text">Download a region before you travel and keep navigating with no signal.</p>
</div>
<div class="dcl-carousel__slide" role="group" aria-roledescription="slide" aria-label="2 of 4" hidden>
<svg class="dcl-carousel__icon" viewBox="0 0 36 32" width="36" height="32" aria-hidden="true" focusable="false"><path d="M8 8h18M8 16h18M8 24h12" stroke="#1d4ed8" stroke-width="3" stroke-linecap="round"/></svg>
<h3 class="dcl-carousel__heading">Shared trip lists</h3>
<p class="dcl-carousel__text">Plan stops together: everyone on the trip can add, tick off and reorder places.</p>
</div>
<div class="dcl-carousel__slide" role="group" aria-roledescription="slide" aria-label="3 of 4" hidden>
<svg class="dcl-carousel__icon" viewBox="0 0 36 32" width="36" height="32" aria-hidden="true" focusable="false"><circle cx="18" cy="16" r="11" fill="none" stroke="#1d4ed8" stroke-width="2"/><path d="M18 9v8l5 3" fill="none" stroke="#1d4ed8" stroke-width="2"/></svg>
<h3 class="dcl-carousel__heading">Live arrival times</h3>
<p class="dcl-carousel__text">See when the next train or bus actually leaves, updated every minute.</p>
</div>
<div class="dcl-carousel__slide" role="group" aria-roledescription="slide" aria-label="4 of 4" hidden>
<svg class="dcl-carousel__icon" viewBox="0 0 36 32" width="36" height="32" aria-hidden="true" focusable="false"><path d="M6 26h8v-6h8v-6h8" fill="none" stroke="#1d4ed8" stroke-width="3"/></svg>
<h3 class="dcl-carousel__heading">Step-free routes</h3>
<p class="dcl-carousel__text">Turn on step-free routing to avoid stairs and escalators on every journey.</p>
</div>
</div>
<div class="dcl-carousel__controls">
<button type="button" class="dcl-carousel__button dcl-carousel__prev" aria-controls="dcl-carousel-slides">Previous<span class="dcl-carousel__sr"> slide</span></button>
<p class="dcl-carousel__position" aria-live="polite" aria-atomic="true">Slide 1 of 4</p>
<button type="button" class="dcl-carousel__button dcl-carousel__next" aria-controls="dcl-carousel-slides">Next<span class="dcl-carousel__sr"> slide</span></button>
</div>
</section>
<style>
.dcl-carousel { max-width: 34rem; padding: 1rem; border: 1px solid #cbd5e1; border-radius: 0.75rem; font: inherit; color: #0f172a; background-color: #f8fafc; }
.dcl-carousel__title { margin: 0 0 0.75rem; font-size: 1.15rem; color: #0f172a; background-color: #f8fafc; }
.dcl-carousel__slides { min-height: 9rem; }
.dcl-carousel__slide { padding: 1rem; border: 1px solid #e2e8f0; border-radius: 0.5rem; color: #0f172a; background-color: #ffffff; }
.dcl-carousel__icon { display: block; margin-bottom: 0.5rem; }
.dcl-carousel__heading { margin: 0 0 0.35rem; font-size: 1.05rem; color: #0f172a; background-color: #ffffff; }
.dcl-carousel__text { margin: 0; color: #334155; background-color: #ffffff; }
.dcl-carousel__controls { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.75rem; }
.dcl-carousel__position { margin: 0; font-weight: 600; color: #0f172a; background-color: #f8fafc; }
.dcl-carousel__button { padding: 0.45rem 0.9rem; border: none; border-radius: 6px; font: inherit; font-weight: 600; cursor: pointer; color: #ffffff; background-color: #1d4ed8; }
.dcl-carousel__button:hover { color: #ffffff; background-color: #1e40af; }
.dcl-carousel__button:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 2px; }
.dcl-carousel__sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
</style>
<script>
(function () {
document.querySelectorAll(".dcl-carousel").forEach(function (root) {
if (root.dataset.dclBound) { return; }
root.dataset.dclBound = "true";
var slides = root.querySelectorAll(".dcl-carousel__slide");
var position = root.querySelector(".dcl-carousel__position");
var prev = root.querySelector(".dcl-carousel__prev");
var next = root.querySelector(".dcl-carousel__next");
if (!slides.length) { return; }
var current = 0;
function show(index) {
current = (index + slides.length) % slides.length;
slides.forEach(function (slide, i) { slide.hidden = i !== current; });
if (position) { position.textContent = "Slide " + (current + 1) + " of " + slides.length; }
}
if (prev) { prev.addEventListener("click", function () { show(current - 1); }); }
if (next) { next.addEventListener("click", function () { show(current + 1); }); }
show(0);
});
})();
</script>
Was this useful? Send feedback.