Accessibility Standards
On This Page
Accessibility Overview
QR Igniter is committed to ensuring digital accessibility for people with disabilities. We aim to meet WCAG 2.1 Level AA compliance across all web and mobile interfaces.
Accessibility Target
All QR Igniter interfaces must meet WCAG 2.1 Level AA compliance. New features cannot be released without passing accessibility review.
Why Accessibility Matters
- Legal Compliance: UK Equality Act 2010, EU Accessibility Act
- User Inclusion: 15% of the world's population has some form of disability
- Better UX: Accessible design improves usability for everyone
- SEO Benefits: Many accessibility practices improve search rankings
WCAG 2.1 Compliance
The Four Principles (POUR)
Perceivable
Information and UI components must be presentable in ways users can perceive.
Operable
UI components and navigation must be operable by all users.
Understandable
Information and operation of the UI must be understandable.
Robust
Content must be robust enough to be interpreted by assistive technologies.
Level AA Requirements
| Criterion | Requirement | Implementation |
|---|---|---|
| 1.1.1 Non-text Content | All images have alt text | Alt attributes on all <img> elements |
| 1.3.1 Info and Relationships | Structure conveyed programmatically | Semantic HTML, ARIA landmarks |
| 1.4.3 Contrast (Minimum) | 4.5:1 for normal text, 3:1 for large text | Design system color palette verified |
| 1.4.4 Resize Text | Text resizable up to 200% | Relative units (rem), fluid layouts |
| 2.1.1 Keyboard | All functionality keyboard accessible | Focus management, keyboard handlers |
| 2.4.4 Link Purpose | Link purpose determinable from text | Descriptive link text, aria-label where needed |
| 2.4.7 Focus Visible | Visible focus indicator | Custom focus styles defined in CSS |
| 3.1.1 Language of Page | Default language defined | lang attribute on <html> |
| 4.1.2 Name, Role, Value | Name and role of components exposed | ARIA attributes, semantic elements |
Web Accessibility
Semantic HTML
<!-- Good: Semantic structure -->
<header role="banner">
<nav aria-label="Main navigation">
<ul>
<li><a href="/dashboard">Dashboard</a></li>
<li><a href="/qr-codes">QR Codes</a></li>
</ul>
</nav>
</header>
<main role="main">
<h1>Dashboard</h1>
<section aria-labelledby="stats-heading">
<h2 id="stats-heading">Statistics</h2>
<!-- Content -->
</section>
</main>
<!-- Bad: Non-semantic structure -->
<div class="header">
<div class="nav">
<span onclick="navigate('/dashboard')">Dashboard</span>
</div>
</div>
Focus Management
/* Visible focus indicators */
:focus {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
/* Don't remove focus for keyboard users */
:focus:not(:focus-visible) {
outline: none; /* Only for mouse users */
}
:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
Color Contrast
| Color Pair | Contrast Ratio | Status |
|---|---|---|
| Primary (#F05A28) on White | 4.58:1 | Pass AA |
| Text (#1f2937) on White | 14.07:1 | Pass AAA |
| Muted (#6b7280) on White | 5.35:1 | Pass AA |
| Success (#22c55e) on White | 3.02:1 | Pass Large Text |
Form Accessibility
<!-- Accessible form with labels and error handling -->
<form aria-labelledby="form-title">
<h2 id="form-title">Create QR Code</h2>
<div class="form-group">
<label for="gtin">
GTIN
<span class="required" aria-label="required">*</span>
</label>
<input
type="text"
id="gtin"
name="gtin"
aria-describedby="gtin-help gtin-error"
aria-required="true"
aria-invalid="false"
>
<p id="gtin-help" class="help-text">
Enter a 14-digit Global Trade Item Number
</p>
<p id="gtin-error" class="error-text" role="alert" hidden>
Please enter a valid GTIN
</p>
</div>
<button type="submit">Create QR Code</button>
</form>
ARIA Usage
<!-- Live regions for dynamic content -->
<div aria-live="polite" aria-atomic="true" class="status-message">
QR code generated successfully
</div>
<!-- Modal dialog -->
<div
role="dialog"
aria-modal="true"
aria-labelledby="dialog-title"
aria-describedby="dialog-description"
>
<h2 id="dialog-title">Confirm Delete</h2>
<p id="dialog-description">
Are you sure you want to delete this QR code?
</p>
<button type="button">Cancel</button>
<button type="button">Delete</button>
</div>
Mobile Accessibility
Flutter Accessibility
// Semantic labels for widgets
Semantics(
label: 'Scan QR Code',
hint: 'Opens camera to scan a QR code',
button: true,
child: FloatingActionButton(
onPressed: _openScanner,
child: const Icon(Icons.qr_code_scanner),
),
)
// Exclude decorative elements from accessibility
ExcludeSemantics(
child: Image.asset('assets/decorative_background.png'),
)
// Merge semantics for complex widgets
MergeSemantics(
child: Row(
children: [
const Icon(Icons.check_circle, color: Colors.green),
const Text('Scan successful'),
],
),
)
Touch Target Size
- Minimum touch target: 48x48 dp (44x44 pt on iOS)
- Adequate spacing between interactive elements
- Large buttons for primary actions
// Ensure adequate touch target size
SizedBox(
width: 48,
height: 48,
child: IconButton(
icon: const Icon(Icons.settings),
onPressed: _openSettings,
tooltip: 'Settings',
),
)
Screen Reader Support
- VoiceOver (iOS) fully supported
- TalkBack (Android) fully supported
- Logical reading order maintained
- Focus order follows visual layout
Testing Tools
Automated Testing
| Tool | Type | Integration |
|---|---|---|
| axe-core | Browser extension / library | CI/CD pipeline |
| Lighthouse | Browser DevTools | Automated audits |
| WAVE | Browser extension | Manual testing |
| Pa11y | CLI tool | CI/CD pipeline |
CI/CD Integration
# .gitlab-ci.yml accessibility stage
accessibility:
stage: test
script:
# Run Pa11y accessibility tests
- pa11y-ci --config pa11y.config.js
# Run Lighthouse accessibility audit
- lhci autorun --collect.url="http://localhost:8080"
--assert.preset="lighthouse:recommended"
--assert.assertions.accessibility=0.9
artifacts:
paths:
- accessibility-report/
expire_in: 7 days
Manual Testing
- Keyboard navigation: Tab through all interactive elements
- Screen reader: Test with VoiceOver, NVDA, or TalkBack
- Zoom: Test at 200% zoom level
- Color blindness: Use simulation tools
- Motion sensitivity: Test with reduced motion
Accessibility Checklist
Development Checklist
| Category | Check | Required |
|---|---|---|
| Images | All images have alt text | Yes |
| Decorative images have empty alt="" | Yes | |
| Complex images have extended descriptions | Yes | |
| Forms | All inputs have labels | Yes |
| Error messages are associated with inputs | Yes | |
| Required fields are indicated | Yes | |
| Navigation | All functionality keyboard accessible | Yes |
| Focus visible at all times | Yes | |
| Skip links provided | Yes | |
| Content | Heading hierarchy is logical (h1-h6) | Yes |
| Link text is descriptive | Yes | |
| Color is not the only indicator | Yes |
Release Accessibility Sign-off
Before each release, the following must be completed:
- Automated accessibility tests pass (Lighthouse score > 90)
- Manual keyboard navigation test completed
- Screen reader testing with VoiceOver/TalkBack
- Color contrast verification
- Mobile accessibility testing
- Accessibility statement updated (if needed)