Typography

Summary

Soma uses the system font stack (zero network weight, native rendering on every platform) with a monospace stack for code, logs and diffs. Type is styled at the element level: headings, paragraphs, lists, quotes and code need no classes inside content areas.

Type scale

TokenSizeUsed for
--soma-font-size-display30pxStat-tile values, the shell page title (.soma-page-title)
--soma-font-size-xxl24pxh1
--soma-font-size-xl20pxh2, the navbar brand, dialog titles
--soma-font-size-lg16pxh3, widget/drawer/toolbar titles
--soma-font-size-md14pxBody, controls, menus (the base size)
--soma-font-size-sm13pxDense UI: table cells, sidebar, <small>
--soma-font-size-xs12pxMicro-text: timestamps, hints, badges, h5/h6 labels

Density modes never change the scale (only vertical padding), so compact screens stay as readable as comfortable ones.

Examples

Headings

Heading 1 — 24px

Heading 2 — 20px

Heading 3 — 16px

Heading 4 — 14px

Heading 5 — 12px uppercase label

Body text and lists

Paragraphs get a comfortable line height and rhythm spacing. Links use the primary colour; strong and emphasis behave as expected. Abbreviations with a title, such as WCAG, get a dotted underline and a help cursor.

  • Unordered item
  • Another, with a link
  1. Ordered item
  2. Second step

Quotes

Cortex thinks, Axon acts — Soma is what you see.

Nware naming lore

Code and keys

Inline code spans and Ctrl+K keys sit in body text. Both code forms render on --soma-surface-inset, a surface deliberately darker than widgets so code stays visible on any Soma surface, with no classes needed: pre becomes a bordered panel, inline spans get a bordered chip (the edge keeps the chip legible even on an opaque white card, where the fill alone would wash out).

// Block code uses the mono stack on the inset surface
Soma.toast({ title: 'Deployed', appearance: 'success' });

Small print

<small> renders at the sm size (13px) in the muted colour; badges, timestamps and other micro-text use xs (12px). Two colour tiers matter here: --soma-color-text-muted for informational micro-text (timestamps and gutters, which must stay readable), and --soma-color-text-subtle for decorative text only. The axe sweep enforces this split.

Vertical rhythm

Spacing flows downward only: block elements push away from whatever precedes them with a top margin, and nothing carries a bottom margin. That makes spacing predictable (the gap above an element depends only on that element, never on what came before), and containers never end with stray trailing space, because every :first-child block sits flush (margin-top: 0).

  • Flowing blocks (p, ul, ol, dl, blockquote, pre, table.soma-table, .soma-tabs, .soma-widget, .soma-list-group) get margin: var(--soma-space-3) 0 0 (12px above, nothing below).
  • Headings push down harder, scaled to their level: h1/h2 get --soma-space-6 (32px) above, h3 gets --soma-space-5 (24px), h4h6 get --soma-space-4 (16px).
  • Directly stacked headings (h1 + h2, h2 + h3, …) tighten to --soma-space-2 (8px), so a title and its subtitle read as one unit.

If you add your own block components to content areas, follow the same contract: top margin from a --soma-space-* token, no bottom margin, flush when first.

Changing the font

The whole library reads its faces from two tokens, so swapping the font is a two-line override after soma.css, no rebuild needed:

:root {
  --soma-font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
  --soma-font-family-mono: 'JetBrains Mono', ui-monospace, monospace; /* optional */
}

Keep the system faces in the fallback chain, and remember the trade you're making: a webfont costs network weight and a flash of fallback text that the default system stack avoids. Sizes are unaffected; the scale tokens are separate.

HTML

<h1>Page title</h1>
<p>Body text with a <a href="…">link</a> and <code>code</code>.</p>
<blockquote><p>Quote</p><cite>Source</cite></blockquote>
<pre><code>block code</code></pre>

No classes needed: the element styles live in _typography.scss. The mono stack is exposed as --soma-font-family-mono for custom components (the log viewer and diff consume it).