> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qaos.machdel.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Accessibility

> Issues that prevent users with disabilities from accessing or using your application — including keyboard navigation, screen reader support, and visual perception.

Accessibility issues affect users who rely on assistive technologies — screen readers, keyboard navigation, voice control, and screen magnifiers. In many jurisdictions, web accessibility compliance is legally required.

***

## missing-form-labels

<Badge>Medium</Badge> WCAG 1.3.1, 2.4.6

**What it is**

Form input elements have no associated label, making their purpose unclear to screen readers and assistive technologies.

**Why it matters**

Screen reader users navigate forms by cycling through labeled inputs. An unlabeled field is announced as "edit text" or "text field" with no indication of what it's for. This makes the form effectively unusable without sight.

**How QAOS detects it**

The agent scans the DOM for `<input>`, `<textarea>`, and `<select>` elements that lack an associated `<label>` (via `for`/`id` pairing), `aria-label`, or `aria-labelledby` attribute.

**Examples**

```html theme={null}
<!-- Missing label -->
<input type="email" name="email" placeholder="Enter email">

<!-- Correct: explicit label -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">

<!-- Correct: aria-label -->
<input type="search" aria-label="Search products">
```

**How to fix**

Associate every form field with a visible label using `<label for="...">`, or provide an accessible name via `aria-label` or `aria-labelledby`. Placeholder text is **not** a substitute for a label.

***

## button-no-text

<Badge>Medium</Badge> WCAG 4.1.2

**What it is**

Buttons have no visible text, making their purpose ambiguous to all users — especially those who cannot see icons or who use screen readers.

**How QAOS detects it**

The agent captures a screenshot and identifies buttons that contain no visible text content — including icon-only buttons where the icon has no accessible label.

**Examples**

```html theme={null}
<!-- Empty button — no indication of purpose -->
<button type="submit"></button>

<!-- Icon button with no accessible name -->
<button><svg>...</svg></button>

<!-- Correct: icon button with accessible label -->
<button aria-label="Delete item"><svg>...</svg></button>
```

**How to fix**

For icon-only buttons, add `aria-label` with a descriptive action. For buttons with hidden text, use `sr-only` CSS or `aria-label` instead of `display:none`:

```html theme={null}
<button aria-label="Save document">
  <svg>...</svg>
</button>
```

***

## missing-alt-text

<Badge>Medium</Badge> WCAG 1.1.1

**What it is**

`<img>` elements have no `alt` attribute at all. This is distinct from an empty `alt=""` — a missing `alt` attribute causes screen readers to announce the image filename instead.

**How QAOS detects it**

The agent scans the DOM for `<img>` elements where the `alt` attribute is absent entirely.

**Examples**

```html theme={null}
<!-- Missing alt — screen reader announces filename -->
<img src="company-logo.png">

<!-- Correct: descriptive alt -->
<img src="company-logo.png" alt="Acme Corporation">

<!-- Correct: decorative image (empty alt) -->
<img src="divider.png" alt="">
```

**How to fix**

Add an `alt` attribute to every `<img>` element. For images that convey information, write a concise description. For purely decorative images, use `alt=""` (empty string) to tell screen readers to skip it.

***

## empty-alt-informative-image

<Badge>Low</Badge> WCAG 1.1.1

**What it is**

Images with an empty `alt=""` attribute that actually convey meaningful information — such as charts, infographics, or product photos that a user needs to understand the content.

**How QAOS detects it**

The agent identifies `<img alt="">` elements and uses LLM-based analysis to determine whether the image appears to convey information (based on filename, surrounding context, and image content).

**Examples**

```html theme={null}
<!-- Informative image incorrectly marked as decorative -->
<img src="revenue-chart-2024.png" alt="">
<img src="product-photo.jpg" alt="">
```

**How to fix**

Provide a descriptive alt text for informative images. Reserve `alt=""` for genuinely decorative images:

