Components / A11y

VisuallyHidden

VisuallyHidden renders content that a screen reader announces but the eye never sees. Use it for labels and headings that the visual design conveys some other way.

Loading playground…
Updated 3 days agoEdit on GitHubWeb & native

What it is

A span (or div) styled with the standard "sr-only" pattern — a one-pixel clipped box that keeps the content in the accessibility tree while removing it from the visual layout. This is not display: none, which would drop the content from both. VisuallyHidden hides from sight only.

Install

VisuallyHidden is exported from usemotif. No separate install.

example.tsx
import { VisuallyHidden } from 'usemotif';

API

VisuallyHidden

stable
function VisuallyHidden(props: VisuallyHiddenProps): JSX.Element
as"span" | "div"= "span"

The element to render. Use `div` when the hidden content is block-level.

childrenReactNode

The screen-reader-only content.

Accessibility

VisuallyHidden bridges the gap between what a design shows and what it says. A search button with only a magnifying-glass icon reads as nothing — wrap a "Search" label in VisuallyHidden and the button has an accessible name without changing the visual. A section whose heading is obvious from layout but absent from the markup breaks the heading outline — a VisuallyHidden heading repairs it.

Use it for content that is genuinely present, just conveyed visually by other means. It is not a place to park text you do not want shown — a screen-reader user reads everything inside it.

Examples

An accessible name for an icon-only button:

example.tsx
<IconButton aria-label="Search">
<SearchIcon />
</IconButton>

Or, when the label is text rather than an aria-label:

example.tsx
<Pressable onPress={search}>
<SearchIcon />
<VisuallyHidden>Search</VisuallyHidden>
</Pressable>

A heading that keeps the outline intact:

example.tsx
<VisuallyHidden as="div">
<Heading level={2}>Search results</Heading>
</VisuallyHidden>