# ============================================================ # WCAG Accessibility Rules # Based on: W3C WCAG 2.0, 2.1, 2.2 + axe-core Rule Mapping # ============================================================ metadata: name: "WCAG Accessibility Standards" version: "1.0.0" last_updated: "2026-02-13" sources: - name: "Web Content Accessibility Guidelines (WCAG) 2.2" url: "https://www.w3.org/TR/WCAG22/" version: "2.2" date: "2023-10-05" - name: "Web Content Accessibility Guidelines (WCAG) 2.1" url: "https://www.w3.org/TR/WCAG21/" version: "2.1" date: "2018-06-05" - name: "Web Content Accessibility Guidelines (WCAG) 2.0" url: "https://www.w3.org/TR/WCAG20/" version: "2.0" date: "2008-12-11" - name: "axe-core Rule Descriptions" url: "https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md" - name: "axe-core API Documentation" url: "https://www.deque.com/axe/core-documentation/api-documentation/" # ============================================================ # axe-core Tag Mapping # These tags control which rules axe-core runs # IMPORTANT: Tags are NOT inclusive - wcag2aa only runs AA rules, # NOT A rules. Combine tags for full compliance testing. # ============================================================ axe_core_tags: wcag20: - tag: "wcag2a" description: "WCAG 2.0 Level A rules only" - tag: "wcag2aa" description: "WCAG 2.0 Level AA rules only" - tag: "wcag2aaa" description: "WCAG 2.0 Level AAA rules only" wcag21: - tag: "wcag21a" description: "WCAG 2.1 Level A rules only (new in 2.1)" - tag: "wcag21aa" description: "WCAG 2.1 Level AA rules only (new in 2.1)" wcag22: - tag: "wcag22aa" description: "WCAG 2.2 Level AA rules only (new in 2.2)" other: - tag: "best-practice" description: "Common accessibility best practices (not WCAG-specific)" - tag: "section508" description: "Section 508 compliance rules" # Compliance presets (combine tags for full testing) compliance_presets: wcag_20_a: tags: ["wcag2a"] description: "WCAG 2.0 Level A compliance" wcag_20_aa: tags: ["wcag2a", "wcag2aa"] description: "WCAG 2.0 Level AA compliance" wcag_21_aa: tags: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa"] description: "WCAG 2.1 Level AA compliance (most common requirement)" wcag_22_aa: tags: ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"] description: "WCAG 2.2 Level AA compliance (latest standard)" wcag_22_full: tags: ["wcag2a", "wcag2aa", "wcag2aaa", "wcag21a", "wcag21aa", "wcag22aa"] description: "WCAG 2.2 all levels including AAA" # ============================================================ # WCAG 2.2 Complete Success Criteria # Total: 86 criteria (4.1.1 Parsing removed in 2.2) # Distribution: Level A (32), Level AA (24), Level AAA (30) # ============================================================ principles: # ======================================================== # Principle 1: PERCEIVABLE # ======================================================== - id: "perceivable" name: "Perceivable" description: "Information and user interface components must be presentable to users in ways they can perceive" guidelines: # --- 1.1 Text Alternatives --- - id: "1.1" name: "Text Alternatives" description: "Provide text alternatives for any non-text content" criteria: - id: "1.1.1" name: "Non-text Content" level: "A" since: "2.0" description: "All non-text content has a text alternative that serves the equivalent purpose" axe_rules: ["image-alt", "input-image-alt", "area-alt", "object-alt", "svg-img-alt"] # --- 1.2 Time-based Media --- - id: "1.2" name: "Time-based Media" description: "Provide alternatives for time-based media" criteria: - id: "1.2.1" name: "Audio-only and Video-only (Prerecorded)" level: "A" since: "2.0" description: "An alternative is provided for prerecorded audio-only and video-only media" axe_rules: ["audio-caption", "video-caption"] - id: "1.2.2" name: "Captions (Prerecorded)" level: "A" since: "2.0" description: "Captions are provided for all prerecorded audio content in synchronized media" axe_rules: ["video-caption"] - id: "1.2.3" name: "Audio Description or Media Alternative (Prerecorded)" level: "A" since: "2.0" description: "An alternative for time-based media or audio description is provided" axe_rules: ["video-description"] - id: "1.2.4" name: "Captions (Live)" level: "AA" since: "2.0" description: "Captions are provided for all live audio content in synchronized media" - id: "1.2.5" name: "Audio Description (Prerecorded)" level: "AA" since: "2.0" description: "Audio description is provided for all prerecorded video content" - id: "1.2.6" name: "Sign Language (Prerecorded)" level: "AAA" since: "2.0" description: "Sign language interpretation is provided for prerecorded audio" - id: "1.2.7" name: "Extended Audio Description (Prerecorded)" level: "AAA" since: "2.0" description: "Extended audio description is provided when pauses are insufficient" - id: "1.2.8" name: "Media Alternative (Prerecorded)" level: "AAA" since: "2.0" description: "A text alternative is provided for all prerecorded synchronized media" - id: "1.2.9" name: "Audio-only (Live)" level: "AAA" since: "2.0" description: "A text alternative is provided for live audio-only content" # --- 1.3 Adaptable --- - id: "1.3" name: "Adaptable" description: "Create content that can be presented in different ways without losing information" criteria: - id: "1.3.1" name: "Info and Relationships" level: "A" since: "2.0" description: "Information, structure, and relationships can be programmatically determined" axe_rules: ["aria-required-parent", "aria-required-children", "definition-list", "dlitem", "list", "listitem", "th-has-data-cells", "td-headers-attr", "p-as-heading"] - id: "1.3.2" name: "Meaningful Sequence" level: "A" since: "2.0" description: "Correct reading sequence can be programmatically determined" - id: "1.3.3" name: "Sensory Characteristics" level: "A" since: "2.0" description: "Instructions do not rely solely on sensory characteristics" - id: "1.3.4" name: "Orientation" level: "AA" since: "2.1" description: "Content does not restrict viewing to a single display orientation" - id: "1.3.5" name: "Identify Input Purpose" level: "AA" since: "2.1" description: "Input field purpose can be programmatically determined" axe_rules: ["autocomplete-valid"] - id: "1.3.6" name: "Identify Purpose" level: "AAA" since: "2.1" description: "The purpose of UI components, icons, and regions can be programmatically determined" # --- 1.4 Distinguishable --- - id: "1.4" name: "Distinguishable" description: "Make it easier for users to see and hear content" criteria: - id: "1.4.1" name: "Use of Color" level: "A" since: "2.0" description: "Color is not the only visual means of conveying information" axe_rules: ["link-in-text-block"] - id: "1.4.2" name: "Audio Control" level: "A" since: "2.0" description: "Mechanism to pause/stop/control volume of auto-playing audio" axe_rules: ["no-autoplay-audio"] - id: "1.4.3" name: "Contrast (Minimum)" level: "AA" since: "2.0" description: "Text has contrast ratio of at least 4.5:1 (3:1 for large text)" axe_rules: ["color-contrast"] - id: "1.4.4" name: "Resize Text" level: "AA" since: "2.0" description: "Text can be resized up to 200% without loss of content or functionality" axe_rules: ["meta-viewport-large"] - id: "1.4.5" name: "Images of Text" level: "AA" since: "2.0" description: "Text is used instead of images of text where possible" - id: "1.4.6" name: "Contrast (Enhanced)" level: "AAA" since: "2.0" description: "Text has contrast ratio of at least 7:1 (4.5:1 for large text)" axe_rules: ["color-contrast-enhanced"] - id: "1.4.7" name: "Low or No Background Audio" level: "AAA" since: "2.0" description: "Prerecorded speech audio has low or no background noise" - id: "1.4.8" name: "Visual Presentation" level: "AAA" since: "2.0" description: "Text blocks have configurable visual presentation" - id: "1.4.9" name: "Images of Text (No Exception)" level: "AAA" since: "2.0" description: "Images of text are only used for pure decoration or essential cases" - id: "1.4.10" name: "Reflow" level: "AA" since: "2.1" description: "Content can reflow without scrolling in two dimensions at 320px/256px" - id: "1.4.11" name: "Non-text Contrast" level: "AA" since: "2.1" description: "UI components and graphics have contrast ratio of at least 3:1" - id: "1.4.12" name: "Text Spacing" level: "AA" since: "2.1" description: "Content adapts to specified text spacing without loss" - id: "1.4.13" name: "Content on Hover or Focus" level: "AA" since: "2.1" description: "Hoverable/focusable additional content is dismissible, hoverable, persistent" # ======================================================== # Principle 2: OPERABLE # ======================================================== - id: "operable" name: "Operable" description: "User interface components and navigation must be operable" guidelines: # --- 2.1 Keyboard Accessible --- - id: "2.1" name: "Keyboard Accessible" description: "Make all functionality available from a keyboard" criteria: - id: "2.1.1" name: "Keyboard" level: "A" since: "2.0" description: "All functionality is operable through a keyboard interface" axe_rules: ["scrollable-region-focusable"] - id: "2.1.2" name: "No Keyboard Trap" level: "A" since: "2.0" description: "Keyboard focus can be moved away from any component" - id: "2.1.3" name: "Keyboard (No Exception)" level: "AAA" since: "2.0" description: "All functionality is operable through keyboard without exception" - id: "2.1.4" name: "Character Key Shortcuts" level: "A" since: "2.1" description: "Single character key shortcuts can be turned off or remapped" axe_rules: ["accesskeys"] # --- 2.2 Enough Time --- - id: "2.2" name: "Enough Time" description: "Provide users enough time to read and use content" criteria: - id: "2.2.1" name: "Timing Adjustable" level: "A" since: "2.0" description: "Time limits can be turned off, adjusted, or extended" axe_rules: ["meta-refresh"] - id: "2.2.2" name: "Pause, Stop, Hide" level: "A" since: "2.0" description: "Moving, blinking, scrolling, or auto-updating content can be controlled" axe_rules: ["blink", "marquee"] - id: "2.2.3" name: "No Timing" level: "AAA" since: "2.0" description: "Timing is not an essential part of the activity" - id: "2.2.4" name: "Interruptions" level: "AAA" since: "2.0" description: "Interruptions can be postponed or suppressed" - id: "2.2.5" name: "Re-authenticating" level: "AAA" since: "2.0" description: "Data is preserved when re-authenticating after session expiry" - id: "2.2.6" name: "Timeouts" level: "AAA" since: "2.1" description: "Users are warned about data loss from inactivity timeouts" # --- 2.3 Seizures and Physical Reactions --- - id: "2.3" name: "Seizures and Physical Reactions" description: "Do not design content that causes seizures or physical reactions" criteria: - id: "2.3.1" name: "Three Flashes or Below Threshold" level: "A" since: "2.0" description: "Pages do not contain content that flashes more than three times per second" - id: "2.3.2" name: "Three Flashes" level: "AAA" since: "2.0" description: "Pages do not contain any content that flashes more than three times per second" - id: "2.3.3" name: "Animation from Interactions" level: "AAA" since: "2.1" description: "Motion animation triggered by interaction can be disabled" # --- 2.4 Navigable --- - id: "2.4" name: "Navigable" description: "Provide ways to help users navigate, find content, and determine where they are" criteria: - id: "2.4.1" name: "Bypass Blocks" level: "A" since: "2.0" description: "Mechanism available to bypass blocks of content repeated on pages" axe_rules: ["bypass", "region"] - id: "2.4.2" name: "Page Titled" level: "A" since: "2.0" description: "Web pages have titles that describe topic or purpose" axe_rules: ["document-title"] - id: "2.4.3" name: "Focus Order" level: "A" since: "2.0" description: "Focus order preserves meaning and operability" axe_rules: ["tabindex"] - id: "2.4.4" name: "Link Purpose (In Context)" level: "A" since: "2.0" description: "Link purpose can be determined from link text or context" axe_rules: ["link-name"] - id: "2.4.5" name: "Multiple Ways" level: "AA" since: "2.0" description: "More than one way available to locate a page in a set" - id: "2.4.6" name: "Headings and Labels" level: "AA" since: "2.0" description: "Headings and labels describe topic or purpose" axe_rules: ["empty-heading"] - id: "2.4.7" name: "Focus Visible" level: "AA" since: "2.0" description: "Keyboard focus indicator is visible" - id: "2.4.8" name: "Location" level: "AAA" since: "2.0" description: "Information about the user's location within a set of pages is available" - id: "2.4.9" name: "Link Purpose (Link Only)" level: "AAA" since: "2.0" description: "Link purpose can be determined from link text alone" - id: "2.4.10" name: "Section Headings" level: "AAA" since: "2.0" description: "Section headings are used to organize content" - id: "2.4.11" name: "Focus Not Obscured (Minimum)" level: "AA" since: "2.2" description: "Focused component is not entirely hidden by author-created content" - id: "2.4.12" name: "Focus Not Obscured (Enhanced)" level: "AAA" since: "2.2" description: "No part of the focused component is hidden by author-created content" - id: "2.4.13" name: "Focus Appearance" level: "AAA" since: "2.2" description: "Focus indicator meets minimum area and contrast requirements" # --- 2.5 Input Modalities --- - id: "2.5" name: "Input Modalities" description: "Make it easier to operate through various inputs beyond keyboard" criteria: - id: "2.5.1" name: "Pointer Gestures" level: "A" since: "2.1" description: "Multipoint/path-based gestures have single-pointer alternatives" - id: "2.5.2" name: "Pointer Cancellation" level: "A" since: "2.1" description: "Functions using single pointer can be cancelled" - id: "2.5.3" name: "Label in Name" level: "A" since: "2.1" description: "Visible label is part of the accessible name" axe_rules: ["label-title-only"] - id: "2.5.4" name: "Motion Actuation" level: "A" since: "2.1" description: "Motion-activated functions have UI alternatives and can be disabled" - id: "2.5.5" name: "Target Size (Enhanced)" level: "AAA" since: "2.1" description: "Target size is at least 44 by 44 CSS pixels" - id: "2.5.6" name: "Concurrent Input Mechanisms" level: "A" since: "2.1" description: "Content does not restrict use of available input modalities" - id: "2.5.7" name: "Dragging Movements" level: "AA" since: "2.2" description: "Drag functions have single-pointer alternatives" - id: "2.5.8" name: "Target Size (Minimum)" level: "AA" since: "2.2" description: "Target size is at least 24 by 24 CSS pixels" axe_rules: ["target-size"] # ======================================================== # Principle 3: UNDERSTANDABLE # ======================================================== - id: "understandable" name: "Understandable" description: "Information and the operation of user interface must be understandable" guidelines: # --- 3.1 Readable --- - id: "3.1" name: "Readable" description: "Make text content readable and understandable" criteria: - id: "3.1.1" name: "Language of Page" level: "A" since: "2.0" description: "Default human language of each page can be programmatically determined" axe_rules: ["html-has-lang", "html-lang-valid"] - id: "3.1.2" name: "Language of Parts" level: "AA" since: "2.0" description: "Language of each passage or phrase can be programmatically determined" axe_rules: ["valid-lang"] - id: "3.1.3" name: "Unusual Words" level: "AAA" since: "2.0" description: "Mechanism is available for unusual words or jargon" - id: "3.1.4" name: "Abbreviations" level: "AAA" since: "2.0" description: "Mechanism for identifying expanded form of abbreviations" - id: "3.1.5" name: "Reading Level" level: "AAA" since: "2.0" description: "Supplemental content for text beyond lower secondary education level" - id: "3.1.6" name: "Pronunciation" level: "AAA" since: "2.0" description: "Mechanism for identifying pronunciation of ambiguous words" # --- 3.2 Predictable --- - id: "3.2" name: "Predictable" description: "Make web pages appear and operate in predictable ways" criteria: - id: "3.2.1" name: "On Focus" level: "A" since: "2.0" description: "Receiving focus does not initiate a change of context" - id: "3.2.2" name: "On Input" level: "A" since: "2.0" description: "Changing a UI component setting does not automatically cause a change of context" - id: "3.2.3" name: "Consistent Navigation" level: "AA" since: "2.0" description: "Navigation repeated on pages occurs in the same relative order" - id: "3.2.4" name: "Consistent Identification" level: "AA" since: "2.0" description: "Components with the same functionality are identified consistently" - id: "3.2.5" name: "Change on Request" level: "AAA" since: "2.0" description: "Changes of context are initiated only by user request" - id: "3.2.6" name: "Consistent Help" level: "A" since: "2.2" description: "Help mechanisms occur in the same relative order across pages" # --- 3.3 Input Assistance --- - id: "3.3" name: "Input Assistance" description: "Help users avoid and correct mistakes" criteria: - id: "3.3.1" name: "Error Identification" level: "A" since: "2.0" description: "Input errors are automatically detected and described to the user" axe_rules: ["aria-input-field-name"] - id: "3.3.2" name: "Labels or Instructions" level: "A" since: "2.0" description: "Labels or instructions are provided when content requires user input" axe_rules: ["label", "input-button-name", "select-name"] - id: "3.3.3" name: "Error Suggestion" level: "AA" since: "2.0" description: "Error suggestions are provided when errors are detected and suggestions are known" - id: "3.3.4" name: "Error Prevention (Legal, Financial, Data)" level: "AA" since: "2.0" description: "Submissions are reversible, checked, or confirmed for legal/financial/data" - id: "3.3.5" name: "Help" level: "AAA" since: "2.0" description: "Context-sensitive help is available" - id: "3.3.6" name: "Error Prevention (All)" level: "AAA" since: "2.0" description: "Submissions are reversible, checked, or confirmed for all user input" - id: "3.3.7" name: "Redundant Entry" level: "A" since: "2.2" description: "Previously entered information is auto-populated or available for selection" - id: "3.3.8" name: "Accessible Authentication (Minimum)" level: "AA" since: "2.2" description: "Cognitive function test is not required for authentication" - id: "3.3.9" name: "Accessible Authentication (Enhanced)" level: "AAA" since: "2.2" description: "No cognitive function test is required for authentication (no exceptions)" # ======================================================== # Principle 4: ROBUST # ======================================================== - id: "robust" name: "Robust" description: "Content must be robust enough to be interpreted by a wide variety of user agents" guidelines: # --- 4.1 Compatible --- - id: "4.1" name: "Compatible" description: "Maximize compatibility with current and future user agents" criteria: # Note: 4.1.1 Parsing was REMOVED in WCAG 2.2 # It was deemed obsolete as modern browsers handle parsing errors gracefully - id: "4.1.2" name: "Name, Role, Value" level: "A" since: "2.0" description: "Name, role, and value of all UI components can be programmatically determined" axe_rules: ["aria-allowed-attr", "aria-allowed-role", "aria-hidden-body", "aria-hidden-focus", "aria-roles", "aria-valid-attr", "aria-valid-attr-value", "button-name", "frame-title", "image-alt", "input-button-name", "input-image-alt", "label", "link-name", "select-name"] - id: "4.1.3" name: "Status Messages" level: "AA" since: "2.1" description: "Status messages can be programmatically determined without receiving focus" axe_rules: ["aria-progressbar-name"] # ============================================================ # Version Diff Summary # What's new in each version # ============================================================ version_diff: removed_in_22: - id: "4.1.1" name: "Parsing" reason: "Modern browsers handle parsing errors; criterion was obsolete" new_in_21: level_a: - "1.3.4 Orientation" # Note: Listed as A in some sources, AA in W3C spec - "2.1.4 Character Key Shortcuts" - "2.5.1 Pointer Gestures" - "2.5.2 Pointer Cancellation" - "2.5.3 Label in Name" - "2.5.4 Motion Actuation" - "2.5.6 Concurrent Input Mechanisms" level_aa: - "1.3.4 Orientation" - "1.3.5 Identify Input Purpose" - "1.4.10 Reflow" - "1.4.11 Non-text Contrast" - "1.4.12 Text Spacing" - "1.4.13 Content on Hover or Focus" level_aaa: - "1.3.6 Identify Purpose" - "2.2.6 Timeouts" - "2.3.3 Animation from Interactions" - "2.5.5 Target Size (Enhanced)" new_in_22: level_a: - "3.2.6 Consistent Help" - "3.3.7 Redundant Entry" level_aa: - "2.4.11 Focus Not Obscured (Minimum)" - "2.5.7 Dragging Movements" - "2.5.8 Target Size (Minimum)" - "3.3.8 Accessible Authentication (Minimum)" level_aaa: - "2.4.12 Focus Not Obscured (Enhanced)" - "2.4.13 Focus Appearance" - "3.3.9 Accessible Authentication (Enhanced)" # ============================================================ # Additional axe-core Best Practice Rules # (Not mapped to specific WCAG criteria but recommended) # ============================================================ best_practices: - id: "landmark-one-main" description: "Document should have one main landmark" severity: "major" - id: "landmark-complementary-is-top-level" description: "Aside/complementary should be top-level" severity: "minor" - id: "landmark-no-duplicate-banner" description: "Document should have at most one banner landmark" severity: "major" - id: "landmark-no-duplicate-contentinfo" description: "Document should have at most one contentinfo landmark" severity: "major" - id: "landmark-no-duplicate-main" description: "Document should have at most one main landmark" severity: "major" - id: "page-has-heading-one" description: "Page should contain a level-one heading" severity: "major" - id: "heading-order" description: "Heading levels should increase by one" severity: "minor" - id: "scope-attr-valid" description: "scope attribute should be used correctly" severity: "minor" - id: "skip-link" description: "Skip navigation link should be provided" severity: "minor" - id: "tabindex" description: "Tabindex should not be greater than zero" severity: "major" - id: "duplicate-id-active" description: "Active elements should not have duplicate IDs" severity: "critical" - id: "duplicate-id-aria" description: "ARIA IDs should be unique" severity: "critical" - id: "frame-tested" description: "Frames should be tested with axe-core" severity: "minor" - id: "aria-text" description: "Elements with role=text should have no focusable descendants" severity: "minor"