Skip to content

Checklist - Code

A and AA levels (Required)

🧩 Markup rules

  • Decorative or redundant images have an empty alt attribute (1.1.1)
  • Non-decorative images have a text alternative in the alt attribute (1.1.1)
  • SVG images have role="img" and alt attributes (1.1.1)
  • Long descriptions of images are provided in the aria-describedby attribute (1.1.1)
  • Markup uses semantic HTML elements (avoid div and span) (1.3.1)
  • The page uses one h1 element and correct heading levels (1.3.1)
  • Markup order follows the visual order of the content (1.3.2)
  • Form fields use the autocomplete and inputmode attributes (1.3.5)
  • Native HTML elements are preferred over custom elements (2.1.1)
  • Custom interactive elements have a tabindex="0" attribute (2.1.1)
  • Elements that should not be focusable are hidden from the tab order (2.1.1)
  • The page has a descriptive title in the title element (2.4.2)
  • The page h1 element content is similar to the title element (2.4.2)
  • Visible labels are preferred over visually hidden labels (2.5.3)
  • Otherwise, visually hidden labels start with the visible labels (2.5.3)
  • The html element has a lang ISO attribute that matches the main language of the content (3.1.1)
  • Parts of content in a different language are identified with a lang ISO attribute (3.1.2)
  • Error messages are associated with the form field using the aria-describedby attribute (3.3.1)
  • Form fields with an error have an aria-invalid="true" attribute (3.3.1)
  • Error message have a role="alert" attribute (3.3.1)
  • Form fields are associated to label elements using the for attribute (3.3.2)
  • Custom form fields are associated to label elements using the aria-labelledby attribute (3.3.2)
  • Placeholders are not used as labels (3.3.2)
  • Required form fields have a required attribute (3.3.2)
  • Custom required form fields have an aria-required="true" attribute (3.3.2)
  • Required form fields (or optional ones) are clearly identified (3.3.2)
  • Hint texts are associated to form fields using the aria-describedby attribute (3.3.2)
  • Groups of form fields are made with the fieldset element or role="group" (3.3.2)
  • Error messages are descriptive and explain how to fix the error (3.3.3)
  • Custom interactive elements have a role attribute (4.1.2)
  • Custom interactive elements have an accessible name (4.1.2)
  • Custom interactive elements clearly indicate their state and value with ARIA (4.1.2)
  • Status messages are used sparingly and only when necessary (4.1.3)
  • Status messages use the correct ARIA role (status, alert, log...) (4.1.3)

🫟 Styling rules

  • The page adapts to both portrait and landscape mode (1.3.4)
  • Relative units (em, rem) are used for font sizes, margins and paddings (1.4.4)
  • Layouts are flexible and text can be resized to 200% (1.4.4)
  • Elements do not have a fixed width bigger than 320px (1.4.10)
  • CSS media queries are used to adapt the layout to breakpoints (1.4.10)
  • The user can hover a tooltip (1.4.13)
  • Content does not flash more than 3 times in a second (2.3.1)
  • Skip links are visible when focused (2.4.1)
  • Content is not re-ordered with CSS if it changes tab order (2.4.3)
  • Links have a meaningful label (at least in context) (2.4.4)
  • Focus on interactive elements is visible and consistent (2.4.7)
  • Focused elements are at least partially visible, not totally masked by any other element (2.4.11)

🧬 Functionality

  • Depending on the content team, live audio content can have AI generated captions (1.2.4)
  • The orientation of the page is not restricted (1.3.4)
  • Audio does not autoplay, or the user can turn it off (1.4.2)
  • Tooltips do not disappear automatically (1.4.13)
  • Components do not only rely on mouse events (2.1.1)
  • Correct keyboard navigation is implemented for custom interactive elements (2.1.1)
  • The user focus is not trapped in an interactive element (2.1.2)
  • Do not use single character shortcuts, or provide a way to disable or remap them (2.1.4)
  • Shortcuts are active only when the element using them has focus (2.1.4)
  • The user can adjust the time limit of interactive content (2.2.1)
  • The user can pause, stop or hide content that moves or auto-updates (2.2.2)
  • Elements use keyup or mouseup events instead of keydown or mousedown (2.5.2)
  • The user can cancel those events mid-way by dragging or with Esc (2.5.2)
  • The user motion preference is respected (no forced motion) (2.5.4)
  • Focusing an element does not cause unexpected change (3.2.1)
  • Filling a form field does not cause unexpected change (3.2.2)
  • Form fields that have not been interacted with do not have errors (3.3.1)
  • The user can review and confirm data before submitting important forms (3.3.4)
  • The user can access a previously entered value in form fields (3.3.7)
  • Authentication forms do not prevent from pasting content (3.3.8)
  • Authentication mechanisms (Face ID, Passkeys, OAuth...) are implemented (3.3.8)
  • There are alternatives for CAPTCHAs (3.3.8)

AAA level (Optional)

🧩 Markup rules

  • Every component has a role and an accessible name (1.3.6)
  • If a link label is too generic, visually hidden context is linked to it (2.4.9)
  • Abbreviations expanded in a tooltip use the abbr element (3.1.4)
  • Authentication forms fields use the autocomplete and inputmode attributes (3.3.8)

🫟 Styling rules

  • Font sizes, margins and paddings use relative units (em, rem) (1.4.8)
  • Text width is no more than 80 characters per line (40 if CJK) (1.4.8)
  • Text is not justified (1.4.8)
  • Line height is at least 1.5 in paragraphs (1.4.8)
  • Space between paragraphs is at least 2.25 (1.4.8)
  • Content does not flash more than 3 times in a second (2.3.2)
  • Content respects the user's preferences for reduced motion (2.3.3)
  • Focused elements are fully visible, not masked by any other element (2.4.12)
  • The website focus indicator is at least 2px wide (2.4.13)
  • Contrast ratio for the website focus indicator is at least 3:1 (2.4.13)

🧬 Functionality

  • The entire page can be operated with keyboard alone (2.1.3)
  • The website does not use time limits, except for live events and non interactive media (2.2.3)
  • The user can turn off or delay interruptions (2.2.4)
  • User data is saved automatically, and restored after a session interruption (2.2.5)
  • User data is preserved for more than 20 hours after inactivity (2.2.6)
  • The user is never restricted to a mode of interaction (mouse, keyboard, touch...) (2.5.6)
  • The page content does not change automatically (feed refresh, next step...) (3.2.5)
  • Help in non-trivial forms or complex steps is implemented (3.3.5)
  • Every data submission can be reviewed and confirmed, or cancelled by the user (3.3.6)
  • Authentication forms do not prevent from pasting content (3.3.8)

Released under the MIT License