Web accessibility specialist for WCAG compliance, ARIA implementation, and inclusive design. Use when auditing websites for accessibility issues, implementing WCAG 2.1 AA/AAA standards, testing with screen readers, or ensuring ADA compliance. Expert in semantic HTML, keyboard navigation, and assistive technology compatibility.
<img src="/products/shoes.jpg">
<!-- Informative image -->
<img src="/products/shoes.jpg" alt="Red Nike Air Max running shoes with white swoosh">
<!-- Decorative image -->
<img src="/decorative-pattern.svg" alt="" role="presentation">
<!-- Logo that links -->
<a href="/">
<img src="/logo.png" alt="Company Name - Home">
</a>
/* Contrast ratio 2.5:1 - Fails WCAG */
.text {
color: #767676;
background: #ffffff;
}
/* Contrast ratio 4.5:1+ - Passes AA */
.text {
color: #595959;
background: #ffffff;
}
/* Contrast ratio 7:1+ - Passes AAA */
.text-high-contrast {
color: #333333;
background: #ffffff;
}
<div class="button" onclick="submitForm()">Submit</div>
<div class="heading">Page Title</div>
<div class="nav-menu">...</div>
<button type="submit" onclick="submitForm()">Submit</button>
<h1>Page Title</h1>
<nav aria-label="Main navigation">...</nav>
<button> for buttons<a> for links<h1> - <h6> for headings (hierarchical)<nav>, <main>, <aside>, <article>, <section> for landmarks<ul>, <ol>, <li> for lists<table>, <th>, <td> for tabular data<input type="email" placeholder="Enter your email">
<!-- Explicit label -->
<label for="email">Email Address</label>
<input type="email" id="email" name="email">
<!-- Implicit label -->
<label>
Email Address
<input type="email" name="email">
</label>
<!-- Hidden label (for tight layouts) -->
<label for="search" class="sr-only">Search</label>
<input type="text" id="search" placeholder="Search...">
<fieldset> and <legend><div onclick="handleClick()">Click me</div>
<a href="javascript:void(0)" onclick="doSomething()">Action</a>
<!-- Use proper button -->
<button onclick="handleClick()">Click me</button>
<!-- If div required, make it accessible -->
<div
role="button"
tabindex="0"
onclick="handleClick()"
onkeydown="handleKeyPress(event)"
>
Click me
</div>
<script>
function handleKeyPress(event) {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
handleClick();
}
}
</script>
<div class="header">...</div>
<div class="main-content">...</div>
<div class="sidebar">...</div>
<div class="footer">...</div>
<header role="banner">
<nav aria-label="Main navigation">...</nav>
</header>
<main role="main">
<h1>Page Title</h1>
<article>...</article>
</main>
<aside role="complementary" aria-label="Related articles">
...
</aside>
<footer role="contentinfo">
...
</footer>
banner - Site headernavigation - Navigation menusmain - Primary content (one per page)complementary - Supporting contentcontentinfo - Site footersearch - Search functionalityform - Form regions<div class="modal">
<div class="content">
Modal content
<button onclick="closeModal()">Close</button>
</div>
</div>
<div
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
aria-describedby="modal-desc"
>
<h2 id="modal-title">Confirm Action</h2>
<p id="modal-desc">Are you sure you want to delete this item?</p>
<button onclick="confirmAction()">Confirm</button>
<button onclick="closeModal()">Cancel</button>
</div>
<script>
// Focus management
function openModal() {
const modal = document.querySelector('[role="dialog"]');
const focusableElements = modal.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
// Store previous focus
previousFocus = document.activeElement;
// Focus first element
focusableElements[0].focus();
// Trap focus
modal.addEventListener('keydown', trapFocus);
}
function closeModal() {
// Return focus
if (previousFocus) previousFocus.focus();
}
function trapFocus(event) {
if (event.key !== 'Tab') return;
const focusableElements = Array.from(
modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];
if (event.shiftKey && document.activeElement === firstElement) {
lastElement.focus();
event.preventDefault();
} else if (!event.shiftKey && document.activeElement === lastElement) {
firstElement.focus();
event.preventDefault();
}
}
</script>
role="dialog" or role="alertdialog"aria-modal="true" to indicate modal behavioraria-labelledby pointing to titlearia-describedby for description (optional)<a href="#main-content" class="skip-link">
Skip to main content
</a>
<header>
<nav>...</nav>
</header>
<main id="main-content" tabindex="-1">
<!-- Page content -->
</main>
<style>
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: #fff;
padding: 8px;
text-decoration: none;
z-index: 100;
}
.skip-link:focus {
top: 0;
}
</style>
aria-checked - Checkbox/radio statearia-disabled - Disabled statearia-expanded - Expanded/collapsed statearia-hidden - Hidden from assistive technologyaria-pressed - Toggle button statearia-selected - Selected statearia-label - Accessible namearia-labelledby - ID reference for labelaria-describedby - ID reference for descriptionaria-live - Live region updatesaria-required - Required fieldaria-invalid - Validation state<!-- Polite: Wait for pause in speech -->
<div aria-live="polite" aria-atomic="true">
Item added to cart
</div>
<!-- Assertive: Interrupt immediately -->
<div aria-live="assertive" role="alert">
Error: Payment failed
</div>
<!-- Status message -->
<div role="status" aria-live="polite">
Saving changes...
</div>
<div class="accordion">
<button
aria-expanded="false"
aria-controls="panel-1"
id="accordion-1"
>
Section 1
</button>
<div id="panel-1" role="region" aria-labelledby="accordion-1" hidden>
Panel content
</div>
</div>
<div role="tablist" aria-label="Content sections">
<button
role="tab"
aria-selected="true"
aria-controls="panel-1"
id="tab-1"
>
Tab 1
</button>
<button
role="tab"
aria-selected="false"
aria-controls="panel-2"
id="tab-2"
tabindex="-1"
>
Tab 2
</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
Panel 1 content
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" hidden>
Panel 2 content
</div>
# Accessibility Statement
We are committed to ensuring digital accessibility for people with disabilities. We continually improve the user experience for everyone and apply relevant accessibility standards.
## Conformance Status
This website is partially conformant with WCAG 2.1 Level AA. "Partially conformant" means that some parts of the content do not fully conform to the accessibility standard.
## Feedback
We welcome your feedback on the accessibility of this site. Please contact us:
- Email: accessibility@example.com
- Phone: +1-555-0123
## Known Issues
- [List any known accessibility issues and planned fixes]
Last updated: [Date]