```html theme={null}
<img src="revenue-chart-2024.png" alt="Revenue chart showing 40% growth in Q3 2024">
```

***

## insufficient-color-contrast

<Badge>Medium</Badge> WCAG 1.4.3

**What it is**

Text elements have a foreground-to-background color contrast ratio below the WCAG minimum of **4.5:1** for normal text (3:1 for large text). This makes text hard or impossible to read for users with low vision or color blindness.

**How QAOS detects it**

The agent computes the actual contrast ratio between text and background colors from computed CSS styles and flags any text below the threshold.

**Examples**

```css theme={null}
/* Failing: light gray on white — ratio ~2.8:1 */
color: #999999;
background: #ffffff;

/* Passing: dark gray on white — ratio ~7:1 */
color: #595959;
background: #ffffff;
```

**How to fix**

Use a contrast checker tool ([WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)) to verify all text/background combinations. Aim for at least 4.5:1 for body text and 3:1 for large text (18pt+ or 14pt+ bold).

***

## text-too-small

<Badge>Medium</Badge> WCAG 1.4.4

**What it is**

Text has a font size below **14 pixels**, making it difficult to read — especially for older users, users with low vision, or users on high-density displays.

**How QAOS detects it**

The agent computes the rendered font size of all text nodes from computed CSS and flags any below 14px.

**How to fix**

Set a minimum font size of 14px for all body text. Use relative units (`em`, `rem`) rather than pixels so users can scale text with browser settings:

```css theme={null}
body { font-size: 1rem; }       /* 16px default */
.caption { font-size: 0.875rem; } /* 14px */
```

***

## not-keyboard-reachable

<Badge>High</Badge> WCAG 2.1.1

**What it is**

Interactive elements — elements that respond to click events — cannot be reached by tabbing with the keyboard. This affects `<div>` or `<span>` elements used as buttons, custom dropdowns, and any non-native interactive component that lacks a `tabindex` attribute.

**Why it matters**

Users who cannot use a mouse (motor disabilities, power users, keyboard navigators) rely entirely on the Tab key to reach interactive elements. An unreachable element is completely inaccessible to them.

**How QAOS detects it**

The agent identifies elements with click handlers or interactive roles that are not natively focusable (not a `<button>`, `<a>`, `<input>`, etc.) and checks whether they have `tabindex` or appropriate ARIA role.

**Examples**

```html theme={null}
<!-- Unreachable: div with click handler, no tabindex -->
<div onclick="openModal()">Open Settings</div>

<!-- Correct: button element (natively focusable) -->
<button onclick="openModal()">Open Settings</button>

<!-- Correct: div with tabindex and role -->
<div role="button" tabindex="0" onclick="openModal()">Open Settings</div>
```

**How to fix**

Use native HTML elements (`<button>`, `<a>`, `<input>`) wherever possible — they are focusable by default. For custom interactive elements, add `tabindex="0"` and the appropriate ARIA `role`.

***

## not-keyboard-activatable

<Badge>High</Badge> WCAG 2.1.1

**What it is**

Elements that can be focused via keyboard (either natively or via `tabindex`) but cannot be **activated** using keyboard input. Typically custom button-like elements that only respond to mouse clicks, not `Enter` or `Space`.

**How QAOS detects it**

The agent tabs to focusable elements and presses `Enter` and `Space`, checking whether the element responds in the same way as a mouse click.

**Examples**

```html theme={null}
<!-- Focusable but not keyboard-activatable -->
<div tabindex="0" onclick="handleAction()">Click Me</div>
```

**How to fix**

Add keyboard event handlers to custom interactive elements:

```javascript theme={null}
element.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault()
    handleAction()
  }
})
```

Or better, replace the custom element with a native `<button>` which handles this automatically.

***

## missing-focus-indicator

<Badge>Medium</Badge> WCAG 2.4.7

**What it is**

Interactive elements have their default focus ring removed via CSS (`outline: none` or `outline: 0`) with no alternative focus indicator provided.

**Why it matters**

