Skip navigation links for screen reader and keyboard users. Because the main content is not usually the first thing in the document, it is valuable to provide a shortcut for keyboard and screen reader users to skip to the content.
npm install @chakra-ui/skip-navimport { SkipNavLink, SkipNavContent } from "@chakra-ui/skip-nav";For type imports:
import type { SkipNavLinkProps, SkipNavContentProps } from "@chakra-ui/skip-nav";For system type imports:
import type {
HTMLChakraProps,
ThemingProps,
SystemStyleObject
} from "@chakra-ui/system";import { SkipNavLink, SkipNavContent } from "@chakra-ui/skip-nav";
function App() {
return (
<>
{/* Place the skip link at the top of your app */}
<SkipNavLink>Skip to content</SkipNavLink>
<nav>
{/* Your navigation content */}
</nav>
{/* Place the content target around your main content */}
<SkipNavContent>
<main>
{/* Your main content */}
</main>
</SkipNavContent>
</>
);
}The Skip Nav component system consists of two parts:
Both components use the same id prop (defaulting to "chakra-skip-nav") to establish the link relationship. The link remains invisible until accessed via keyboard navigation, following web accessibility best practices.
Renders a link that remains hidden until focused to skip to the main content. The link becomes visible when users navigate with the keyboard (Tab key), allowing them to bypass repetitive navigation elements.
/**
* Renders a link that remains hidden until focused to skip to the main content
*/
export const SkipNavLink: React.ForwardRefExoticComponent<
SkipNavLinkProps & React.RefAttributes<HTMLAnchorElement>
>;Usage Examples:
// Basic usage with default id
<SkipNavLink>Skip to main content</SkipNavLink>
// Custom id to match specific target
<SkipNavLink id="main-content">Skip to main</SkipNavLink>
// With Chakra UI styling props
<SkipNavLink
bg="blue.500"
color="white"
px={4}
py={2}
borderRadius="md"
_focus={{
bg: "blue.600",
boxShadow: "outline"
}}
>
Skip to content
</SkipNavLink>
// With theming props
<SkipNavLink variant="solid" size="sm" colorScheme="blue">
Skip to content
</SkipNavLink>
// With additional HTML props
<SkipNavLink className="custom-skip-link" data-testid="skip-nav">
Skip to content
</SkipNavLink>Renders a div as the target for the SkipNavLink. This component wraps or precedes the main content area and receives focus when the skip link is activated.
/**
* Renders a div as the target for the SkipNavLink
*/
export const SkipNavContent: React.ForwardRefExoticComponent<
SkipNavContentProps & React.RefAttributes<HTMLDivElement>
>;Usage Examples:
// Basic usage wrapping main content
<SkipNavContent>
<main>
<h1>Main Content</h1>
<p>Your main content here...</p>
</main>
</SkipNavContent>
// Custom id to match specific link
<SkipNavContent id="main-content">
<section>Content section</section>
</SkipNavContent>
// With Chakra UI styling props
<SkipNavContent
p={4}
bg="gray.50"
borderRadius="lg"
outline="none"
_focus={{ boxShadow: "outline" }}
>
<main>Main content</main>
</SkipNavContent>
// As a marker before content (receives focus programmatically)
<SkipNavContent />
<main>
<h1>Main Content</h1>
</main>// Skip Nav component type definitions
interface SkipNavLinkProps extends HTMLChakraProps<"a">, ThemingProps<"SkipNavLink"> {
/** The id of the target element to skip to. Defaults to "chakra-skip-nav" */
id?: string;
}
interface SkipNavContentProps extends HTMLChakraProps<"div"> {
/** The id that matches the SkipNavLink href. Defaults to "chakra-skip-nav" */
id?: string;
}
// Chakra UI system types (from @chakra-ui/system)
type HTMLChakraProps<T extends As> = Omit<
React.ComponentPropsWithoutRef<T>,
"ref" | keyof StyleProps
> & ChakraProps & { as?: As };
type As = React.ElementType;
interface ChakraProps extends SystemProps {
/** Used to truncate text at a specific number of lines */
noOfLines?: ResponsiveValue<number>;
/** Used for internal css management (private) */
__css?: SystemStyleObject;
/** Used to pass theme-aware style props */
sx?: SystemStyleObject;
/** The emotion's css style object */
css?: Interpolation<{}>;
}
interface ThemingProps<ThemeComponent extends string = any> {
variant?: ResponsiveValue<
ThemeComponent extends keyof ThemeTypings["components"]
? ThemeTypings["components"][ThemeComponent]["variants"]
: string
>;
size?: ResponsiveValue<
ThemeComponent extends keyof ThemeTypings["components"]
? ThemeTypings["components"][ThemeComponent]["sizes"]
: string
>;
colorScheme?: ThemeTypings["colorSchemes"];
orientation?: "vertical" | "horizontal";
styleConfig?: Record<string, any>;
}
// Supporting types
type ResponsiveValue<T> = T | ResponsiveArray<T> | ResponsiveObject<T>;
type ResponsiveArray<T> = Array<T | null>;
type ResponsiveObject<T> = Partial<Record<string, T>>;
type SystemStyleObject = RecursiveCSSObject<CSSWithMultiValues>;
interface SystemProps extends StyleProps, PseudoProps {}
// Key styling props available on all Chakra components
interface StyleProps {
// Layout
display?: ResponsiveValue<CSS.Property.Display>;
w?: ResponsiveValue<CSS.Property.Width>;
width?: ResponsiveValue<CSS.Property.Width>;
h?: ResponsiveValue<CSS.Property.Height>;
height?: ResponsiveValue<CSS.Property.Height>;
// Colors
color?: ResponsiveValue<string>;
bg?: ResponsiveValue<string>;
backgroundColor?: ResponsiveValue<string>;
// Spacing
m?: ResponsiveValue<CSS.Property.Margin>;
margin?: ResponsiveValue<CSS.Property.Margin>;
p?: ResponsiveValue<CSS.Property.Padding>;
padding?: ResponsiveValue<CSS.Property.Padding>;
px?: ResponsiveValue<CSS.Property.PaddingLeft>;
py?: ResponsiveValue<CSS.Property.PaddingTop>;
// Borders
border?: ResponsiveValue<CSS.Property.Border>;
borderRadius?: ResponsiveValue<CSS.Property.BorderRadius>;
borderColor?: ResponsiveValue<string>;
// Position
position?: ResponsiveValue<CSS.Property.Position>;
top?: ResponsiveValue<CSS.Property.Top>;
left?: ResponsiveValue<CSS.Property.Left>;
// And many more CSS properties...
}
// Pseudo-selector props
interface PseudoProps {
_hover?: SystemStyleObject;
_focus?: SystemStyleObject;
_focusVisible?: SystemStyleObject;
_active?: SystemStyleObject;
_disabled?: SystemStyleObject;
_visited?: SystemStyleObject;
// And many more pseudo-selectors...
}As Chakra UI components, both SkipNavLink and SkipNavContent support the full Chakra UI styling system:
All standard Chakra UI style props are available:
// Layout props
<SkipNavLink display="block" w="200px" h="40px" />
// Color props
<SkipNavLink bg="gray.100" color="gray.800" />
// Spacing props
<SkipNavLink p={4} m={2} px={6} py={3} />
// Border props
<SkipNavLink border="1px solid" borderColor="gray.200" borderRadius="md" />
// Position props
<SkipNavLink position="fixed" top={4} left={4} zIndex={999999} />Support for all Chakra UI pseudo-selector props:
<SkipNavLink
_hover={{ bg: "blue.600" }}
_focus={{
bg: "blue.700",
boxShadow: "outline",
transform: "translateY(0)"
}}
_active={{ bg: "blue.800" }}
/>The SkipNavLink component can be themed through Chakra UI's theme system using the SkipLink component key:
// In your theme
const theme = {
components: {
SkipLink: {
baseStyle: {
position: "absolute",
left: "-999px",
// ... other styles
},
variants: {
solid: {
bg: "blue.500",
color: "white",
},
outline: {
border: "1px solid",
borderColor: "blue.500",
}
}
}
}
}All style props support responsive values using arrays or objects:
// Array syntax (mobile-first)
<SkipNavLink px={[2, 4, 6]} />
// Object syntax
<SkipNavLink px={{ base: 2, md: 4, lg: 6 }} />Use the sx prop for advanced styling with full TypeScript support:
<SkipNavLink
sx={{
clipPath: "inset(50%)",
_focus: {
clipPath: "none",
position: "fixed",
top: 4,
left: 4,
zIndex: 999999,
}
}}
/>SkipNavContent) has tabIndex={-1} to receive programmatic focus