Skip to content

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 wiring icon

    ARIA & semantics

    Every interactive component sets the ARIA attributes its Bootstrap JS plugin expects — aria-expanded, aria-controls, aria-labelledby, aria-current and friends — so you don't have to add them by hand.

  • Keyboard and focus icon

    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 icon

    Required alt text

    Card and Carousel Item both require image_alt whenever an image is set — enforced in the component's JSON Schema, not left as an optional prop, per WCAG 1.1.1.

  • Persistent pause control icon

    Autoplay pause control

    Carousel's show_pause defaults to true, 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.

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's message or Modal's body: 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.