Keyboard users need to know which element is currently focused. Without a visible focus indicator, keyboard navigation becomes blind navigation.

**How QAOS detects it**

The agent tabs to interactive elements and captures a screenshot, using LLM-based analysis to determine whether a visible focus indicator is present.

**How to fix**

Never use `outline: none` without providing an alternative focus style:

```css theme={null}
/* Don't do this */
:focus { outline: none; }

/* Do this instead */
:focus-visible {
  outline: 2px solid #8265fd;
  outline-offset: 2px;
}
```

***

## color-only-distinction

<Badge>High</Badge> WCAG 1.4.1

**What it is**

Critical information is conveyed using color as the **only** visual differentiator — no text label, symbol, icon, pattern, or shape difference accompanies the color cue.

**Why it matters**

Approximately 8% of men and 0.5% of women have some form of color vision deficiency. When color is the sole indicator of meaning (e.g., a red border meaning "required"), those users receive no information at all. This affects all colorblind users, as well as users on monochrome displays.

**How QAOS detects it**

The agent captures a screenshot and analyzes elements where color appears to be the sole distinguishing factor — for example, required fields marked only with a red border and no asterisk, text, or icon.

**Examples**

```html theme={null}
<!-- Only color distinguishes required — inaccessible -->
<input type="text" style="border-color: red;">

<!-- Correct: color + text marker -->
<label>Name <span aria-hidden="true" style="color: red;">*</span></label>
<input type="text" aria-required="true">
```

**How to fix**

Always combine color with at least one other visual cue — text, icon, pattern, or shape:

* Required fields: add an asterisk or "required" label text
* Status indicators: add text labels ("Error", "Success", "Warning")
* Charts: use patterns or direct labels in addition to color coding

***

## image-as-text

<Badge>Medium</Badge> WCAG 1.4.5

**What it is**

Meaningful text is rendered as a rasterized image (PNG, JPG, GIF) rather than actual HTML text. This makes the text unzoomable, unsearchable, unable to be restyled, and often missing from screen reader output.

**Why it matters**

Users who need to zoom text, adjust font size, change contrast, or copy text cannot do so when the "text" is actually a pixel image. Search engines also cannot index image text, reducing discoverability.

**How QAOS detects it**

The agent captures a screenshot and uses visual analysis to identify images that appear to contain meaningful text — such as headings, promotional messages, or navigation labels — without an equivalent readable text alternative.

**Examples**

```html theme={null}
<!-- Text rendered as image — unzoomable, unsearchable -->
<img src="sale-banner.png" alt="">

<!-- Correct: real HTML text with CSS styling -->
<h2 class="sale-banner">Summer Sale — 30% Off Everything</h2>
```

**How to fix**

Replace image-based text with styled HTML text. Use CSS for custom fonts, colors, and visual effects. If a logo or brand mark must be an image, provide a descriptive `alt` attribute.

***

## iframe-missing-title

<Badge>Medium</Badge> WCAG 4.1.2

**What it is**

An `<iframe>` element has no `title` attribute, making it impossible for screen reader users to understand the purpose of the embedded content before deciding to enter it.

**Why it matters**

Screen readers announce iframes by their title before allowing the user to enter them. Without a title, the iframe is announced as "frame" with no indication of what it contains — forcing users to enter and explore just to understand the context.

**How QAOS detects it**

The agent scans the DOM for `<iframe>` elements with no `title` attribute.

**Examples**

```html theme={null}
<!-- No title — screen reader announces "frame" -->
<iframe src="payment.html" width="600" height="400"></iframe>

<!-- Correct: descriptive title -->
<iframe src="payment.html" title="Secure payment form" width="600" height="400"></iframe>
```

**How to fix**

Add a concise, descriptive `title` attribute to every `<iframe>`:

```html theme={null}
<iframe src="map-embed.html" title="Map showing our office location"></iframe>
<iframe src="video-player.html" title="Product demo video"></iframe>
```
