Skip to main content
Responsive design issues affect users on mobile devices, touch screens, and any context where the screen size or input method differs from a desktop with a mouse. These issues range from elements that are too small to tap to pages that require horizontal scrolling.

touch-target-too-small

Medium WCAG 2.5.5

What it is

Interactive elements — buttons, links, checkboxes, toggles — have a touch target area smaller than 44×44 CSS pixels. Small targets are difficult to activate accurately on touch screens, especially for users with motor impairments.

How QAOS detects it

The agent computes the rendered dimensions of interactive elements from computed CSS styles and flags any with a bounding box smaller than 44×44 pixels.

Examples

/* Too small: 24x24px icon button */
.icon-button {
  width: 24px;
  height: 24px;
}

/* Correct: minimum 44x44px touch target */
.icon-button {
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

How to fix

Set minimum dimensions of 44×44px on all interactive elements. If the visual appearance must be smaller (e.g., an 8px radio button), use padding to extend the touch target:
input[type="radio"] {
  width: 16px;
  height: 16px;
  padding: 14px; /* extends touch target to 44px */
}

touch-target-spacing-too-small

Low

What it is

Interactive elements are positioned too close together, increasing the risk that a user accidentally activates the wrong element. WCAG 2.5.8 recommends at least 8px of spacing between touch targets.

How QAOS detects it

The agent computes the positions of adjacent interactive elements and flags pairs that are closer than 8px apart.

Examples

/* Problematic: navigation links with 2px gap */
nav a {
  margin: 0 1px;
}

/* Correct: adequate spacing */
nav a {
  margin: 0 8px;
}

How to fix

Add sufficient margin or padding between adjacent interactive elements. Group related controls and space unrelated groups further apart.

horizontal-overflow

Medium

What it is

One or more elements extend beyond the viewport width, causing the page to require horizontal scrolling. This is almost always unintentional and indicates a responsive design issue.

How QAOS detects it

The agent checks the page’s computed layout to detect elements whose rendered width exceeds the viewport width.

Common causes

  • Fixed-width elements (e.g., width: 1200px on a small screen)
  • Tables without horizontal scroll wrappers
  • Images with width: auto but min-width constraints
  • Flex or grid children that don’t wrap at small sizes
  • Long unbreakable strings (URLs, email addresses) in text content

How to fix

Use relative units and responsive layout patterns:
/* Avoid fixed widths */
.container { width: 100%; max-width: 1200px; }

/* Images: respect viewport width */
img { max-width: 100%; height: auto; }

/* Tables: horizontal scroll wrapper */
.table-wrapper { overflow-x: auto; }

/* Long text: allow breaking */
.url-text { word-break: break-all; }

missing-page-title

High WCAG 2.4.2

What it is

The page lacks a <title> element in <head>, or the title is empty (<title></title>). Page titles are announced by screen readers when a page loads and are used as tab labels in browsers.

Why it matters

Screen reader users rely on page titles to understand which page they’ve navigated to, especially when using browser history or switching tabs. Browsers also use page titles for bookmarks and tab management.

How QAOS detects it

The agent checks the DOM for the presence of a non-empty <title> element in <head>.

How to fix

Add a descriptive, unique title to every page:
<head>
  <title>Account Settings — Acme App</title>
</head>
Titles should follow the pattern Page Name — Site Name so users can distinguish tabs. In React/Next.js, use the framework’s head management:
// Next.js App Router
export const metadata = {
  title: 'Account Settings — Acme App',
}

// Next.js Pages Router
import Head from 'next/head'
<Head><title>Account Settings — Acme App</title></Head>

button-no-icon

Low

What it is

Text-only buttons that would benefit from an accompanying icon to clarify their purpose — particularly buttons with ambiguous or very long text, or action buttons in dense interfaces where icons provide faster visual scanning.

Why it matters

Icons alongside text help users quickly identify action buttons during visual scanning. They also provide redundant communication for users with cognitive disabilities who may process images faster than text.

How QAOS detects it

The agent captures a screenshot and uses LLM-based analysis to identify text-only buttons in contexts where an icon would meaningfully improve clarity (e.g., “Click me to continue” with no visual reinforcement).

How to fix

Add contextually meaningful icons to action buttons using an icon library:
import { Trash2, Save, Share } from 'lucide-react'

<button><Trash2 size={16} /> Delete</button>
<button><Save size={16} /> Save changes</button>
<button><Share size={16} /> Share</button>

missing-lang-attribute

High WCAG 3.1.1

What it is

The <html> element lacks a lang attribute. Screen readers use this attribute to select the correct language engine and pronunciation rules.

Why it matters

Without a language declaration, a screen reader may pronounce the page content using the wrong language rules — making it difficult or impossible to understand for users whose assistive technology defaults to a different language.

How QAOS detects it

The agent checks whether the <html> element has a non-empty lang attribute.

Examples

<!-- Missing lang — screen reader uses its default language -->
<html>

<!-- Correct -->
<html lang="en">
<html lang="fr">
<html lang="pt-BR">

How to fix

Add the appropriate BCP 47 language tag to the <html> element:
<html lang="en">
In Next.js, set the locale in next.config.js or the <html> element in your root layout:
// app/layout.jsx (App Router)
export default function RootLayout({ children }) {
  return <html lang="en">{children}</html>
}

missing-meta-viewport

High

What it is

The page <head> contains no <meta name="viewport"> tag, causing the page to render at full desktop width on mobile devices rather than scaling to fit the screen.

Why it matters

Without a viewport meta tag, mobile browsers zoom the page out to show the full desktop layout — making text tiny and requiring constant pinch-zooming to read content. This makes the page effectively unusable on mobile.

How QAOS detects it

The agent checks the page <head> for the presence of <meta name="viewport">.

How to fix

Add the standard viewport meta tag to every page’s <head>:
<meta name="viewport" content="width=device-width, initial-scale=1">
Avoid using user-scalable=no or maximum-scale=1 — these prevent users from zooming to read content, which is a WCAG failure.

non-sequential-heading-hierarchy

Medium WCAG 1.3.1

What it is

Heading levels on the page skip ranks — for example, jumping from <h1> directly to <h3>, or from <h2> to <h4>. This breaks the document outline and disrupts screen reader navigation.

Why it matters

Screen reader users navigate pages by jumping between headings. A logical heading hierarchy conveys the structure of the page. Skipped levels imply a missing section and make the structure confusing to navigate.

How QAOS detects it

The agent analyzes the heading elements on the page and checks whether any heading level is skipped in the hierarchy.

Examples

<!-- Non-sequential: h1 → h3 skips h2 -->
<h1>Dashboard</h1>
<h3>Recent Activity</h3>  <!-- should be h2 -->

<!-- Correct: sequential hierarchy -->
<h1>Dashboard</h1>
<h2>Recent Activity</h2>
<h3>Today</h3>

How to fix

Ensure headings follow a sequential hierarchy without skipping levels. The heading level should reflect the structural importance of the section, not its visual size — use CSS for visual sizing.

multiple-h1

Medium

What it is

The page has more than one <h1> element, which confuses the document outline and makes it unclear what the page’s primary topic is.

Why it matters

The <h1> is the page’s top-level heading — its primary title. Multiple <h1> elements undermine the document structure and make it harder for screen reader users to understand the page hierarchy.

How QAOS detects it

The agent counts the number of <h1> elements on the page and flags any page with more than one.

How to fix

Designate a single <h1> as the primary page title. Other top-level sections should use <h2>:
<h1>Product Catalog</h1>   <!-- one per page -->
<h2>Electronics</h2>
<h2>Clothing</h2>

empty-heading

Medium

What it is

A heading element (<h1><h6>) contains no text content, creating a meaningless invisible entry in the page’s document outline.

Why it matters

Screen readers announce empty headings as “heading level X” with nothing after — confusing users navigating by headings. Empty headings are often accidental (leftover markup, a placeholder not filled in) and should be removed or filled.

How QAOS detects it

The agent scans heading elements and flags any that have no text content or contain only whitespace.

Examples

<!-- Empty headings — meaningless in document outline -->
<h2></h2>
<h3>   </h3>

How to fix

Either add meaningful text content to the heading or remove the element. If you need visual spacing, use CSS margin/padding on surrounding elements rather than empty headings.