Catalog · Documentation
Shell
The page of a documentation site in three columns: the sidebar, the content and a rail, down to one column on a phone.
Fits best: docs — the layout of every page of a documentation site
Example
The shell is the whole page, so it has no live example inside another page. The markup below is a complete page: copy it, add your own content and resize the window.
It is three columns from 80rem, two from 60rem and one below, with the rail above the content when there is no third column. Documentation templates has the same page filled in.
Known issues
None known.
Code
Copy the markup
import "@luz-ds/catalog/components/docs-layout.css";
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/components/docs-layout.min.css" integrity="sha384-4mL+wj5xGmF98hYy2houcLGyUl4xNNTemLvMbtsCj1A7wpQ7RE3Ng26GboK9hgm9" crossorigin="anonymous">
The shell on <body>, then the header, the sidebar, the rail, the content and the footer, in the order a keyboard reaches them. The skip link goes to the content, past the sidebar and the rail:
<body class="o-shell luz-docs-layout">
<a class="luz-skip-link" href="#main-content">Skip to content</a>
<header>
<button class="luz-nav-toggle" type="button" popovertarget="docs-nav" aria-label="Menu">…</button>
<p><a href="/">Acme docs</a></p>
</header>
<nav class="luz-sidebar luz-docs-nav" id="docs-nav" aria-label="Acme docs" popover>…</nav>
<aside class="luz-page-rail" aria-label="About this page">…</aside>
<main class="o-main luz-docs-main" id="main-content" tabindex="-1">
<header class="luz-doc-header">…</header>
…
</main>
<footer>…</footer>
</body>
Variants and options
No modifier. Three classes on native elements, and three custom properties.
| Class or property | Effect |
|---|---|
.luz-docs-layout | On <body>, with core's .o-shell: the tracks and where each part goes |
.luz-docs-nav | With the catalog's .luz-sidebar, on the <nav>: the sidebar's column |
.luz-docs-main | With .o-main, on the <main>: the content's column. Its children keep to the measure |
.luz-page-rail | On an <aside>: the third column from 80rem, above the content below it. See Rail |
--luz-docs-measure | A line of text: 46rem. Set it on the shell in your own CSS to change it |
--luz-docs-nav-w, --luz-page-rail-w | The sidebar and the rail: 16.5rem and 14rem |
--luz-page-rail-top | How far from the top the rail sticks. Raise it under a sticky header |
How it works
CSS from components/docs-layout.css of @luz-ds/catalog on core's shell and the catalog's sidebar. The file gives the tracks and the measure; core gives the grid, and the sidebar the drawer.
- From 80rem there are three tracks: sidebar, content, rail. From 60rem there are two, with the rail drawn above the content. Below, one, in the order of the markup: sidebar, rail, content, footer.
- A plain
<header>goes across every track. The footer sits under the content, and the sidebar runs down beside it. - Between 769px and 60rem the sidebar is the first block above the content. At 768px and below it is the sidebar's drawer, a popover the menu button opens.
- Every child of the content keeps to
--luz-docs-measure, so an example is as wide as a line of text. In print the rail is left out.
Without JavaScript
Nothing changes: the layout is CSS. The drawer is a popover opened by the menu button's popovertarget, with no script.
In a browser without the popover API the sidebar stays in the page, above the content.
Keyboard and ARIA
- Order: the order of the source; the grid does not change it. Skip link, header, sidebar, rail, content, footer. The skip link goes to the content, past the sidebar and the rail.
- Skip link: put the skip link first, aimed at the
<main>, so a keyboard user passes the sidebar. - Landmarks: a
<header>child of<body>is the banner; name the<nav>after the site and the<aside>"About this page". - Keys: Enter or Space on the menu button opens the drawer; Escape closes it. The browser does it.
Contrast and focus are in the Design tab.
Design
When to use
Use the shell for the pages of a documentation site: read one after another, with a sidebar of all of them and a list of the sections of the page.
- Your site has more pages than fit in a header.
- Readers move through pages in order.
When not to use
Do not use the shell for a page that is not documentation: it assumes a sidebar and a content column.
- A page with no sidebar uses core's
.o-page: see the page and its bars. - A web application has App; a blog has CMS.
Do and don't
<nav class="luz-sidebar luz-docs-nav">…</nav>
<aside class="luz-page-rail">…</aside>
<main class="o-main luz-docs-main">…</main>
<nav class="luz-sidebar luz-docs-nav">…</nav>
<main class="o-main luz-docs-main">…</main>
<aside class="luz-page-rail">…</aside>
Writing the content
The shell has few words of its own, and each is a name.
- Skip link: "Skip to content".
- Sidebar:
aria-labelthe name of the documentation, such as "Acme docs". Not "Navigation": the role already says it. - Rail: "About this page". Its list is named "On this page".
- Sidebar links: the titles of the pages, in the order a reader goes through them.
- Menu button: "Menu".
Contrast and focus
The shell sets no colour of its own. The text sits on the page surface, and the sidebar keeps its own colours.
| Part | Colour on background | Light | Dark | High contrast | Needs |
|---|---|---|---|---|---|
Content text | --luz-text-primary on --luz-surface-page | 15.8:1 | 15.1:1 | 21.0:1 | 4.5:1 |
Sidebar link | --luz-sidebar-text on --luz-sidebar-bg | 10.9:1 | 10.0:1 | 14.1:1 | 4.5:1 |
Current sidebar link | --luz-sidebar-active-text on --luz-sidebar-active-bg | 10.3:1 | 10.2:1 | 21.0:1 | 4.5:1 |
Focus ring | --luz-focus-ring on --luz-surface-page | 5.6:1 | 7.7:1 | 21.0:1 | 3:1 |
Measured from the token values of each mode, rounded down. Needs is the WCAG 2.2 AA minimum: 4.5:1 for text, 3:1 for focus rings, borders and icons.
- Focus: every link and button keeps core's ring, 2 px of
--luz-focus-ring. - Reflow: at 320px the page is one column and does not scroll sideways. It is checked in the tests.
Tokens it uses
The 4 tokens that the .luz-docs-layout rules of catalog’s components/docs-layout.css read, by family. Each family links to its page, with the values in every mode. In Figma they are variables with the same names: see Tokens in Figma.
- Spacing and sizing
--luz-space-3xl,--luz-space-lg,--luz-space-md,--luz-space-xl
Keyboard and ARIA are in the Code tab.