Skip to content

Layout and Spacing

Karthik P edited this page Oct 24, 2026 · 1 revision

This page sets the spacing scale, page widths, breakpoints and grids of the docs and landing pages, including what changes on phones. Use it when placing anything on a page; the values are defined once on Design Tokens.

Spacing scale

A 4 px base. Use only these steps, for padding, margins and gaps.

Token px Tailwind step Typical use (Proposed)
space.0 0 0 Resetting a margin
space.4 4 1 Icon to label, inline code padding
space.8 8 2 Between buttons in a group, between sidebar items
space.12 12 3 Callout padding, table cell padding (vertical)
space.16 16 4 Phone gutter, paragraph gap, code block padding
space.20 20 5 Label to input group in the demo
space.24 24 6 Tablet gutter, card and demo frame padding
space.32 32 8 Desktop gutter, space above an H3
space.40 40 10 Space above an H2
space.48 48 12 Top of a docs page, footer padding
space.64 64 16 Landing section padding, phones
space.80 80 20 Landing section padding, tablets
space.96 96 24 Landing section padding, desktop

Tailwind's --spacing is already 0.25 rem, so p-4 is 16 px with no theme change (Tailwind: Theme variables). Our components use no steps outside the scale (p-7, gap-[18px]). Fumadocs' own components use a few other steps internally; leave those.

Widths

Token Value What it is Fumadocs default (fumadocs-ui 16.17.8)
layout.header 64 px Sticky header height 56 px (h-14)
layout.sidebar 280 px Docs sidebar, from 768 px 268 px
layout.prose 640 px Maximum width of docs text, about 85 characters (Typography) Page column up to 900 px including padding
layout.toc 220 px "On this page" column, from 1280 px 268 px
layout.page 1400 px Maximum width of header and docs grid 97 rem (1552 px)
layout.landing 1200 px Landing page container Home layout: 1400 px
layout.gutter 16 px minimum Side gutter on phones 16 px (px-4)

At 1400 px the docs grid is 280 + 900 + 220. The 900 px content column holds 640 px of prose plus gutters, with room for wide tables and code to break out if a page needs it.

Breakpoints

Tailwind's defaults, unchanged: sm 640, md 768, lg 1024, xl 1280, 2xl 1536 px (tailwindcss 4.3.3). The docs use Fumadocs' Notebook layout with a top header (decision log on Design System); its behaviour at each width, from fumadocs-ui 16.17.8 layouts/notebook/slots/:

Width Header Sidebar On this page Gutter Docs H1 Landing headline
< 640 Logo, search icon, menu button Drawer from the menu button; holds the nav links, GitHub link and theme toggle Collapsed bar under the header 16 px 30 px (Proposed) 38 px
640–767 same same same 16 px 38 px 38 px
768–1023 Logo, search field, theme toggle Fixed column, 280 px; the nav links and GitHub link sit at its top and bottom Collapsed bar 24 px 38 px 48 px (Proposed)
1024–1279 Logo, search field, nav links, GitHub, theme toggle Fixed column, 280 px Collapsed bar 24 px 38 px 60 px
≥ 1280 same same Column, 220 px 32 px 38 px 60 px

The drawer, the collapsed bar, where the links move and the gutters are Fumadocs' behaviour; we change only the widths and the header height. The landing page's Home layout also moves its links into a menu below 1024 px.

Docs page grid

A full-width header above sidebar, content and table of contents, like nextjs.org/docs: Fumadocs' Notebook layout (fumadocs-ui/layouts/notebook) with nav: { mode: 'top' } (Fumadocs: Notebook).

|<---------------------------------- max 1400 ---------------------------------->|
+--------------------------------------------------------------------------------+
| [mark] workclock  [Search Ctrl K]  Docs Migrating Playground Benchmarks GH (o) |  64, sticky
+-----------------------+------------------------------------------+-------------+
| sidebar 280           | content column 900                       | on this     |
|                       |    |<-------- prose 640 -------->|       | page 220    |
| Start                 |    | Adding time (H1 38/1.1)     |       |             |
|   Install             |    |                             |       | Rules       |
| Concepts              |    | Body 16/1.7 ...             |       | Overnight   |
|   Adding time  <-amber|    |                             |       | Holidays    |
|   bar, surface bg     |    | +-------------------------+ |       |             |
|                       |    | | code, surface, radius 8 | |       |             |
|                       |    | +-------------------------+ |       |             |
+-----------------------+------------------------------------------+-------------+

Landing page grid

The same header links and a 1200 px container. Sections are on Landing Page.

