Page
A page places units on the grid: navigation, content and optional supporting areas, in one of six layouts. See the full-page Examples for all six.
Design examples
Section titled “Design examples”A page title, quiet count and a few aligned rows establish hierarchy.
<section class="specimen">
<ds-page><ds-row class="line" auto><ds-text literal size="display">New acquisitions</ds-text></ds-row><ds-gap></ds-gap><ds-row class="line" ><ds-text literal tone="muted" size="small">Three additions this week</ds-text></ds-row><ds-list><ds-row class="line" ><span class="mark"><ds-icon type="page" size="large" aria-hidden="true"></ds-icon></span><ds-text literal class="grow">A book of windows</ds-text><ds-text literal class="mono">2026</ds-text></ds-row><ds-row class="line" ><span class="mark"><ds-icon type="page" size="large" aria-hidden="true"></ds-icon></span><ds-text literal class="grow">Along the river</ds-text><ds-text literal class="mono">2025</ds-text></ds-row><ds-row class="line" ><span class="mark"><ds-icon type="page" size="large" aria-hidden="true"></ds-icon></span><ds-text literal class="grow">The listening room</ds-text><ds-text literal class="mono">2026</ds-text></ds-row></ds-list></ds-page>
</section>
<style>
.specimen { width: 100%; min-width: 0; --cell: calc(20px * var(--sf, 1)); }
.specimen .line { width: 100%; }
.specimen .grow { flex: 1; min-width: 0; }
.specimen .muted { color: var(--ds-text-color-muted); }
.specimen .mono { --ds-typeface-regular: var(--ds-typeface-mono); font-variant-numeric: tabular-nums; }
.specimen .value { width: calc(4 * var(--cell)); text-align: right; }
.specimen .mark { display: inline-flex; align-items: flex-end; width: var(--cell); height: var(--ds-control-height); flex: 0 0 var(--cell); }
.specimen .columns { display: flex; flex-wrap: wrap; gap: var(--cell); }
.specimen .columns > * { min-width: 0; }
.specimen fieldset { border: 0; padding: 0; margin: 0; }
.specimen legend { padding: 0; }
.specimen label { display: flex; align-items: flex-end; gap: calc(var(--cell) / 2); min-height: var(--cell); }
.specimen ds-panel { height: calc(10 * var(--cell)); }
</style> Try it
Section titled “Try it”The sidebar layout: navigation on the left, a header and the work on the right. Every area is named.
<ds-page layout="sidebar" divided view>
<ds-list slot="nav">
<ds-row><ds-text>Inbox</ds-text></ds-row>
<ds-row><ds-text>Projects</ds-text></ds-row>
</ds-list>
<ds-row slot="header" fill>
<ds-text literal strong>Projects</ds-text>
<ds-button primary>New item</ds-button>
</ds-row>
<ds-list>
<ds-row fill><ds-text>Write the brief</ds-text><ds-badge>Done</ds-badge></ds-row>
<ds-row fill><ds-text>Sketch the home page</ds-text><ds-badge>Next</ds-badge></ds-row>
</ds-list>
</ds-page> Use it
Section titled “Use it”<ds-page layout="sidebar" divided> <ds-sidebar slot="nav" label="Projects"></ds-sidebar> <ds-row slot="header" fill>…</ds-row> <ds-list>…</ds-list></ds-page>Every layout has the same five areas, so content moves between layouts without being rewritten. An area with nothing in it takes no room.
| Area | Put it there with | Holds |
|---|---|---|
| Header | slot="header" | The page’s title and its main actions, along the top of the main area. |
| Nav | slot="nav" | Navigation, or the list in List and detail. The leading column. |
| Main | No slot | The work itself. |
| Aside | slot="aside" | Properties or related things. Its own column in Inspector, under the main area elsewhere. |
| Footer | slot="footer" | Closing actions such as Save, along the bottom of the main area. |
Widths
Section titled “Widths”Every column is a whole number of squares. Between columns there are two squares, between areas down the page one, and one around the page.
| Layout | Leading column | Main | Trailing column |
|---|---|---|---|
sidebar | 12 squares | The rest | — |
split | 16 squares | The rest | — |
inspector | 12 squares | The rest | 12 squares |
column | — | 32 squares, centred on the grid | — |
centered | — | 16 squares, centred on the grid both ways | — |
tiles | — | 12-square tiles | — |
Below 30 squares of width every layout becomes one column, navigation first. The layout follows the width of its own container, not the window, so a page inside a panel stacks when the panel is narrow.
Attributes
Section titled “Attributes”| Attribute | Default | What it does |
|---|---|---|
layout | sidebar | sidebar, split, inspector, column, centered or tiles. |
divided | false | Draws a hairline between the columns. |
measure | — | The width of the column or centered column, in whole squares. |
fill | false | Takes its container’s full height; each column scrolls on its own. |
view | false | Outlines each area and names it, for inspection. |
drawer | false | Folds the navigation into a drawer on a narrow page. |
drawer-label | Menu | The menu button’s and drawer’s name, a translation key. |
A drawer on a narrow page
Section titled “A drawer on a narrow page”With drawer, the navigation folds away below 30 squares instead of standing above the work. A menu button stands in a one-square column before the header and opens the navigation over the whole screen, the same screen overlay the Header opens: focus stays inside it, Escape, its close button, a link or the page widening close it, and the page holds its scroll meanwhile. ds-page-drawer reports it opening and closing (detail.open); openDrawer() and closeDrawer() work it from code.
<ds-page layout="sidebar" drawer> <ds-sidebar slot="nav" label="Projects"></ds-sidebar> <h1 slot="header">Inbox</h1> …</ds-page>Setting the measure
Section titled “Setting the measure”A column or centered page is as wide as its measure: 32 squares and 16 by default. Set another in whole squares with measure:
<ds-page layout="column" measure="28">…</ds-page>measure="28" is exactly 28 squares at every scale. A fraction rounds to the nearest square, and zero, a negative number or text is ignored, so the layout keeps its own width. The attribute wins over --ds-page-measure, which is the same width as a custom property for styles that cannot reach the element’s attributes; write it in squares too, never pixels: --ds-page-measure: calc(28 * var(--ds-unit)). --ds-page-nav, --ds-page-aside and --ds-page-tile set the other widths the same way.
Standing on the grid
Section titled “Standing on the grid”Centring a column in the width it has can leave it on a half square, off the grid lines the rest of the page is drawn on. ds-page shares the room beside the column out and rounds it down to whole squares, so the column always starts and ends on a grid line. When that room is an odd number of squares, the extra square falls on the trailing side. With less room than the measure needs, the column takes the width it has and stays one square in from the edge.
In React
Section titled “In React”Import the typed adapter. It renders <ds-page> with layout, divided, measure, fill, view, drawer and drawerLabel typed, so the product declares nothing of its own:
import { Page } from "./design/react/page";
<Page layout="column" measure={28} divided> <h1 slot="header">Settings</h1> …</Page>The adapter does not register the element: import 4-page/ds-page once in the browser entry, as for the other components. A product that writes <ds-page> directly instead needs a JSX.IntrinsicElements entry for it in its own declarations, because React does not know custom elements; the adapter replaces that entry. Sync 1 copies react/page.ts with the component when a product names page in its components.