This document outlines the accessibility standards and practices for the DevFest Detroit website. Our goal is to ensure the website is accessible to all users, including those using assistive technologies.
We have implemented comprehensive accessibility tooling and guidelines to ensure our website meets WCAG 2.1 AA standards. This includes both static analysis and runtime testing to catch accessibility issues during development.
We follow the Web Content Accessibility Guidelines (WCAG) 2.1 at the AA level.
We use eslint-plugin-jsx-a11y to catch accessibility issues during development:
# Run accessibility linting
npm run lint:a11y
# Run accessibility check (alias)
npm run a11y:checkConfiguration: .eslintrc.a11y.cjs
Key Rules:
- Alt text for images (
jsx-a11y/alt-text) - ARIA attributes validation (
jsx-a11y/aria-props) - Semantic HTML structure (
jsx-a11y/heading-has-content) - Keyboard navigation support (
jsx-a11y/click-events-have-key-events) - Focus management (
jsx-a11y/no-static-element-interactions)
We use @axe-core/react for real-time accessibility checking in development mode:
- When: Only runs in development mode (
import.meta.env.DEV) - Delay: 1000ms to avoid performance impact
- Output: Console warnings for accessibility violations
- Integration: Automatically initialized in
main.jsx
Use semantic HTML elements to provide meaning and structure:
// ✅ Good
<main>
<section>
<h2>Speakers</h2>
<article>
<h3>Speaker Name</h3>
<p>Speaker bio...</p>
</article>
</section>
</main>
// ❌ Bad
<div>
<div>
<div>Speakers</div>
<div>
<div>Speaker Name</div>
<div>Speaker bio...</div>
</div>
</div>
</div>All images must have meaningful alt text:
// ✅ Good
<img src="speaker.jpg" alt="Portrait of John Doe, software engineer" />
// ✅ Good - Decorative images
<img src="decoration.png" alt="" role="presentation" />
// ❌ Bad
<img src="speaker.jpg" alt="image" />
<img src="speaker.jpg" />Ensure all interactive elements are keyboard accessible:
// ✅ Good
<button onClick={handleClick} onKeyDown={handleKeyDown}>
Click me
</button>
// ✅ Good - Using proper semantic elements
<a href="/speakers" onClick={handleClick}>
View Speakers
</a>
// ❌ Bad
<div onClick={handleClick}>Click me</div>Use ARIA attributes to enhance accessibility:
// ✅ Good
<button
aria-expanded={isOpen}
aria-controls="speaker-details"
aria-label="Toggle speaker details"
>
{isOpen ? 'Hide' : 'Show'} Details
</button>
<div id="speaker-details" aria-hidden={!isOpen}>
Speaker information...
</div>Ensure proper labeling and validation:
// ✅ Good
<label htmlFor="email">Email Address</label>
<input
id="email"
type="email"
required
aria-describedby="email-error"
/>
<div id="email-error" role="alert">
Please enter a valid email address
</div>
// ❌ Bad
<input type="email" placeholder="Email" />Ensure proper focus management:
// ✅ Good - Focus management in modals
const Modal = ({ isOpen, onClose }) => {
const modalRef = useRef(null)
useEffect(() => {
if (isOpen && modalRef.current) {
modalRef.current.focus()
}
}, [isOpen])
return (
<div
ref={modalRef}
role="dialog"
aria-modal="true"
tabIndex={-1}
onKeyDown={handleKeyDown}
>
Modal content...
</div>
)
}- Ensure sufficient color contrast (4.5:1 for normal text, 3:1 for large text)
- Don't rely solely on color to convey information
- Use patterns, icons, or text in addition to color
- Ensure content is accessible on all screen sizes
- Test with screen readers and keyboard navigation
- Use responsive images with appropriate alt text
Run accessibility linting before committing:
npm run lint:a11y- Start development server:
npm run dev - Open browser console to see axe-core warnings
- Fix any reported accessibility violations
- Keyboard Navigation: Test all interactive elements using only keyboard
- Screen Reader: Test with screen readers (NVDA, JAWS, VoiceOver)
- Browser Tools: Use browser accessibility inspectors
- Color Contrast: Use tools like WebAIM's contrast checker
Accessibility testing is integrated into our git workflow:
- Pre-commit: Runs accessibility linting on staged files via lint-staged
- Pre-push: Runs full accessibility audit before pushing
- CI/CD: Ready for integration with continuous integration
Pre-commit Hook (.husky/pre-commit):
- Runs
lint-stagedwhich includes accessibility checks - Automatically fixes issues where possible
- Prevents commits with accessibility violations
Pre-push Hook (.husky/pre-push):
- Runs full accessibility audit on all files
- Blocks push if accessibility issues are found
- Provides clear error messages and guidance
# Run full accessibility check (linting + automated testing)
npm run a11y:check
# Run accessibility checks on staged files only
npm run a11y:check:staged
# Run lint-staged (includes accessibility checks)
npx lint-stagedSolution: Add descriptive alt text or alt="" for decorative images
Solution: Add onKeyDown handler or use semantic elements like <button>
Solution: Use <label> elements or aria-label attributes
Solution: Implement proper focus management in modals and dynamic content
Solution: Use WebAIM's contrast checker and adjust colors
- WCAG 2.1 Guidelines
- WebAIM
- axe-core Documentation
- eslint-plugin-jsx-a11y Rules
- React Accessibility Guide
If you encounter accessibility issues or need guidance:
- Check the browser console for axe-core warnings
- Run
npm run lint:a11yto see ESLint accessibility errors - Consult the resources above
- Test with actual assistive technologies
- Ask for help from team members familiar with accessibility
We are committed to maintaining and improving the accessibility of our website. All new features and changes must meet these accessibility standards before being merged into the main branch.