Footer
A site footer stands its brand and a line about the site at the start, in twelve squares; columns of links beside it, eight squares each, two squares apart; and two squares below, the legal line at the start and the preferences, language and theme, at the end. Every line is one square. Column headings are in the title grey, links in the text’s ink with a faint hairline under the pointer, and a hairline runs along the top. Columns that do not fit beside the brand go below it; on a narrow screen the brand stands above the columns and the preferences come before the legal line.
Design examples
Section titled “Design examples”Quiet grouped links under a short editorial identity.
<section class="specimen">
<ds-footer brand="Field Journal" tagline="Notes from places worth noticing" literal year="2026" columns='[{"heading":"Read","links":[{"label":"Essays","href":"#essays"},{"label":"Archive","href":"#archive"}]},{"heading":"Visit","links":[{"label":"Reading room","href":"#room"},{"label":"Contact","href":"#contact"}]}]'></ds-footer>
</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 cycles change this preview's language and theme. Columns that do not fit go under the brand.
<ds-footer brand="Studio" tagline="Tools for working on the grid" literal preferences year="2026" style="flex-basis:100%"
columns='[{"heading":"Product","links":[{"label":"Download","href":"#download"},{"label":"Help","href":"#help"}]},{"heading":"Company","links":[{"label":"About","href":"#about"},{"label":"Terms","href":"#terms"}]}]'>
</ds-footer> Use it
Section titled “Use it”<ds-footer brand="Name" tagline="What it does" preferences literal columns='[{"heading":"Product","links":[{"label":"Download","href":"/download"},{"label":"Help","href":"/help"}]}, {"heading":"Elsewhere","links":[{"label":"Instagram","href":"https://instagram.com/name","external":true}]}]'></ds-footer>columns is a list of { heading, links }, each link { label, href, external, current }: external opens in a new tab with no referrer, current marks the page being read. Words are translation keys unless literal. The copyright reads © <year> <owner>, this year and the brand by default. preferences puts a ds-cycle for each setting it names at the end of the last row: language, theme, or both when it is present and empty.
| Attribute | Type | Default | What it does |
|---|---|---|---|
brand | string | Empty | The site’s name, a link home. |
href | string | / | Where the brand links. |
tagline | string | Empty | A line about the site under the brand, muted. |
columns | FooterColumn[] | [] | The columns of links. |
label | string | Empty | Names the columns as a navigation; without it they are plain lists. |
owner | string | The brand | Who holds the copyright. |
year | number | This year | The copyright’s year. |
preferences | string | None | language, theme, or both. |
literal | boolean | false | Show the words as written. |
| Slot | What it holds |
|---|---|
brand | A brand of the page’s own: a logo, one square high. |
preferences | Controls of the page’s own beside the cycles, such as a currency. |
legal | The last line, in place of the copyright. |
In React
Section titled “In React”import { Footer } from "./design/react/footer";
<Footer brand="Name" literal preferences="" columns={[{ heading: "Product", links: [{ label: "Help", href: "/help" }] }]} />columns is set as a property. The adapter does not register the element: import 4-page/ds-footer once in the browser entry.