Skip Nav
Allows keyboard and screen reader users to skip repeated content and jump straight to the main content of the page.
Navigation
Repeated on every page, so keyboard users want to skip past it.
Main Content
Focus lands here when the skip link is activated.
import { Box, SkipNavContent, SkipNavLink, Stack, Text } from '@chakra-ui/react'
export const SkipNavBasic = () => {
return (
<Stack gap="4">
<SkipNavLink>Skip to Content</SkipNavLink>
<Box p="4" borderWidth="1px" borderRadius="panel.md" bg="bg.muted">
<Text fontWeight="medium">Navigation</Text>
<Text textStyle="sm" color="fg.muted">
Repeated on every page, so keyboard users want to skip past it.
</Text>
</Box>
<SkipNavContent />
<Box p="4" borderWidth="1px" borderRadius="panel.md">
<Text fontWeight="medium">Main Content</Text>
<Text textStyle="sm" color="fg.muted">
Focus lands here when the skip link is activated.
</Text>
</Box>
</Stack>
)
}
Anatomy
import { SkipNavContent, SkipNavLink } from '@chakra-ui/react'<SkipNavLink>Skip to content</SkipNavLink>
<SkipNavContent />Usage
Per WCAG 2.4.1 (Bypass Blocks — Level A), a page that repeats the same navigation across pages should offer a way to bypass it. A screen reader user can jump between headings or landmarks, but a sighted keyboard user cannot — they have to tab through every navigation link before reaching the content.
The key things to note:
SkipNavLinkrenders anatag that is visually hidden until it receives keyboard focus. Place it as high in the tree as possible, so it is the first thing a user tabs to.SkipNavContentrenders adivthat acts as the target. It can be self-closing or wrap your main content.- Both components share a default
id, so they link up without any configuration.
Examples
Basic
Render SkipNavLink before your navigation and SkipNavContent right before
the main content. Tab into the example below to reveal the link.
Navigation
Repeated on every page, so keyboard users want to skip past it.
Main Content
Focus lands here when the skip link is activated.
import { Box, SkipNavContent, SkipNavLink, Stack, Text } from '@chakra-ui/react'
export const SkipNavBasic = () => {
return (
<Stack gap="4">
<SkipNavLink>Skip to Content</SkipNavLink>
<Box p="4" borderWidth="1px" borderRadius="panel.md" bg="bg.muted">
<Text fontWeight="medium">Navigation</Text>
<Text textStyle="sm" color="fg.muted">
Repeated on every page, so keyboard users want to skip past it.
</Text>
</Box>
<SkipNavContent />
<Box p="4" borderWidth="1px" borderRadius="panel.md">
<Text fontWeight="medium">Main Content</Text>
<Text textStyle="sm" color="fg.muted">
Focus lands here when the skip link is activated.
</Text>
</Box>
</Stack>
)
}
Custom ID
Pass a custom id to change the anchor. The value must be set on both
components, otherwise the link has nothing to point at.
Header & Navigation
Both components use the same main-content id.
Main Content
The id must match on both sides, otherwise the link does nothing.
import { Box, SkipNavContent, SkipNavLink, Stack, Text } from '@chakra-ui/react'
export const SkipNavCustomId = () => {
return (
<Stack gap="4">
<SkipNavLink id="main-content">Skip to Main Content</SkipNavLink>
<Box p="4" borderWidth="1px" borderRadius="panel.md" bg="bg.muted">
<Text fontWeight="medium">Header & Navigation</Text>
<Text textStyle="sm" color="fg.muted">
Both components use the same <code>main-content</code> id.
</Text>
</Box>
<SkipNavContent id="main-content" />
<Box p="4" borderWidth="1px" borderRadius="panel.md">
<Text fontWeight="medium">Main Content</Text>
<Text textStyle="sm" color="fg.muted">
The id must match on both sides, otherwise the link does nothing.
</Text>
</Box>
</Stack>
)
}
Wrapping the content
SkipNavContent can wrap the main content area instead of being self-closing.
This makes the whole region the focus target, which reads better in screen
readers.
Site Header
Home
About
Pricing
Contact
import {
Box,
Heading,
SkipNavContent,
SkipNavLink,
Stack,
Text,
} from '@chakra-ui/react'
export const SkipNavWithContent = () => {
return (
<Stack gap="4">
<SkipNavLink>Skip to Content</SkipNavLink>
<Box p="4" borderWidth="1px" borderRadius="panel.md" bg="bg.muted">
<Text fontWeight="medium">Site Header</Text>
<Stack gap="1" mt="2">
<Text textStyle="sm" color="fg.muted">
Home
</Text>
<Text textStyle="sm" color="fg.muted">
About
</Text>
<Text textStyle="sm" color="fg.muted">
Pricing
</Text>
<Text textStyle="sm" color="fg.muted">
Contact
</Text>
</Stack>
</Box>
<SkipNavContent>
<Box p="6" borderWidth="1px" borderRadius="panel.md">
<Heading size="lg" mb="2">
Welcome
</Heading>
<Text textStyle="sm" color="fg.muted">
Wrapping the main content makes the whole region the focus target,
so screen readers continue reading from here.
</Text>
</Box>
</SkipNavContent>
</Stack>
)
}
Props
Link
| Prop | Default | Type |
|---|---|---|
id | 'chakra-skip-nav' | stringThe id of the `SkipNavContent` to link to. Must match the id used on `SkipNavContent`. |
children | React.ReactNodeThe label of the link, for example "Skip to content". | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Content
| Prop | Default | Type |
|---|---|---|
id | 'chakra-skip-nav' | stringThe id used as the anchor target. Must match the id used on `SkipNavLink`. |
children | React.ReactNodeOptional main content to wrap. When omitted the component renders an empty div that acts as the focus target. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |