Skip to content
DataLeaf

Documentation

Design tokens

DataLeaf’s visual language is defined by CSS custom properties in the theme’s assets/css/tokens.css. Components use only these tokens, so a site can adjust the design by overriding them in custom CSS without touching component selectors. The regression tests keep this page in sync with the stylesheet and check that the default colors meet WCAG 2.2 AA in both color schemes.

The design is editorial rather than app-like: reading text and titles are set in a serif, the interface and metadata in a sans, and structure comes from thin rules, alignment, and whitespace instead of cards and shadows. Color is restrained: one accent for links and focus, a muted second color for annotations, and semantic tints for callouts.

Typography

#

Typeface families

#

Each stack names the bundled face first, then installed fonts of similar proportions, so the design holds when the bundle is disabled. With the bundle, a metric-matched fallback follows each text face: Arial or a metric-compatible clone for IBM Plex Sans, and Georgia, or Times New Roman and its clones where Georgia is missing, scaled to the width of Source Serif 4. Text is set in it while the bundled fonts load, so lines keep their breaks and the page does not shift when the fonts arrive. IBM Plex Sans, the interface face, is preloaded and loaded with font-display: optional: it is used from the first render when it arrives promptly, and otherwise from the next page, so a late font never rewraps the navigation.

TokenDefaultRole
--dl-font-serif"Source Serif 4", "Source Serif 4 Fallback", "Source Serif 4 Times Fallback", "Source Serif Pro", "Iowan Old Style", "Charter", "Bitstream Charter", "Sitka Text", Cambria, Georgia, serifEditorial serif for reading text and titles
--dl-font-sans"IBM Plex Sans", "IBM Plex Sans Fallback", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serifSans-serif for navigation, metadata, captions, and labels
--dl-font-mono"IBM Plex Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, "Liberation Mono", monospaceMonospace for code
--dl-font-math"STIX Two Math", "Cambria Math", "Latin Modern Math", "Libertinus Math", "TeX Gyre Pagella Math", "DejaVu Math TeX Gyre", "Noto Sans Math", mathMathML fonts with OpenType MATH tables

Typeface roles

#

Components choose a role, not a family. To set reading text in the sans, override --dl-font-body with var(--dl-font-sans).

TokenDefaultRole
--dl-font-displayvar(--dl-font-serif)Titles, headings, and entry titles in lists
--dl-font-bodyvar(--dl-font-serif)Prose, ledes, and summaries
--dl-font-uivar(--dl-font-sans)Interface text, metadata, captions, and labels
--dl-font-codevar(--dl-font-mono)Code blocks, inline code, and code labels

Font strategy

#

The theme bundles Source Serif 4, IBM Plex Sans, IBM Plex Mono, and STIX Two Math under the SIL Open Font License 1.1 and serves them from your own site: no font service, CDN, or tracking request is involved. Browsers download a file only when a page renders characters in that face and its unicode-range; a typical English page needs about 140 KB, and STIX Two Math (about 400 KB) loads only on pages with formulas when it is not installed.

To rely on installed fonts instead, disable the bundle:

toml
[params.fonts]
  bundled = false

The theme then publishes no font files and no @font-face rules. The family stacks above fall back to installed fonts: Iowan Old Style, Charter, Sitka Text, Cambria, or Georgia for the serif; the system interface font for the sans; and the system monospace. A locally installed copy of a bundled family is still used when present. To use other web fonts, keep the bundle disabled, declare your own @font-face rules in custom CSS, and override the family tokens.

Type scale

#

Interface sizes are fixed; reading text and titles grow slightly with the viewport.

TokenDefaultRole
--dl-text-xs0.8125remKickers, labels, archive dates, and code labels
--dl-text-sm0.875remMetadata, captions, tags, site tools, and status messages
--dl-text-ui0.9375remTable-of-contents links
--dl-text-md1.0625remPrimary navigation, summaries, search excerpts, and list entry titles
--dl-text-proseclamp(1.0625rem, 1rem + 0.25vw, 1.1875rem)Body text of articles and pages
--dl-text-lg1.25remLedes, fourth-level headings, and adjacent-article titles
--dl-text-xlclamp(1.375rem, 1.25rem + 0.5vw, 1.5rem)Third-level headings and entry titles
--dl-text-2xlclamp(1.625rem, 1.4rem + 0.9vw, 2rem)Second-level headings, section titles, and the masthead site title
--dl-text-3xlclamp(1.875rem, 1.5rem + 1.2vw, 2.5rem)Article titles
--dl-text-displayclamp(2.25rem, 1.75rem + 1.6vw, 3rem)The home page title

Line height, tracking, and weight

#
TokenDefaultRole
--dl-leading-tight1.1Display, article, and masthead titles
--dl-leading-heading1.25Headings and entry titles
--dl-leading-ui1.5Interface text and ledes
--dl-leading-code1.55Code blocks
--dl-leading-prose1.65Body text
--dl-tracking-display-0.02emThe home page title
--dl-tracking-title-0.015emArticle titles and the masthead site title
--dl-tracking-caps0.08emUppercase kickers and labels
--dl-weight-regular400Body and interface text
--dl-weight-strong600Headings and bold text; the bundled faces have no heavier weight

Rhythm

#

Paragraph spacing is relative to the text it separates, so it follows the body size.

TokenDefaultRole
--dl-flow-space1emSpace between paragraphs, lists, and display equations
--dl-block-spacevar(--dl-space-6)Space around code, tables, figures, callouts, and statements
--dl-heading-spaceclamp(var(--dl-space-6), 5vw, var(--dl-space-7))Space before article headings and thematic breaks

Layout

