---
description: Image alternative text accessibility compliance and WCAG 2.2 requirements
globs: *.vue, *.jsx, *.tsx, *.html, *.php, *.js, *.ts, *.liquid, *.css, *.scss, *.sass, *.less
alwaysApply: true
---
# Image Alt Text Accessibility Standards

Ensures images have appropriate alternative text following WCAG 2.2 requirements for informative, decorative, and functional images.

<rule>
name: image_alt_text_accessibility_standards
description: Enforce image alternative text accessibility standards per WCAG 2.2 requirements
filters:
  - type: file_extension
    pattern: "\\.(vue|jsx|tsx|html|liquid|php|js|ts|css|scss|sass|less)$"

actions:
  - type: enforce
    conditions:
      # Missing alt attribute on img elements
      - pattern: "<img[^>]*>"
        pattern_negate: "alt=\"[^\"]*\""
        message: "All img elements must have an alt attribute. Use alt=\"\" for decorative images or provide meaningful description for informative images."

      # Empty alt on informative images (likely missing description)
      - pattern: "<img[^>]*alt=\"\"[^>]*>"
        pattern_negate: "(aria-hidden=\"true\"|role=\"presentation\"|decorative|background)"
        message: "Empty alt attributes should only be used for decorative images. Provide meaningful alt text for informative images."

      # SVG img missing alt attribute
      - pattern: "<img[^>]*\\.svg[^>]*>"
        pattern_negate: "alt=\"[^\"]+\""
        message: "SVG images using img element must have alt attribute and role=\"img\"."

      # SVG img missing role attribute
      - pattern: "<img[^>]*\\.svg[^>]*>"
        pattern_negate: "role=\"img\""
        message: "SVG images using img element must have role=\"img\" attribute."

      # Inline SVG missing text alternative
      - pattern: "<svg[^>]*>"
        pattern_negate: "(aria-label=\"[^\"]+\"|aria-labelledby=\"[^\"]+\"|<title>|<desc>)"
        message: "Inline SVG elements must have text alternative via aria-label, aria-labelledby, or title/desc elements."

      # Decorative SVG missing aria-hidden
      - pattern: "<svg[^>]*>"
        pattern_negate: "(aria-hidden=\"true\"|aria-label|aria-labelledby|<title>|<desc>)"
        message: "Decorative SVG elements must have aria-hidden=\"true\" to hide from assistive technology."

      # Informative SVG missing role and accessible name
      - pattern: "<svg[^>]*>"
        pattern_negate: "(role=\"img\"|aria-hidden=\"true\")"
        message: "Informative SVG elements must have role=\"img\" and accessible name via aria-label, aria-labelledby, or title/desc elements."

      # SVG with role=\"img\" but missing accessible name
      - pattern: "<svg[^>]*role=\"img\"[^>]*>"
        pattern_negate: "(aria-label=\"[^\"]+\"|aria-labelledby=\"[^\"]+\"|<title>|<desc>)"
        message: "SVG elements with role=\"img\" must have accessible name via aria-label, aria-labelledby, or title/desc elements."

      # Image links missing descriptive alt text
      - pattern: "<a[^>]*>\\s*<img[^>]*>"
        pattern_negate: "alt=\"[^\"]{10,}\""
        message: "Image links should have descriptive alt text that describes the link destination."

      # Button/control images missing purpose description
      - pattern: "<(button|input)[^>]*>\\s*<img[^>]*>"
        pattern_negate: "alt=\"[^\"]{5,}\""
        message: "Button/control images should have alt text describing the purpose or resulting action."

      # Background images with information missing alternative
      - pattern: "background.*url.*\\.(jpg|jpeg|png|gif|svg|webp)"
        pattern_negate: "(aria-label|role=\"img\"|alt=|title=)"
        message: "Background images conveying information must have alternative text via visible text, aria-label, or role=\"img\"."

      # Active background images missing accessible name
      - pattern: "<(a|button)[^>]*>\\s*<[^>]*background.*url"
        pattern_negate: "(aria-label|aria-labelledby|title=)"
        message: "Active elements with background images must have accessible name via aria-label or similar."

      # Images of text without justification
      - pattern: "<img[^>]*alt=\"[^\"]*[A-Za-z]{10,}[^\"]*\"[^>]*>"
        pattern_negate: "(logo|essential|font.*customizable|size.*customizable)"
        message: "Images containing text should use real text unless essential (like logos) or font/size/color are customizable."

      # Alt text too long (over 250 characters)
      - pattern: "alt=\"[^\"]{250,}\""
        message: "Alternative text should be concise (no more than 250 characters). Consider using aria-describedby for longer descriptions."

      # Alt text includes unnecessary image identification
      - pattern: "alt=\"[^\"]*(?:image of|picture of|graphic of|photo of|icon of)[^\"]*\""
        message: "Avoid phrases like 'image of' or 'graphic of' in alt text. Screen readers already announce the element type."

      # Complex images missing extended description
      - pattern: "<img[^>]*alt=\"[^\"]{50,}\"[^>]*>"
        pattern_negate: "(aria-describedby|longdesc=)"
        message: "Complex images with long alt text should have extended description via aria-describedby or longdesc."

      # Decorative images with unnecessary alt text
      - pattern: "<img[^>]*alt=\"[^\"]+\"[^>]*>"
        pattern_negate: "(informative|functional|link|button)"
        message: "Consider using alt=\"\" for purely decorative images to avoid screen reader announcement."

  - type: suggest
    message: |
      **WCAG 2.2 Image Alt Text Requirements:**

      **Informative Images and Active Images (Links, Buttons, Controls):**
      - **Required:** All images MUST have alternative text
      - **Meaningful:** Alt text MUST accurately convey the image's purpose and author's intent
      - **Concise:** Alt text SHOULD be no more than 250 characters
      - **Avoid Redundancy:** Don't include words like "image of," "graphic of," etc.

      **Image Types and Requirements:**

      **1. Standard Images (<img>):**
      ```html
      <!-- Informative image -->
      <img src="chart.png" alt="Sales increased 25% in Q3 compared to Q2">

      <!-- Decorative image -->
      <img src="decorative-border.png" alt="" role="presentation">

      <!-- Image link -->
      <a href="/products">
        <img src="product-catalog.png" alt="Browse our complete product catalog">
      </a>
      ```

      **2. SVG Images:**
      ```html
      <!-- SVG as img -->
      <img src="icon.svg" alt="Close dialog" role="img">

      <!-- Informative inline SVG -->
      <svg role="img" aria-label="Settings icon" viewBox="0 0 24 24">
        <path d="M12 15.5A3.5 3.5 0 0 1 8.5 12A3.5 3.5 0 0 1 12 8.5A3.5 3.5 0 0 1 15.5 12A3.5 3.5 0 0 1 12 15.5M19.43 12.97C19.47 12.65 19.5 12.33 19.5 12C19.5 11.67 19.47 11.34 19.43 11L21.54 9.37C21.73 9.22 21.78 8.95 21.66 8.73L19.66 5.27C19.54 5.05 19.27 4.96 19.05 5.05L16.56 6.05C16.04 5.66 15.5 5.32 14.87 5.07L14.5 2.42C14.46 2.18 14.25 2 14 2H10C9.75 2 9.54 2.18 9.5 2.42L9.13 5.07C8.5 5.32 7.96 5.66 7.44 6.05L4.95 5.05C4.73 4.96 4.46 5.05 4.34 5.27L2.34 8.73C2.22 8.95 2.27 9.22 2.46 9.37L4.57 11C4.53 11.34 4.5 11.67 4.5 12C4.5 12.33 4.53 12.65 4.57 12.97L2.46 14.63C2.27 14.78 2.22 15.05 2.34 15.27L4.34 18.73C4.46 18.95 4.73 19.03 4.95 18.95L7.44 17.94C7.96 18.34 8.5 18.68 9.13 18.93L9.5 21.58C9.54 21.82 9.75 22 10 22H14C14.25 22 14.46 21.82 14.5 21.58L14.87 18.93C15.5 18.68 16.04 18.34 16.56 17.94L19.05 18.95C19.27 19.03 19.54 18.95 19.66 18.73L21.66 15.27C21.78 15.05 21.73 14.78 21.54 14.63L19.43 12.97Z"/>
      </svg>

      <!-- Decorative inline SVG -->
      <svg aria-hidden="true" viewBox="0 0 24 24">
        <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
      </svg>

      <!-- SVG with title and desc -->
      <svg role="img" aria-labelledby="chart-title chart-desc" viewBox="0 0 400 300">
        <title id="chart-title">Monthly Sales Chart</title>
        <desc id="chart-desc">Bar chart showing sales data for January through December 2023</desc>
        <!-- SVG content -->
      </svg>
      ```

      **SVG Accessibility Requirements:**
      SVGs must be properly categorized and labeled for accessibility:

      **1. Decorative SVGs:**
      - Use `aria-hidden="true"` to hide from assistive technology
      - No role or accessible name needed
      - Examples: background patterns, visual dividers, purely aesthetic elements

      **2. Informative SVGs:**
      - Use `role="img"` to identify as image
      - Provide accessible name via `aria-label`, `aria-labelledby`, or `<title>`/`<desc>` elements
      - Examples: icons with meaning, charts, diagrams, functional graphics

      **3. SVG Implementation Options:**
      ```html
      <!-- Option 1: aria-label (preferred for simple descriptions) -->
      <svg role="img" aria-label="Close dialog" viewBox="0 0 24 24">
        <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
      </svg>

      <!-- Option 2: title and desc elements (for complex descriptions) -->
      <svg role="img" aria-labelledby="chart-title chart-desc" viewBox="0 0 400 300">
        <title id="chart-title">Monthly Sales Chart</title>
        <desc id="chart-desc">Bar chart showing sales data for January through December 2023</desc>
        <!-- SVG content -->
      </svg>

      <!-- Option 3: Decorative SVG -->
      <svg aria-hidden="true" viewBox="0 0 24 24">
        <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
      </svg>
      ```

      **3. Background Images:**
      ```html
      <!-- Informative background with visible text -->
      <div class="hero-section" style="background-image: url('hero-bg.jpg')">
        <h1>Welcome to Our Store</h1>
        <p>Discover amazing products</p>
      </div>

      <!-- Active background image -->
      <button class="icon-button"
              style="background-image: url('close-icon.svg')"
              aria-label="Close dialog">
      </button>

      <!-- Decorative background -->
      <div class="decorative-bg" style="background-image: url('pattern.png')">
        <!-- Content without alt text needed -->
      </div>
      ```

      **4. Complex Images with Extended Descriptions:**
      ```html
      <!-- Complex chart with extended description -->
      <img src="complex-chart.png"
           alt="Sales performance chart for 2023"
           aria-describedby="chart-description">
      <div id="chart-description" class="sr-only">
        Detailed description: The chart shows quarterly sales data with Q1 at $2.3M,
        Q2 at $2.8M, Q3 at $3.1M, and Q4 at $3.5M. The trend shows consistent
        growth throughout the year with the highest growth in Q4.
      </div>
      ```

      **5. Button and Control Images:**
      ```html
      <!-- Button with image -->
      <button aria-label="Add item to cart">
        <img src="cart-icon.svg" alt="" role="presentation">
      </button>

      <!-- Image button -->
      <input type="image"
             src="submit-button.png"
             alt="Submit order"
             aria-label="Submit your order">
      ```

      **Alt Text Guidelines:**

      **Good Examples:**
      - `alt="Company logo"` (for logos)
      - `alt="Close dialog"` (for close buttons)
      - `alt="Submit form"` (for submit buttons)
      - `alt="Sales increased 25% in Q3"` (for charts)
      - `alt="Product image: Red wireless headphones"` (for products)
      - `alt="Team photo: 5 employees in office"` (for photos)

      **Avoid These:**
      - `alt="Image of a chart"` (redundant)
      - `alt="Click here"` (not descriptive)
      - `alt="Picture of a button"` (unnecessary)
      - `alt="Graphic showing data"` (too vague)

      **Decorative Images:**
      ```html
      <!-- Use empty alt for decorative images -->
      <img src="decorative-border.png" alt="" role="presentation">

      <!-- Or use aria-hidden -->
      <img src="background-pattern.png" alt="" aria-hidden="true">
      ```

      **Images of Text:**
      ```html
      <!-- Avoid unless essential -->
      <img src="company-slogan.png" alt="Innovation through excellence"
           aria-label="Company slogan">

      <!-- Better: Use real text -->
      <h2>Innovation through excellence</h2>
      ```

      **CSS Considerations:**
      ```css
      /* Screen reader only class */
      .sr-only {
        position: absolute;
        width: 1px;
        height: 1px;
        padding: 0;
        margin: -1px;
        overflow: hidden;
        clip: rect(0, 0, 0, 0);
        white-space: nowrap;
        border: 0;
      }

      /* Background image with fallback */
      .hero-section {
        background-image: url('hero-bg.jpg');
        background-size: cover;
        background-position: center;
      }

      /* Ensure text over background images has sufficient contrast */
      .hero-section h1 {
        color: #ffffff;
        text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.7);
      }
      ```

      **Testing and Validation:**
      - Test with screen readers (NVDA, JAWS, VoiceOver)
      - Use browser dev tools to inspect alt attributes
      - Validate with automated accessibility tools
      - Test keyboard navigation for image links/buttons
      - Verify contrast ratios for text over background images
      - Check that decorative images don't announce to screen readers
      - Test SVG accessibility with screen readers
      - Verify decorative SVGs are hidden with aria-hidden="true"
      - Check informative SVGs announce their accessible names
      - Validate SVG role="img" and accessible name combinations

      **Common Mistakes to Avoid:**
      - Missing alt attributes on informative images
      - Using "image of" or "picture of" in alt text
      - Providing alt text for decorative images
      - Using images of text when real text would work
      - Missing accessible names on image buttons
      - Insufficient contrast for text over background images
      - Not providing extended descriptions for complex images
      - Missing aria-hidden="true" on decorative SVGs
      - Missing role="img" on informative SVGs
      - SVGs without accessible names or aria-hidden
      - Using decorative SVGs without hiding from assistive technology

metadata:
  priority: high
  version: 1.0
</rule>
