In website design, “carousel” and “slider” often describe overlapping image or content rotators. Define the behavior rather than relying on the name. A carousel browses a set of items or slides; an HTML range slider selects a value. Those controls need different semantics, keyboard behavior, and labels.
Three patterns that are often confused
| Pattern | What the visitor does | Example |
|---|---|---|
| Content carousel | Moves between distinct items | Featured projects with Previous and Next buttons |
| Image slider | Views images or slides; terminology varies | A manually controlled product gallery |
| Range slider | Selects a numeric value | Volume, budget, or a filter threshold |
During design review, specify how many cards are visible, whether movement wraps, whether it advances automatically, and what happens at narrow widths. “Add a slider” leaves all of those decisions unresolved.
Try a manual carousel and a range slider
Example setup: Tailwind CSS 4.1.18, compiled locally, with plain HTML and vanilla JavaScript. These small educational examples are separate from the membership library. Adapt them to your application and test your final content and browser requirements.
Complete HTML, CSS, and JavaScript
Use your compiled Tailwind stylesheet in place of /examples/tailwind.css. The example uses Tailwind CSS 4 utilities and vanilla JavaScript.
<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex,follow"><title>A manual carousel and a continuous range slider</title><link rel="stylesheet" href="/examples/tailwind.css"><style>body{font-family:system-ui,sans-serif;background:#faf9f6;color:#252824;padding:24px}button{cursor:pointer}button:disabled{cursor:wait;opacity:.6}:focus-visible{outline:3px solid #4f46e5;outline-offset:4px}[hidden]{display:none!important}</style></head><body><section role="region" aria-roledescription="carousel" aria-label="Project examples" class="rounded-2xl border bg-white p-5">
<div class="flex justify-between gap-4"><button id="previous" class="rounded-lg border px-3 py-2">Previous</button><button id="next" class="rounded-lg border px-3 py-2">Next</button></div>
<div id="slides" class="mt-4">
<div role="group" aria-roledescription="slide" aria-label="1 of 3" class="rounded-xl bg-orange-100 p-8"><h2 class="text-2xl font-semibold">01 — Gather</h2><p>A place for the whole team.</p></div>
<div role="group" aria-roledescription="slide" aria-label="2 of 3" hidden class="rounded-xl bg-indigo-100 p-8"><h2 class="text-2xl font-semibold">02 — Explore</h2><p>Make space for a new direction.</p></div>
<div role="group" aria-roledescription="slide" aria-label="3 of 3" hidden class="rounded-xl bg-emerald-100 p-8"><h2 class="text-2xl font-semibold">03 — Build</h2><p>Turn a small idea into something useful.</p></div>
</div><p id="position" role="status" class="mt-3 text-sm">Slide 1 of 3</p>
</section>
<div class="mt-6"><label for="volume" class="block font-semibold">A different kind of slider: volume</label><input id="volume" type="range" min="0" max="100" value="50" class="mt-3 w-full"><output for="volume" id="value">50%</output></div><script>const slides = Array.from(document.querySelector('#slides').children);
let current = 0;
function show(offset) {
current = (current + offset + slides.length) % slides.length;
slides.forEach((slide, index) => { slide.hidden = index !== current; });
document.querySelector('#position').textContent = 'Slide ' + (current + 1) + ' of ' + slides.length;
}
document.querySelector('#previous').addEventListener('click', () => show(-1));
document.querySelector('#next').addEventListener('click', () => show(1));
document.querySelector('#volume').addEventListener('input', event => { document.querySelector('#value').value = event.target.value + '%'; });</script></body></html>The carousel does not start moving by itself. Its buttons keep focus while the displayed item changes, and a status message identifies the current slide. Hidden slides are removed from the tab order through the native hidden attribute. The range control uses a labeled native input, so its keyboard behavior comes from the browser.
When a carousel earns its space
A carousel can work when visitors deliberately inspect a sequence: several views of a product, a project story, or a small collection of related images. Make the controls visible and communicate that more content exists. Keep the position indicator understandable without color alone.
A carousel is less suitable when every item is essential to choosing or buying. Pricing plans, required setup steps, and key feature comparisons are easier to compare when visible together. A grid also lets visitors scan at their own pace without remembering the previous slide.
Be cautious with automatic rotation
Automatically moving content introduces additional requirements. A visitor may be reading, using a keyboard, or enlarging the page when the content changes. The WAI-ARIA carousel pattern describes rotation controls, focus behavior, and labeling. Implement that complete pattern if automatic rotation is necessary; do not just add a timer to this example.
For a marketing hero, start with one strong message. If several audiences need different messages, explicit tabs or separate landing pages may explain the choices more clearly than rotating headlines.
Images and performance
Reserve a consistent image area, choose crops intentionally, and provide useful alternative text. Avoid downloading a large collection of full-resolution images before the first screen becomes usable. Load the initial important image promptly and defer images that are not immediately needed.
Check touch interaction without relying on it exclusively: Previous and Next buttons should remain usable. Try the carousel at 200% zoom, with a long caption, and with JavaScript unavailable. A fallback that still shows the first item is better than an empty container.
Choose the simplest useful version
- Use a static grid when comparison matters.
- Use a manual carousel when browsing a sequence matters.
- Use a range input when the task is choosing a value.
- Use a single hero when one message deserves attention.
Compare an asymmetric gallery with the gallery collection, and read our motion guide before adding transitions.
