Accessibility for Shopify Liquid Themes
Core Principle
Every interactive component must work with keyboard only, screen readers, and reduced-motion preferences. Start with semantic HTML — add ARIA only when native semantics are insufficient.
Decision Table: Which Pattern?
Page Structure
Landmarks
- Single
<header>,<main>,<footer>per page - Multiple
<nav>elements must have distinctaria-label - All content must live inside a landmark
Skip Link
Headings
- One
<h1>per page, never skip levels (h1 → h3) - Use real heading elements, not styled divs
- Template:
<h1>is typically the page/product title
Focus Management
Focus Indicators
- Minimum 3:1 contrast ratio for focus indicators
- Use
:focus-visible(not:focus) to avoid showing on click - Never
outline: nonewithout a visible replacement
Focus Trapping (Modals/Drawers)
- Trap focus inside modals, drawers, and dialogs
- Return focus to trigger element on close
- First focusable element gets focus on open
- Query all focusable elements:
a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])
See focus and keyboard patterns [blocked] for full FocusTrap implementation.
Component Patterns
Product Card
Rules:
- Single tab stop per card (the main link)
tabindex="-1"on mouse-only shortcuts (quick add)aria-labelledbyon<article>pointing to the title- Descriptive alt text on images; empty
alt=""if decorative
Carousel
Rules:
- Auto-rotation minimum 5 seconds, pause on hover/focus
- Play/pause button required for auto-rotating carousels
aria-live="polite"on slide container (set to"off"during auto-rotation)aria-hidden="true"on inactive slides- Each slide:
role="group"+aria-roledescription="slide"
Modal
Rules:
- Prefer native
<dialog>element for modal UI when feasible.showModal()provides native modal behavior, Escape-to-close, and backdrop handling, butrole="dialog"remains a valid fallback when native<dialog>is not a good fit. aria-labelledbypointing to the title (notaria-labelwith a string —aria-labelledbystays in sync when the title changes)- Close on Escape key (native with
<dialog>) - Focus first interactive element on open
- Return focus to trigger on close
Cart Drawer
Same as modal pattern but with additional:
- Live region for cart count updates:
<span aria-live="polite" aria-atomic="true"> - Clear "remove item" buttons with
aria-label="{{ 'cart.remove_item' | t: title: item.title }}" - Quantity inputs with associated labels
Forms
Rules:
- Every input has a visible
<label>with matchingfor/id - Use
<fieldset>/<legend>for radio/checkbox groups - Error messages:
role="alert"+aria-describedbylinking to input aria-invalid="true"on invalid inputsautocompleteattributes on common fields- Required fields:
required+aria-required="true"+ visual indicator
Product Filters
Price Display
- Use
aria-labelon both sale and regular price paths — screen readers need context for any price display aria-hidden="true"on the visual strikethrough to avoid duplicate reading
Accordion
Native <details>/<summary> provides keyboard and screen reader support automatically.
Tabs
- Arrow keys navigate between tabs (left/right)
- Only active tab has
tabindex="0", others-1
Dropdown Navigation
Tooltip
Mobile Accessibility
- Touch targets: minimum 44x44px, 8px spacing between targets
- No orientation lock: never restrict to portrait/landscape
- No hover-only content: everything accessible via tap
- Use
dvhinstead ofvhfor mobile viewport units
Animation & Motion
- No flashing above 3 times per second
- Auto-playing animations need pause/stop controls
- Meaningful animations only — don't animate for decoration
Visually Hidden Utility
Use for screen-reader-only content like labels and descriptions.
Progressive Enhancement
Interactive components should work without JavaScript where possible. Provide <noscript> fallbacks for JS-dependent controls:
Live Region for Dynamic Updates
When selections change (variants, filters, cart), announce the change to screen readers:
Use the clear-then-set pattern in JS to ensure announcements fire reliably:
Color Contrast
Never rely solely on color to convey information — always pair with text, icons, or patterns.
References
- Component accessibility patterns [blocked]
- Focus and keyboard patterns [blocked]


