
accessibility
18.05.2026
Faceless UI: An open-source web component for accessible carousels
Lucas Falkowsky
Fullstack Development
Five parts, five areas of potential error, one complete picture. Now the obvious question: Does all of this have to be rebuilt from scratch every time? faceless-carousel is an open-source web component that implements all WCAG requirements from this accessible by design series—without dictating to the developer how the carousel should look.
Anyone trying to implement BFSG compliance quickly encounters an unexpected challenge: building an accessible carousel is significantly more involved than it looks. role="region", aria-roledescription, aria-live, inert, prefers-reduced-motion, touch targets, swipe alternatives, dynamic play/pause labels, focus management — that's the full scope of what a genuinely conformant implementation requires. This series has worked through each of those layers.
Now comes the question that's legitimate at the end of any series like this: does all of that have to be built by hand every time? Not necessarily. faceless-carousel is an open-source Web Component that does exactly this work once — and then makes it reusable across every project, without dictating how the carousel should look.
What a Web Component Is — and Why It Matters Here
A Web Component is a component natively anchored in the browser. No React, no Vue, no Angular — it works in any environment because it's part of the web standard itself. To use it, you import a JavaScript file and use a new HTML element as if it were a native tag.
What this means for accessibility is not trivial. Web Components encapsulate their internal behavior in the so-called Shadow DOM — an isolated DOM tree that can't be accidentally overwritten from the outside. ARIA attributes, event listeners, focus management, and live regions live within this encapsulation, protected from global CSS classes, JavaScript conflicts, or framework updates with unexpected side effects. Once accessibility logic has been carefully built into a Web Component, you can be confident it will behave the same way in every deployment — whether in a Next.js project, a statically generated Hugo blog, or a classic HTML page.
The Faceless UI Principle
"Faceless" means: the component has no face. It brings the complete accessibility foundation — ARIA structure, keyboard navigation, focus management, live regions, autoplay control, off-screen handling — but absolutely no opinion on what the carousel should look like. Colors, spacing, animations, typography: all up to the developer.
No CSS to override. No design that needs to fit your design system — or doesn't.
The idea behind it: accessibility logic is infrastructure. Building it once carefully and deploying it everywhere is more efficient than reinventing it with every new component — and safer, because it doesn't have to be retested each time.
What This Looks Like in Practice
After five parts full of ARIA attributes and edge cases, the integration is almost anticlimactic in its simplicity. You include the script, write <faceless-carousel> in your HTML, drop your slides in as direct child elements, and the component takes care of the rest.
Every child is automatically recognized as a slide, assigned the correct ARIA roles, and wired into the navigation. No markup to maintain manually. No JavaScript to write.
For styling, there are no constraints. The component ships with no CSS to override. If you use Tailwind, you write Tailwind. If you use CSS Modules, you write CSS Modules. Dots, spacing, animations, colors — all controllable via CSS Custom Properties, as much or as little as you need.
Carousel control works in two ways. Via HTML attributes directly on the element: loop, autoplay, number of visible slides, peek effects, mousewheel support — all declarative, without a single line of JavaScript. And via external buttons placed anywhere in the DOM — next to the slider, for instance — that are simply linked to the carousel via an attribute. The component wires them up on load and cleans up when removed from the DOM. For those needing more control, there's also a small JavaScript API: next(), prev(), goTo(index) — that's usually all you need.
Open Source
faceless-carousel is open source, framework-agnostic, and dependency-free. If you want to build accessible websites without rebuilding ARIA layers from scratch every time, this is a production-ready foundation. Issues, pull requests, and feedback are welcome.
What This Series Has Shown
Accessibility rarely fails because of a lack of will. It fails because of complexity — and because that complexity is invisible. No screenshot reveals a missing aria-live. No visual test discovers a broken tab order. No stakeholder review notices that off-screen slides are focusable.
What this series has shown: accessibility is not a feature you add at the end. It's a layer that has to be considered from the start — in the semantics, in the interaction, in state communication, in physical input. Once you understand that, you build different components. Better components. Components that work for everyone.
The carousel was the example. The principle applies to everything else too.
Summary Checklist
For reference in your own implementations and audits — all points covered in this series.
Accessible Carousel Checklist
- Carousel navigable as a landmark (
role="region") aria-roledescription="carousel"set on the container- Meaningful
aria-labelon the container — not "Carousel" - Each slide individually identified (
role="group",aria-roledescription="slide") - Position information available (
aria-label="Slide N of M") - Off-screen slides absent from the accessibility tree (
inertoraria-hidden) - Slide change announced on manual navigation (
aria-live="polite") - Slide change not announced during auto-rotation (
aria-live="off") - Play/Pause button present and correctly labeled
- Play/Pause button updates
aria-labelon state change - Rotation stops on keyboard focus and mouse hover
- Focus stays on the control element during navigation
- All controls have meaningful labels
- Touch targets at least 24×24 px (recommended: 44×44 px)
- Swipe gestures have button alternatives
prefers-reduced-motionis respected- Tested with NVDA (Windows), VoiceOver (macOS/iOS), TalkBack (Android)
Sources: W3C APG, Carousel Pattern · WCAG 2.2 · Chrome, Accessible Carousel · faceless-carousel Dokumentation
Contact
Got questions about your website's accessibility?
Lucas Falkowsky
Fullstack Development
