Visually Hidden 1.2.2
Use .velin-sr-only to hide an element visually while keeping it accessible to assistive
technologies such as screen readers. Use .velin-sr-only--focusable to make the element
visible again when it receives focus. Deutsch: visuell-verborgen
.velin-sr-only and .velin-sr-only--focusable are stable a11y helpers in 1.2.0.
(There is no separate .velin-visually-hidden class in the core CSS — use .velin-sr-only.)
When to use
- Provide an accessible name or landmark text that sighted users get from layout (icon buttons, section titles).
- Skip links: combine
.velin-sr-onlywith.velin-sr-only--focusable. - Form labels when a visible label truly cannot appear — still prefer visible labels when possible.
When not
- Do not hide interactive controls with
.velin-sr-onlyunless they become visible on focus (--focusable) or have an equivalent visible control. - Do not use it instead of
display: none/hiddenwhen content must be removed for everyone. - Do not rely on placeholders alone — sr-only labels are a fallback, not a design system.
How it works
.velin-sr-only clips the element to a 1×1 px region using a combination of
clip, clip-path, fixed sizing, and overflow: hidden. The element
is removed from the visual flow but remains in the accessibility tree so screen readers can announce it.
.velin-sr-only {
position: absolute !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
clip: rect(0, 0, 0, 0) !important;
white-space: nowrap !important;
border: 0 !important;
}
.velin-sr-only--focusable:focus-visible,
.velin-sr-only--focusable:active {
position: static !important;
width: auto !important;
height: auto !important;
padding: inherit !important;
margin: inherit !important;
overflow: visible !important;
clip: auto !important;
white-space: normal !important;
}
Example: hidden heading
Add a visually hidden heading to give screen-reader users a landmark for a navigation section that sighted users understand from context alone.
↑ The heading “Main navigation” is visually hidden but announced by screen readers.
<nav aria-labelledby="nav-heading">
<h5 class="velin-sr-only" id="nav-heading">Main navigation</h5>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Features</a></li>
<li><a href="#">Pricing</a></li>
</ul>
</nav>
Example: skip link
A skip-to-content link is hidden until the user tabs to it. Combine
.velin-sr-only with .velin-sr-only--focusable so keyboard users can jump
past repeated navigation.
↑ Press Tab to reveal the skip link above.
<a href="#main-content" class="velin-sr-only velin-sr-only--focusable">
Skip to main content
</a>
Example: form labels
When a visible label is unnecessary (e.g. a search input with a placeholder) you can hide the
<label> while keeping the form accessible.
<form class="velin-flex velin-flex--items-center velin-flex--gap-2">
<label for="sr-search" class="velin-sr-only">Search</label>
<input type="search" id="sr-search" class="velin-input"
placeholder="Search…">
<button type="submit" class="velin-btn velin-btn--primary">Go</button>
</form>
When to use which technique
There are several ways to hide content. Choose the right approach depending on whether the element should remain accessible.
| Technique | Visible | In accessibility tree | Occupies space | Best for |
|---|---|---|---|---|
.velin-sr-only |
No | Yes | No | Content only screen readers should announce |
display: none |
No | No | No | Content hidden from everyone |
visibility: hidden |
No | No | Yes | Reserving layout space while hiding content |
aria-hidden="true" |
Yes | No | Yes | Decorative visuals that screen readers should ignore |
Accessibility
- Keeps content in the accessibility tree while clipping it visually — suited to WCAG-oriented labeling patterns.
initA11y({ skipLink: true })can inject a skip link targeting#main; docs already ship a skip link in chrome.- Also available:
.velin-not-sr-onlyto undo the clip in nested contexts.