ARIA wiring · keyboard focus · required alt text · autoplay pause
Accessibility¶
Bootstrap Components wraps stock Bootstrap 5 markup — no custom CSS, no reinvented behavior. That means most of its accessibility comes straight from Bootstrap's own tested patterns: focus trapping in Modal/Offcanvas, keyboard navigation in Dropdown/Carousel/Nav, and the ARIA attributes Bootstrap's JS plugins manage at runtime. This page covers what's actually built into the components on top of that — not a generic accessibility checklist.
What this module handles¶
Four things enforced or wired in by the components themselves, without a caller having to ask for them.
-
ARIA & semantics
Every interactive component sets the ARIA attributes its Bootstrap JS plugin expects —
aria-expanded,aria-controls,aria-labelledby,aria-currentand friends — so you don't have to add them by hand. -
Keyboard & focus
Focus trapping in Modal/Offcanvas, keyboard navigation in Dropdown/Carousel/Nav — none of it reimplemented here, all of it inherited straight from Bootstrap's own tested JS plugins.
-
Required alt text
Card and Carousel Item both require
image_altwhenever an image is set — enforced in the component's JSON Schema, not left as an optional prop, per WCAG 1.1.1. -
Autoplay pause control
Carousel's
show_pausedefaults totrue, giving autoplaying content the persistent stop control WCAG 2.2.2 requires — Bootstrap's own prev/next and indicators don't satisfy it alone.
Per-topic notes¶
Where the pattern is more specific than "handled," here's the mechanism.
Required alt text on images¶
Carousel Item requires image_alt whenever image_url is set — it's enforced in the component's JSON Schema (an anyOf/not/minLength rule), per WCAG 1.1. Card images come from the Canvas image picker, which carries its own alt text; Twig callers that pass image_src should pass image_alt too.1. An image-less card or slide is exempt; a cleared image_src/image_url is exempt too.
Carousel autoplay has a persistent pause control¶
show_pause defaults to true on Carousel, rendering a pause/resume button whenever the carousel autoplays. Bootstrap's own prev/next controls and indicators only pause the rotation momentarily — they resume cycling once the interaction's transition completes, which doesn't satisfy WCAG 2.2.2 (moving content needs a way to stop it, not just interrupt it). Turn show_pause off only for a carousel that doesn't autoplay (interval: 0).
Disabled buttons stay out of the tab order¶
Setting disabled on Button removes href, sets tabindex="-1" and aria-disabled="true", and adds the .disabled class — for a link rendered as <a>, native disabled isn't a valid attribute, so Button handles all three explicitly rather than leaving a disabled-looking link that's still focusable and clickable.
ARIA wiring already in place¶
| Component | What's wired |
|---|---|
| Accordion Item | aria-expanded, aria-controls on the trigger; aria-labelledby on the panel |
| Breadcrumb | aria-label on the <nav>; aria-current="page" on the active item |
| Pagination | aria-label on the <nav>; aria-current="page" on the active item |
| Carousel | aria-label on each indicator ("Slide N"); aria-current on the active one; aria-label/aria-pressed on the pause control; aria-hidden on decorative icons |
| Carousel Item | role="img" + aria-label on the image placeholder when no image is set |
| Navbar | aria-controls, aria-expanded, aria-label on the collapse/offcanvas toggler |
| Dropdown | aria-expanded on the toggle button; aria-labelledby on the menu |
| Nav (tabs) | aria-selected, aria-controls on each tab; aria-disabled on disabled items |
| Modal / Offcanvas | aria-hidden while closed; aria-labelledby pointing at the title, only when a title is set |
| Close Button | aria-label (defaults to "Close", override via aria_label) |
| Alert / Button | aria-hidden="true" on decorative icons, so screen readers only announce the label text next to them |
Heading levels are a prop, not hardcoded¶
Card, Accordion Item, and Offcanvas all expose a heading_level prop instead of hardcoding an <h3> or similar — so a page author can keep the document's heading hierarchy correct (no skipped levels) regardless of where the component lands on the page.
What this module can't enforce for you¶
-
Content quality
Schema validation can require that
image_alt, ARIA labels, and headings are present — it can't verify they're meaningful, and the same goes for rich HTML in props like Alert'smessageor Modal'sbody: extra headings, links, and images authored inside them aren't validated either. Writing real alt text, labels, and well-structured markup is still on whoever fills in the props. -
Color contrast
This module ships no CSS of its own — contrast comes entirely from Bootstrap's default palette or whatever the consuming theme overrides it with. A theme that changes colors is responsible for checking contrast itself.