|<---------------------------------- max 1400 ---------------------------------->|
+--------------------------------------------------------------------------------+
| [mark] workclock             Docs Migrating Playground Benchmarks  [S] GH (o)  |  64
+--------------------------------------------------------------------------------+
|   |<--------------------------- container 1200 --------------------------->|   |
|   |  Add 8 working hours.                 (display 60/1.1)                 |   |
|   |  Land on Wednesday at 09:30.                                           |   |
|   |  One-line description                 (max 600)                        |   |
|   |  [ install commands ]                                                  |   |
|   |                                                   96                   |   |
|   |  +------------------------------------------------------------------+  |   |
|   |  | demo frame: surface, radius 12, padding 24                       |  |   |
|   |  |  Tue 29  ####=========####======                                 |  |   |
|   |  |  Wed 30  ###|  Due Wed 30 Dec, 09:30   (| = due marker, amber)   |  |   |
|   |  +------------------------------------------------------------------+  |   |
|   |                                                   96                   |   |
|   |  Next section ...                     (section 30/1.25)                |   |
+--------------------------------------------------------------------------------+

Phones

+-----------------------------------+
| [mark]                   [S] [=]  |  64, sticky
+-----------------------------------+
| On this page                  [v] |  collapsed bar
+-----------------------------------+
|16|                             |16|
|  | Adding time     (H1 30)     |  |
|  | Body 16/1.7 ...             |  |
|  | +-------------------------+ |  |
|  | | code: scrolls sideways  | |  |
|  | | inside its own block    | |  |
|  | +-------------------------+ |  |
+-----------------------------------+
Element Below 768 px
Header 64 px, sticky. The menu button opens the sidebar drawer; search is an icon button.
Sidebar Drawer above the page (z.drawer 40), Fumadocs' default. It must close on Escape and return focus to the menu button.
Prose Full width minus 16 px gutters. Nothing scrolls sideways at 320 px (Accessibility).
Code blocks, wide tables, the week strip Scroll sideways inside their own box; the page does not.
Landing demo Proposed: controls stack above the strip; each day row keeps the full width.
Tap targets At least 24 × 24 px (WCAG 2.5.8). Proposed: header buttons 40 × 40 px.

CSS

Fumadocs sets widths with CSS variables (--fd-layout-width, --fd-sidebar-width, --fd-toc-width, --fd-header-height). Only --fd-layout-width is documented (Fumadocs: Themes); the rest, the element ids and the fixed h-14 header height were read from fumadocs-ui 16.17.8 and must be checked after upgrades. Our rules are un-layered, so they win over Fumadocs' Tailwind utilities.

/* website/app/global.css — layout */
:root {
  --fd-layout-width: 1400px;
  scroll-padding-top: calc(var(--wc-header) + 16px);
}

/* Header height: the variable drives the grid, the h-14 class draws the bar. */
#nd-notebook-layout {
  --fd-header-height: var(--wc-header);
}
#nd-subnav [data-header-body],
#nd-nav,
#nd-nav nav {
  height: var(--wc-header);
}

@media (min-width: 768px) {
  #nd-notebook-layout:has(#nd-sidebar) {
    --fd-sidebar-width: var(--wc-sidebar);
  }
}

@media (min-width: 1280px) {
  #nd-notebook-layout:has(#nd-toc) {
    --fd-toc-width: var(--wc-toc);
  }
}

#nd-page .prose {
  max-width: var(--wc-prose);
}

.landing-container {
  max-width: var(--wc-landing);
  margin-inline: auto;
  padding-inline: var(--wc-gutter);
}

#nd-subnav is the Notebook header and #nd-nav the Home layout header. The header-height rule assumes no layout tabs in the header; Fumadocs makes the header taller when they are on. scroll-padding-top keeps headings reached from the table of contents, and elements reached with Tab, clear of the sticky header (Accessibility).

Stacking order

Token z-index What sits there
z.base 0 Page content
z.sticky 10 Sticky table headers, the collapsed "On this page" bar
z.sidebar 20 Docs sidebar
z.header 30 Site header
z.drawer 40 Mobile drawer, navigation menus
z.popover 50 Popovers, tooltips, the search dialog and its overlay
z.skip-link 60 The skip link while focused

The steps match Fumadocs' values (its dialogs and popovers are z-50). The scale applies to components we write; Fumadocs' elements keep theirs (its Notebook header is z-10, its Home header z-40). Nothing uses values between steps or above 60, and a component gets a z-index only when it overlaps something.

Open items

  • Proposed: the "typical use" column of the spacing scale; docs H1 at 30 px and landing headline at 48 px in the widths shown; the phone layout of the demo; 40 × 40 px header buttons.

Clone this wiki locally