Visibility
Visibility utilities show or hide content in different ways. invisible hides an element but keeps its space, visible restores it, visually-hidden hides content on screen while keeping it for screen readers, and visually-hidden-focusable reveals it again when it receives keyboard focus.
1Visible and invisible
invisible hides an element but keeps its space; visible shows it again.
visibleinvisiblevisible<div class="flex gap-2">
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center visible">
<code class="small">visible</code>
</div>
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center invisible">
<code class="small">invisible</code>
</div>
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center visible">
<code class="small">visible</code>
</div>
</div>2Invisible versus d-none
Compare: invisible leaves a gap, d-none closes it.
AB invisibleCAC<div class="grid gap-2">
<div class="flex gap-2">
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center">
<code class="small">A</code>
</div>
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center invisible">
<code class="small">B invisible</code>
</div>
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center">
<code class="small">C</code>
</div>
</div>
<div class="flex gap-2">
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center">
<code class="small">A</code>
</div>
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center hidden">
<code class="small">B d-none</code>
</div>
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center">
<code class="small">C</code>
</div>
</div>
</div>3Hidden label for an input
visually-hidden hides the label on screen while screen readers still announce it.
<div class="flex gap-2" style="max-width:22rem">
<label class="sr-only" for="ut-join-1263">Email address</label>
<input id="ut-join-1263" type="email" class="form-control" placeholder="Email address">
<button type="button" class="btn btn-primary">Join</button>
</div>4Skip link
visually-hidden-focusable shows a skip link only when it receives keyboard focus. Press Tab inside this example.
<div class="border rounded-lg p-2">
<a href="#ut-main-1264" class="sr-only focus:not-sr-only btn btn-sm btn-primary">Skip to main content</a>
<nav class="small flex gap-4 py-1" aria-label="Demo">
<a href="#">Home</a><a href="#">Shop</a><a href="#">Help</a>
</nav>
<div id="ut-main-1264" class="bg-surface-3 rounded-md p-2 small">
Main content
</div>
</div>5Icon button with hidden text
The icon is aria-hidden and a visually-hidden span names the button.
<div class="flex gap-2">
<button type="button" class="btn btn-outline-secondary"><i class="bi bi-pencil" aria-hidden="true"></i><span class="sr-only">Edit</span></button>
<button type="button" class="btn btn-outline-secondary"><i class="bi bi-share" aria-hidden="true"></i><span class="sr-only">Share</span></button>
<button type="button" class="btn btn-outline-danger"><i class="bi bi-trash3" aria-hidden="true"></i><span class="sr-only">Delete</span></button>
</div>6Counter with context
A badge reads "5 unread messages" to screen readers while showing only the number.
<button type="button" class="btn btn-light border">Messages <span class="badge text-bg-primary">4<span class="sr-only"> unread messages</span></span></button>7Keep alignment with invisible icons
An invisible check icon keeps unchecked rows aligned with the checked one.
- Newest first
- Oldest first
- Most popular
<ul class="list-unstyled border rounded-lg mb-0 p-2" style="max-width:16rem">
<li class="px-2 py-1"><span class="text-primary-ink me-2"><i class="bi bi-check-lg" aria-hidden="true"></i></span>Newest first</li>
<li class="px-2 py-1"><span class="invisible me-2"><i class="bi bi-check-lg" aria-hidden="true"></i></span>Oldest first</li>
<li class="px-2 py-1"><span class="invisible me-2"><i class="bi bi-check-lg" aria-hidden="true"></i></span>Most popular</li>
</ul>8Hidden table caption
A visually-hidden caption describes the table for assistive technology.
| City | Visits |
|---|---|
| Lisbon | 88.3k |
| Barcelona | 60.2k |
<table class="table table-sm small mb-0">
<caption class="sr-only">Monthly visits by city</caption>
<thead>
<tr>
<th scope="col">City</th>
<th scope="col" class="text-end">Visits</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lisbon</td>
<td class="text-end">88.3k</td>
</tr>
<tr>
<td>Barcelona</td>
<td class="text-end">60.2k</td>
</tr>
</tbody>
</table>9Hidden section heading
A visually-hidden heading gives a visual-only card grid a name in the outline.
Featured services
<section>
<h3 class="sr-only">Featured services</h3>
<div class="row g-2 small">
<div class="col-4">
<div class="border rounded-lg p-2 text-center">
Ticketing
</div>
</div>
<div class="col-4">
<div class="border rounded-lg p-2 text-center">
Networking app
</div>
</div>
<div class="col-4">
<div class="border rounded-lg p-2 text-center">
Networking app
</div>
</div>
</div>
</section>10Spinner with a hidden status
The spinner's text is visually-hidden inside role="status".
<div class="flex items-center gap-2">
<div class="spinner-border spinner-border-sm text-primary-ink" role="status">
<span class="sr-only">Loading orders</span>
</div>
<span class="small text-muted">Fetching the latest data</span>
</div>11Rating for screen readers
Stars are hidden from assistive tech and a visually-hidden text states the score.
<div>
<span class="text-warning-emphasis" aria-hidden="true"><i class="bi bi-star-fill" aria-hidden="true"></i><i class="bi bi-star-fill" aria-hidden="true"></i><i class="bi bi-star-fill" aria-hidden="true"></i><i class="bi bi-star" aria-hidden="true"></i><i class="bi bi-star" aria-hidden="true"></i></span><span class="sr-only">Rated 3 out of 5</span> <span class="small">(260)</span>
</div>12Old and new price
visually-hidden words tell which price is the original and which the sale price.
Original price:$147.36Sale price:$33.28
<p class="mb-0"><span class="sr-only">Original price:</span><span class="line-through text-tertiary me-2">$147.36</span><span class="sr-only">Sale price:</span><span class="font-bold text-danger-emphasis text-lg">$33.28</span></p>13Reserved space for errors
An invisible error line keeps the form from jumping when the message appears.
<div style="max-width:22rem">
<label class="form-label" for="ut-tel-1265">Phone</label>
<input id="ut-tel-1265" type="tel" class="form-control" value="+1 (555) 869-5041">
<div class="small text-danger-emphasis invisible">
Please enter a valid phone number.
</div>
<button type="button" class="btn btn-primary btn-sm">Next</button>
</div>14Current page in pagination
A visually-hidden "(current)" marks the active page for screen readers.
<nav aria-label="Results pages">
<ul class="pagination pagination-sm mb-0">
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item active" aria-current="page"><a class="page-link" href="#">2 <span class="sr-only">(current)</span></a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
</ul>
</nav>15External link hint
An outward arrow icon plus a visually-hidden note about the link destination.
<a href="#" class="icon-link">Zeni Studio documentation <i class="bi bi-box-arrow-up-right" aria-hidden="true"></i><span class="sr-only"> (external site)</span></a>16Progress with hidden value
The progress bar shows the fill; the percentage is a visually-hidden text.
<div class="progress" role="progressbar" aria-label="Upload progress" aria-valuenow="51" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar" style="width:51%">
<span class="sr-only">51% uploaded</span>
</div>
</div>17Back to top link
A visually-hidden-focusable link at the end of a long page only shows for keyboard users.
More than eighty speakers share what they have learned the hard way. Three days of keynotes, hands-on workshops and evening meetups.
Back to top<div class="border rounded-lg p-4 small">
<p class="mb-2">More than eighty speakers share what they have learned the hard way. Three days of keynotes, hands-on workshops and evening meetups.</p>
<a href="#ut-main-1264" class="sr-only focus:not-sr-only">Back to top</a>
</div>18Placeholder column
An invisible column keeps a three column layout balanced while one is empty.
colcolinvisible col<div class="row g-2">
<div class="col-4">
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center">
<code class="small">col</code>
</div>
</div>
<div class="col-4">
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center">
<code class="small">col</code>
</div>
</div>
<div class="col-4 invisible">
<div class="bg-primary-subtle border border-primary/30 rounded-md p-2 text-center">
<code class="small">invisible col</code>
</div>
</div>
</div>19Hidden legend
A visually-hidden legend names a radio group whose visual heading is elsewhere.
<fieldset>
<legend class="sr-only">Delivery speed</legend>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="ut-speed-1266" id="ut-std-1267" checked>
<label class="form-check-label" for="ut-std-1267">Standard</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="ut-speed-1266" id="ut-exp-1268">
<label class="form-check-label" for="ut-exp-1268">Express</label>
</div>
</fieldset>20Close button label
btn-close has no text, so it needs aria-label; a visually-hidden span is the alternative for custom close icons.
<div class="flex items-center gap-4 border rounded-lg p-2" style="max-width:22rem">
<span class="small grow">The event your calendar has been waiting for</span>
<button type="button" class="btn-close" aria-label="Close"></button>
<button type="button" class="btn btn-sm btn-light"><i class="bi bi-x-lg" aria-hidden="true"></i><span class="sr-only">Dismiss</span></button>
</div>