Interface: Content & Accessibility

Rule

HTML Antipatterns (WCAG Quick Reference)

Common patterns that fail accessibility, mapped to WCAG success criteria. Use as a grep-friendly checklist.

Critical (Must Fix)

PatternWCAGWhat to grep for
Images without alt1.1.1<img> missing alt attribute
Icon-only buttons4.1.2<button> containing only SVG/icon, no aria-label
Unlabeled form inputs1.3.1<input>, <select>, <textarea> without <label> or aria-label
Non-semantic click handlers2.1.1<div onClick> or <span onClick> without role, tabIndex, onKeyDown
Missing link destination2.1.1<a> with only onClick, no href
aria-hidden on focusable4.1.2aria-hidden="true" on element with tabIndex or native focusability

Serious (Should Fix)

PatternWCAGWhat to grep for
Focus outline removed2.4.7outline-none or outline: none without focus-visible:ring replacement
Missing keyboard handlers2.1.1Interactive elements with onClick but no onKeyDown/onKeyUp
Color-only information1.4.1Status/error indicated by color alone (no icon or text)
Touch target too small2.5.5Clickable elements smaller than 44×44px
Heading hierarchy skipped1.3.1h1 followed by h3 (skipping h2)

Moderate (Consider Fixing)

PatternWCAGWhat to grep for
Positive tabIndex2.4.3tabIndex > 0 (disrupts natural tab order)
Role without required attrs4.1.2role="button" without tabIndex="0"
Placeholder-only labels1.3.1<input placeholder="..."> without visible <label>
Auto-playing media1.4.2<video autoPlay> or <audio autoPlay> without pause control

ARIA

  • NEVERUse aria-hidden="true" on focusable elements
  • MUSTLabel elements need text and an associated input
  • MUSTAll anchors must be valid and navigable
  • MUSTAccurate names (aria-label), decorative elements aria-hidden, verify in the Accessibility Tree
  • MUSTIcon-only buttons have descriptive aria-label
  • NEVERAdd tooltips to disabled buttons (inaccessible to keyboard users)
  • MUSTTooltips shouldn't contain interactive content
  • MUSTHTML illustrations need explicit aria-label (raw DOM is announced otherwise)

Focus

  • SHOULDUse box-shadow for focus rings instead of outline (respects border-radius):
:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--background), 0 0 0 4px var(--ring);
}
  • MUSTEnable arrow-key navigation (↑↓) in sequential focusable lists
  • SHOULDEnable ⌘/Ctrl+Backspace deletion in sequential lists

UX Copy & Writing Voice

Follow the Chicago Manual of Style for UX copy (labels, tooltips, empty states, error messages, marketing pages). For fiction-specific CMOS rules, see ~/Sites/fiction/skills/references/style-guides/chicago-manual.md.

Avoid LLM-Sounding Copy

AI-generated text has recognizable patterns that erode trust. Avoid these tells:

  • NEVEREm dashes (—) in UX copy. Use commas, periods, or parentheses instead. Em dashes are the most recognizable LLM tell
  • NEVER"Delve", "leverage", "streamline", "empower", "elevate", "robust", "seamless", "cutting-edge"
  • NEVER"In order to" (just use "to")
  • NEVERFiller hedges like "It's worth noting that", "Interestingly,", "It's important to note"
  • NEVERStarting with "So," or "Great question!"
  • SHOULDPrefer short, direct sentences. If it sounds like a press release, rewrite it
  • SHOULDRead copy aloud. If it sounds unnatural, it reads unnatural

Content & Accessibility

  • SHOULDInline help first; tooltips last resort
  • MUSTSkeletons mirror final content to avoid layout shift
  • MUST<title> matches current context
  • MUSTNo dead ends; always offer next step/recovery
  • MUSTDesign empty/sparse/dense/error states
  • SHOULDCurly quotes (" "); avoid widows/orphans
  • MUSTTabular numbers for comparisons (font-variant-numeric: tabular-nums or a mono like Geist Mono)
  • MUSTRedundant status cues (not color-only); icons have text labels
  • MUSTDon't ship the schema—visuals may omit labels but accessible names still exist
  • MUSTUse the ellipsis character (not ...)
  • MUSTscroll-margin-top on headings for anchored links; include a "Skip to content" link; hierarchical <h1–h6>
  • MUSTResilient to user-generated content (short/avg/very long)
  • MUSTLocale-aware dates/times/numbers/currency
  • SHOULDRight-clicking the nav logo surfaces brand assets
  • MUSTUse non-breaking spaces to glue terms: 10\u00A0MB, ⌘\u00A0+\u00A0K, Vercel\u00A0SDK