liquid-theme-a11y
Implement WCAG 2.2 accessibility patterns in Shopify Liquid themes. Covers e-commerce-specific components including product cards, carousels, cart drawers, price display, forms, filters, and modals. Use when building accessible theme components, fixing accessibility issues, or reviewing ARIA pattern
By benjaminsehl · 2,557 installs
npx skills add benjaminsehl/liquid-skills --skill liquid-theme-a11y
Source repository · Upstream listing
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?
Component HTML Element ARIA Pattern Reference
Expandable content <details /<summary None needed [Accordion]( accordion)
Modal/dialog <dialog aria modal="true" [Modal]( modal)
Tooltip/popup [popover] attribute role="tooltip" fallback [Tooltip]( tooltip)
Dropdown menu <nav + <ul aria expanded on triggers [Navigation]( dropdown navigation)
Tab interface <div role="tablist/tab/tabpanel" [Tabs]( tabs)
Carousel/slider <div role="region" + aria roledescription [Carousel]( carousel)
Product card <article aria labelledby [Product card]( product card)
Form <form aria invalid , aria describedby [Forms]( forms)
Cart drawer <dialog Focus trap [Cart drawer]( cart drawer)
Price display <span aria label for context [Prices]( price display)
Filters <form + <fieldset aria expanded for disclosures [Filters]( product filters)
Page Structure
Landmarks
Single <header , <main , <footer per page
Multiple <nav elements must have distinct aria 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: none without 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](references/focus and keyboard.md) 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 labelledby on <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:
Use native <dialog element
aria labelledby pointing to the title
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 matching for / id
Use <fieldset /<legend for radio/checkbox groups
Error messages: role="alert" + aria describedby linking to input
aria invalid="true" on invalid inputs
autocomplete attributes on common fields
Required fields: required + aria required="true" + visual indicator
Product Filters
Price Display
Use aria label to provide full price context (sale vs. original)
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 dvh instead of vh for 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.
Color Contrast
Element Minimum Ratio
Normal text (<18px / <14px bold) 4.5:1
Large text (≥18px / ≥14px bold) 3:1
UI components & graphics 3:1
Focus indicators 3:1
Never rely solely on color to convey information — always pair with text, icons, or patterns.
References
[Component accessibility patterns](references/component patterns.md)
[Focus and keyboard patterns](references/focus and keyboard.md)