Accessible Components¶
ARIA Roles and Labels¶
Icons¶
Decorative icons should be hidden from screen readers:
Decorative (hidden from SR)
Meaningful (labeled for SR)
Meaningful (labeled for SR)
<!-- Decorative icon (hidden) -->
<i class="ni ni-planet" aria-hidden="true"></i>
<!-- Meaningful icon (labeled) -->
<i class="ni ni-settings-gear-65" aria-label="Settings"></i>
Buttons with Icons¶
<!-- Icon + text: icon is decorative -->
<button class="btn btn-primary">
<i class="ni ni-check-bold me-1" aria-hidden="true"></i> Save
</button>
<!-- Icon-only button: needs aria-label -->
<button class="btn btn-sm btn-outline-secondary" aria-label="Delete item">
<i class="ni ni-fat-remove"></i>
</button>
Navigation Landmarks¶
<nav aria-label="Main navigation">...</nav>
<nav aria-label="Breadcrumb">...</nav>
<main id="main-content">...</main>
<aside aria-label="Sidebar">...</aside>
<footer>...</footer>
Forms¶
Labels and Descriptions¶
We'll never share your email.
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" aria-describedby="emailHelp">
<div id="emailHelp" class="form-text">We'll never share your email.</div>
</div>
Error States¶
Name is required.
<div class="mb-3">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control is-invalid" id="name" aria-describedby="nameError" aria-invalid="true">
<div id="nameError" class="invalid-feedback">Name is required.</div>
</div>
Required Fields¶
<label for="field" class="form-label">
Name <span class="text-danger" aria-hidden="true">*</span>
<span class="visually-hidden">(required)</span>
</label>
<input type="text" id="field" required aria-required="true">
Tables¶
<table class="table" aria-label="User list">
<caption class="visually-hidden">List of active users with roles and status</caption>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice</td>
<td>Developer</td>
</tr>
</tbody>
</table>
Live Regions¶
For dynamic updates (e.g., notifications, search results):
<div aria-live="polite" aria-atomic="true" class="visually-hidden" id="status">
<!-- Updated dynamically via JS -->
</div>
<script>
document.getElementById('status').textContent = '5 results found';
</script>