#
TokenDefaultRole
--dl-wide1180pxPage shell: header, main content, and footer
--dl-guttervar(--dl-space-4)Minimum space between the shell and the viewport edge
--dl-reading42remManuscript column: the reading measure of articles and pages, and the minimum width of wide technical content
--dl-reading-narrow37remLedes and list summaries
--dl-rail16remArticle side rail with the metadata and table of contents, from 72rem
--dl-wide-content60remMaximum width of wide technical content: tables, display equations, code, and figures marked wide
--dl-meta-width6remNarrow metadata columns, such as archive years and dates
--dl-control-height2.5remMinimum height of navigation links, site tools, and controls

Breakpoints

#

Media queries cannot read custom properties, so the layout changes at four fixed widths rather than at tokens. Visual checks cover 320, 375, 768, 1024, 1280, 1440, and 1920px around them.

NameWidthWhat changes
compactbelow 32rem (512px)List entries, archive rows, and pagination stack in one column
medium40rem (640px)Site tools are separated by hairlines, the footer sits on one line, and previous and next articles sit side by side
large64rem (1024px)The front page sets its introduction and latest writing in two columns
wide72rem (1152px)Articles and discovery pages gain the side rail, with metadata and a sticky table of contents

Spacing

#

Components use these steps rather than one-off values.

TokenDefaultRole
--dl-space-10.25remHairline gaps: list items, label offsets
--dl-space-20.5remTight gaps: metadata, captions, small controls
--dl-space-30.75remControl padding and compact rows
--dl-space-41remDefault gap and block padding
--dl-space-51.5remList entries and section padding
--dl-space-62remSeparation between blocks
--dl-space-73remSeparation between page regions
--dl-space-84remLarge page padding
--dl-space-96remSection separation on wide screens

Surfaces and shape

#
TokenDefaultRole
--dl-radius0Corner radius of content blocks; square by default
--dl-radius-control0.25remCorner radius of form controls and buttons

Color

#

Dark mode is a separate palette for reading on a dark ground, not an inversion: a warm charcoal page rather than black or navy, warm off-white text, a lighter and less saturated accent, strong rules softened to grey so tables and lists do not glare, and its own code surface and syntax colors. Figures keep a light backdrop. Both the automatic and the explicit scheme use it, and the browser interface color (theme-color) follows --dl-bg in each. Tokens without a dark value keep their light value; role tokens such as --dl-link follow the color they reference.

Surfaces and text

#
TokenLightDarkRole
--dl-bg#fbfaf7#171614Page background
--dl-surface#ffffff#201f1cRaised surfaces: inputs, tables, the table of contents
--dl-figure-bg#ffffff#f3f1ecBackdrop behind figure images; light in both schemes for transparent plots
--dl-text#1c1b18#e9e5dcBody text
--dl-text-soft#5c5850#a9a397Metadata, captions, and secondary text
--dl-border#dedad1#35332eHairline rules and borders
--dl-rule#1c1b18#8f897dStrong rules: tables, list openings, archive years, pagination, and the search field; keep at 3:1 or more against the background
--dl-control-border#857f74#857f72Form-control boundaries; keep at 3:1 or more against the background
--dl-accent-bg#f1eee7#26241fSubtle background changes, such as table headers
--dl-header-bgvar(--dl-bg)sameHeader background
--dl-selection-bg#d3e0f1#2e4566Selected text

Roles

#
TokenLightDarkRole
--dl-primary#1f4e8c#9fbde6Accent color
--dl-primary-strong#163a68#c3d6f1Stronger accent for hover and pressed states
--dl-secondary#8c3a26#e3a690Muted second color
--dl-linkvar(--dl-primary)sameLinks
--dl-link-hovervar(--dl-primary-strong)sameHovered links
--dl-annotationvar(--dl-secondary)sameAnnotations: kickers, footnote markers, and highlighted code lines
--dl-focus#1f4e8c#9fbde6Focus indicators
--dl-mark-bg#f2e3b3#3d3418Technical emphasis: highlighted text marked with mark
--dl-inline-code-bg#ece8df#2b2925Inline code

Callouts and statements

#

Callouts keep a restrained tint and a rule in their semantic color. Mathematical statements have no tint: a thin rule in the colors below and a small label identify them.

TokenLightDarkRole
--dl-callout-bg#f1f4f8#1d2129Note callout background
--dl-tip-bg#f1f6f1#1b231dTip callout background
--dl-warning-bg#fbf6e9#26221aWarning callout background
--dl-important-bg#fbf0ed#281d1aImportant callout background
--dl-tip-rule#3b7650#7fb491Tip callout rule
--dl-warning-rule#94660f#d2a75aWarning callout rule
--dl-important-rule#a33d2c#e0907fImportant callout rule
--dl-definition-rule#2c6b67#7cbbb5Definition rule
--dl-remark-rule#7a756a#a9a397Remark rule
--dl-example-rule#6a4a86#b89fd0Example rule

Code

#

Code sits on a quiet tint of the page between hairlines, with a restrained syntax palette in each scheme.

TokenLightDarkRole
--dl-code-bg#f3f0e8#1f1e1bCode block background
--dl-code-text#1c1b18#ebe8e1Code text
--dl-code-border#dedad1#35332eHairlines above and below code, and the line-number rule
--dl-code-muted#625e55#a39d90Line numbers and language labels
--dl-code-highlight#e9e3d3#2e2c27Highlighted lines
--dl-code-comment#625e55#a39d90Comments
--dl-code-keyword#6b2f7a#cdb0eaKeywords
--dl-code-string#2d6a3e#a5d4a5Strings
--dl-code-function#8a4a0c#e8bc84Function, class, and attribute names
--dl-code-number#a23a28#f0a491Numbers
--dl-skip-bg#1c1b18#e9e5dcSkip-link background
--dl-skip-text#fbfaf7#171614Skip-link text