Accessibility Best Practices
Overview
This guide combines best practices for both accessibility and HTML validation to help you build websites that are usable, standards-compliant, and performant.
HTML Validation Best Practices
Use Semantic HTML
Semantic HTML helps both accessibility and SEO:
<!-- Bad: Generic divs -->
<div class="header">...</div>
<div class="content">...</div>
<div class="footer">...</div>
<!-- Good: Semantic elements -->
<header>...</header>
<main>...</main>
<footer>...</footer>
Benefits:
- Screen readers understand page structure
- Search engines better index your content
- Easier to style and maintain
Proper Heading Hierarchy
Always maintain logical heading order:
<!-- Bad: Skipping levels -->
<h1>Main Title</h1>
<h3>Subsection</h3>
<!-- Good: Sequential hierarchy -->
<h1>Main Title</h1>
<h2>Section</h2>
<h3>Subsection</h3>
Why it matters:
- Screen reader users navigate by headings
- Search engines use headings to understand content structure
- Creates a clear document outline
Valid HTML Structure
Ensure your HTML is valid:
- Close all tags: Every opening tag needs a closing tag (or be self-closing)
- Nest properly: Don’t overlap elements incorrectly
- Use proper DOCTYPE:
<!DOCTYPE html>for HTML5 - Validate regularly: Use CodeFrog’s HTML validation
Tools:
- CodeFrog HTML validation
- W3C Markup Validator
- Browser developer tools
Accessibility Best Practices
Images and Media
Alt Text Guidelines
Descriptive alt text for informative images:
<img src="chart.png" alt="Sales increased 25% from Q1 to Q2, shown in a bar chart">
Empty alt text for decorative images:
<img src="decorative-border.png" alt="">
Functional images (buttons, links):
<a href="/download">
<img src="download-icon.png" alt="Download PDF">
</a>
Video and Audio
- Provide captions for all video content
- Include transcripts for audio content
- Ensure media players are keyboard accessible
Forms and Inputs
Label All Form Fields
<!-- Bad -->
<input type="email" name="email" placeholder="Email">
<!-- Good -->
<label for="email">Email Address</label>
<input type="email" id="email" name="email">
Group Related Fields
<fieldset>
<legend>Shipping Address</legend>
<label for="street">Street</label>
<input type="text" id="street" name="street">
<!-- More fields -->
</fieldset>
Error Messages
- Associate error messages with form fields
- Use
aria-describedbyto link errors to inputs - Provide clear, actionable error messages
<label for="email">Email</label>
<input type="email" id="email" aria-describedby="email-error">
<span id="email-error" role="alert">Please enter a valid email address</span>
Color and Contrast
Minimum Contrast Ratios
- Normal text: 4.5:1 (WCAG AA) or 7:1 (WCAG AAA)
- Large text (18pt+): 3:1 (WCAG AA) or 4.5:1 (WCAG AAA)
- UI components: 3:1 for visual indicators
Don’t Rely on Color Alone
<!-- Bad: Color only -->
<span style="color: red">Required field</span>
<!-- Good: Color + indicator -->
<span style="color: red">* Required field</span>
Keyboard Navigation
All Interactive Elements Must Be Keyboard Accessible
- Links, buttons, form inputs
- Custom widgets and components
- Modal dialogs and dropdowns
Focus Management
- Visible focus indicators: Users must see where they are
- Logical tab order: Follow visual order
- No keyboard traps: Users must be able to escape
- Skip links: Allow users to skip repetitive content
<!-- Skip to main content -->
<a href="#main-content" class="skip-link">Skip to main content</a>
Keyboard Shortcuts
- Don’t override browser shortcuts
- Provide alternatives for custom shortcuts
- Document all keyboard shortcuts
ARIA (Accessible Rich Internet Applications)
Always Prefer Native HTML Over ARIA
The W3C’s first rule of ARIA use states: if you can use a native HTML element with the semantics and behavior you require already built in, use it instead of adding ARIA. ARIA was designed as a bridge for cases where HTML doesn’t have the right element — it was never meant to replace semantic HTML.
<!-- Best: Native HTML element -->
<button>Close</button>
<!-- Acceptable when no native element exists -->
<div role="button" tabindex="0" aria-label="Close dialog">×</div>
Common replacements — use native elements instead of ARIA:
| Instead of | Use |
|---|---|
<div role="button"> |
<button> |
<div role="dialog"> |
<dialog> |
<div role="navigation"> |
<nav> |
aria-expanded + JS |
<details> and <summary> |
<div aria-live="polite"> |
<output> |
aria-required="true" |
required attribute |
aria-disabled="true" |
disabled attribute |
Native elements provide keyboard behavior, focus management, mobile adaptations, and screen reader support automatically — with less code and fewer potential bugs.
For a comprehensive guide with code examples, see Why Use Semantic HTML (Even When Automated Tests Pass).
Use ARIA When Native HTML Isn’t Enough
ARIA remains valuable for complex widgets (tree views, data grids), supplementary context (aria-describedby, aria-label for icon-only buttons), and state communication (aria-expanded, aria-current).
Common ARIA Patterns
Landmarks (use aria-label to distinguish multiple landmarks of the same type):
<nav aria-label="Main navigation">
<main aria-label="Main content">
<aside aria-label="Related articles">
Live Regions:
<div role="status" aria-live="polite">Item added to cart</div>
<div role="alert" aria-live="assertive">Error: Invalid input</div>
States:
<button aria-expanded="false" aria-controls="menu">Menu</button>
<div id="menu" aria-hidden="true">...</div>
Dynamic Content
Announce Changes to Screen Readers
When content changes dynamically:
<div role="status" aria-live="polite" id="status">
<!-- Status updates appear here -->
</div>
Loading States
<button aria-busy="true" aria-label="Loading...">Submit</button>
Combining HTML Validation and Accessibility
Semantic HTML = Better Accessibility
Valid, semantic HTML is inherently more accessible:
<nav>tells screen readers this is navigation<main>identifies the main content area<article>indicates standalone content<section>groups related content
Performance Benefits
Valid HTML often means:
- Faster parsing by browsers
- Better caching
- Smaller file sizes
- Improved mobile performance
SEO Benefits
Search engines favor:
- Valid HTML structure
- Semantic markup
- Proper heading hierarchy
- Descriptive alt text
Testing Strategy
Automated Testing
- CodeFrog Accessibility Testing: Run on every build
- HTML Validation: Check before deployment
- CI/CD Integration: Automate in your pipeline
Manual Testing
- Screen Reader Testing: Use VoiceOver, NVDA, or JAWS
- Keyboard Navigation: Test without a mouse
- Browser Testing: Test across different browsers
- Mobile Testing: Test on actual devices
User Testing
- Involve users with disabilities
- Get feedback on real-world usage
- Iterate based on user needs
Common Patterns
Accessible Modal Dialog
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm Action</h2>
<p>Are you sure you want to proceed?</p>
<button>Cancel</button>
<button>Confirm</button>
</div>
Accessible Navigation
<nav aria-label="Main navigation">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</nav>
Accessible Form
<form>
<fieldset>
<legend>Contact Information</legend>
<label for="name">Name</label>
<input type="text" id="name" name="name" required>
<label for="email">Email</label>
<input type="email" id="email" name="email" required
aria-describedby="email-help">
<small id="email-help">We'll never share your email</small>
</fieldset>
<button type="submit">Submit</button>
</form>
Maintenance
Regular Audits
- Schedule monthly accessibility reviews
- Run automated tests after major changes
- Keep up with WCAG updates
Documentation
- Document accessibility decisions
- Maintain a style guide with accessibility guidelines
- Share knowledge with your team
Continuous Improvement
- Fix issues as you find them
- Don’t wait for a major redesign
- Small improvements add up
Related Resources
- Why Use Semantic HTML (Even When Automated Tests Pass) - Why native HTML elements should be your first choice over ARIA
- WCAG Levels Explained - Detailed explanation of WCAG A, AA, and AAA conformance levels
- Getting Started with Accessibility - Quick start guide
- Accessibility Testing Guide - Detailed testing instructions
- Why Accessibility Matters - Understanding the importance
- Benefits of Valid HTML and Accessibility - Additional benefits
External Resources
Following these best practices will help you build websites that are accessible, standards-compliant, and provide a great experience for all users.