Skip to main content
react-md

Skip to Main Content

This component is used to allow keyboard users a quick way to skip directly to the main content instead of needing to tab through all navigation items.

This component should not be used if using the LayoutAppBar component since it is already built-in.

Simple Example

The default behavior for the SkipToMainContent component will be to only be visible to screen readers or once keyboard focused. The user can then press the Enter key to focus the <main> element.

Try tabbing into the example below to see the default styles.

import { AppBar } from "@react-md/core/app-bar/AppBar";
import { SkipToMainContent } from "@react-md/core/link/SkipToMainContent";
import { type ReactElement } from "react";

export default function SimpleSkipToMainContentExample(): ReactElement {
  return (
    <AppBar style={{ position: "relative" }}>
      <SkipToMainContent />
    </AppBar>
  );
}

Press Enter to start editing.

Custom Focus Target

The SkipToMainContent can also be used within complex Dialogs to skip to the main content by providing the mainId prop pointing to the id of an element to focus.

The target element must either be a focusable element or have tabIndex={-1} to show it can be programmatically focused. The element might also need custom focus styles to override the default browser behavior.

import { Button } from "@react-md/core/button/Button";
import { Dialog } from "@react-md/core/dialog/Dialog";
import { DialogContent } from "@react-md/core/dialog/DialogContent";
import { DialogHeader } from "@react-md/core/dialog/DialogHeader";
import { DialogTitle } from "@react-md/core/dialog/DialogTitle";
import { main } from "@react-md/core/layout/mainStyles";
import { SkipToMainContent } from "@react-md/core/link/SkipToMainContent";
import { useToggle } from "@react-md/core/useToggle";
import CloseIcon from "@react-md/material-icons/CloseIcon";
import { type ReactElement, useId } from "react";

import styles from "./CustomFocusTargetExample.module.scss";

export default function CustomFocusTargetExample(): ReactElement {
  const mainId = useId();
  const { toggled, toggle, disable } = useToggle();

  return (
    <>
      <Button onClick={toggle}>Show</Button>
      <Dialog
        aria-label="Example"
        visible={toggled}
        onRequestClose={disable}
        type="full-page"
      >
        <DialogHeader>
          <SkipToMainContent mainId={mainId} className={styles.link} />
          <DialogTitle>Example</DialogTitle>
          <Button aria-label="Close" buttonType="icon" onClick={disable}>
            <CloseIcon />
          </Button>
        </DialogHeader>
        <DialogContent
          id={mainId}
          className={main({ className: styles.content })}
          // the target element **must** be focusable, so set it to `-1` if it
          // isn't to show that it can be programmatically focusable
          tabIndex={-1}
        >
          {"Here's the main content!"}
          <Button>Button!</Button>
        </DialogContent>
      </Dialog>
    </>
  );
}

Press Enter to start editing.

@use "everything";

.link {
  @include everything.theme-use-var(color, text-primary-color);
}

// The `main` focus styles use `position: fixed` by default so need to update
// the `top` value to be the dialog header's height which defaults to 5.75rem
// with padding
.content {
  @include everything.layout-set-var(header-height, 5.75rem);
}

// An alternative would be to just set the `DialogContent` to have position
// relative and update the focus styles to be absolute positioned with no inset
// .content {
//   position: relative;

//   &::before {
//     inset: 0;
//     position: absolute;
//   }
// }

// If you don't want to use the `main` class name utility for focus styles,
// here's a small example of adding focus styles
// .content {
//   outline: none;
//   position: relative;

//   &::before {
//     @include everything.pseudo-element;
//     @include everything.interaction-outline(
//       $color: everything.interaction-get-var(focus-color)
//     );

//     opacity: 0;
//   }

//   &:focus-visible::before {
//     opacity: 1;
//   }
// }

Press Enter to start editing.

The default styles can be configured by changing the core.$link-skip-to-main-z-index, core.$link-skip-to-main-styles, and core.$link-skip-to-main-active-styles Sass variables which would be applied globally. If custom styles are required for a single component, enable the unstyled prop to use the default link focus styles instead of the updated color and outline styles. This might make it easier to enable custom focus styles.

import { SkipToMainContent } from "@react-md/core/link/SkipToMainContent";
import { type ReactElement } from "react";

import styles from "./CustomLinkStylesExample.module.scss";

export default function CustomLinkStylesExample(): ReactElement {
  return <SkipToMainContent unstyled className={styles.link} />;
}

Press Enter to start editing.

.link {
  clip: auto;
  clip-path: none;
  height: auto;
  margin: auto;
  overflow: visible;
  white-space: normal;
  width: auto;

  &:focus-visible {
    clip: auto;
  }
}

Press Enter to start editing.