Skip to content

Layout and typography

The layout classes are small, content-agnostic primitives. They set display, gap and alignment and nothing else, so they compose with every component. Tunable values are public custom properties that you can set on an element or in your own CSS.

A centered column with a maximum width and inline padding that grows with the viewport (1rem, 1.5rem, 2rem). It always fills the available width up to its maximum.

sb-container-sm (40rem)
sb-container-md (48rem)
sb-container-lg (64rem)
sb-container (72rem, responsive padding)
sb-container-prose (65ch)
sb-container-fluid sb-container-flush
sb-container-start
<div class="sb-stack sb-stack-2">
<div class="sb-container sb-container-sm"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-container-sm (40rem)</div></div>
<div class="sb-container sb-container-md"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-container-md (48rem)</div></div>
<div class="sb-container sb-container-lg"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-container-lg (64rem)</div></div>
<div class="sb-container"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-container (72rem, responsive padding)</div></div>
<div class="sb-container sb-container-prose"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-container-prose (65ch)</div></div>
<div class="sb-container sb-container-fluid sb-container-flush"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-container-fluid sb-container-flush</div></div>
<div class="sb-container sb-container-sm sb-container-start"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-container-start</div></div>
</div>
Class / property Effect
sb-container Maximum 72rem, responsive inline padding.
sb-container-sm, -md, -lg, -xl Maximum 40, 48, 64 and 80rem.
sb-container-prose Maximum 65ch, the reading measure.
sb-container-fluid No maximum; keeps the padding.
sb-container-flush No inline padding, for nested containers and HUD edges.
sb-container-start Aligns the column to the start instead of centering it.
--sb-container-max Overrides the maximum width of one instance.
--sb-container-pad Overrides the inline padding of one instance.

sb-stack is a vertical flex column with a consistent gap. It also resets the vertical margin of its direct children, so spacing comes from the gap alone.

one
two
three
top
pushed to the end (sb-stack-split)
centered custom gap through --sb-stack-gap
<div class="sb-stack sb-stack-1">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">one</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">two</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">three</div>
</div>
<div class="sb-stack sb-stack-split" style="min-height: 9rem">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">top</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">pushed to the end (sb-stack-split)</div>
</div>
<div class="sb-stack sb-stack-center" style="--sb-stack-gap: var(--sb-space-2)">
<span class="sb-badge">centered</span>
<span class="sb-badge sb-badge-outline">custom gap through --sb-stack-gap</span>
</div>
Class / property Effect
sb-stack Column; gap --sb-stack-gap (default --sb-space-4).
sb-stack-0, -1, -2, -3, -4, -6, -8, -12 Gap presets: 0 and the matching --sb-space-* token.
sb-stack-split Pushes the last child to the end of the column; give the stack a height.
sb-stack-start, sb-stack-center, sb-stack-end Cross-axis alignment of the children.
--sb-stack-gap Custom gap for one instance.
sb-spacer Flexible empty element that takes the free space in a flex row or column (used in the cluster demo below).

sb-cluster is a wrapping flex row, for badges, buttons and tags. It wraps by default and centers its items on the cross axis.

clusterwrapsby default
startend
centeredgap 3
endgap 1
leftpushed right by sb-spacer
<div class="sb-stack sb-stack-3">
<div class="sb-cluster"><span class="sb-badge">cluster</span><span class="sb-badge">wraps</span><span class="sb-badge">by default</span></div>
<div class="sb-cluster sb-cluster-between"><span class="sb-badge">start</span><span class="sb-badge">end</span></div>
<div class="sb-cluster sb-cluster-center sb-cluster-3"><span class="sb-badge sb-badge-outline">centered</span><span class="sb-badge sb-badge-outline">gap 3</span></div>
<div class="sb-cluster sb-cluster-end sb-cluster-1"><span class="sb-badge sb-badge-outline">end</span><span class="sb-badge sb-badge-outline">gap 1</span></div>
<div class="sb-cluster sb-cluster-nowrap"><span class="sb-badge sb-badge-soft sb-badge-info">left</span><span class="sb-spacer"></span><span class="sb-badge sb-badge-soft sb-badge-info">pushed right by sb-spacer</span></div>
</div>
Class / property Effect
sb-cluster Wrapping row; gap --sb-cluster-gap (default --sb-space-2).
sb-cluster-1, -3, -4, -6 Gap presets.
sb-cluster-between, -center, -end Main-axis distribution.
sb-cluster-start Aligns items to the top of the row.
sb-cluster-baseline Aligns items on their text baseline.
sb-cluster-nowrap Never wraps; use with sb-spacer.
--sb-cluster-gap Custom gap for one instance.

sb-grid is a responsive grid. By default it fits as many columns as it can, each at least --sb-grid-min (16rem) wide, and collapses to one column when there is no room, so it needs no breakpoints.

auto
fit
16rem min
fill
10rem min
sb-grid-sm
span-2
1
span-full
2 columns
dense, custom gap
<div class="sb-stack">
<div class="sb-grid">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">auto</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">fit</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">16rem min</div>
</div>
<div class="sb-grid sb-grid-sm sb-grid-fill">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">fill</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">10rem min</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-grid-sm</div>
</div>
<div class="sb-grid sb-grid-3">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body sb-grid-span-2">span-2</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">1</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body sb-grid-span-full">span-full</div>
</div>
<div class="sb-grid sb-grid-2 sb-grid-dense" style="--sb-grid-gap: var(--sb-space-2)">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">2 columns</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">dense, custom gap</div>
</div>
</div>
Class / property Effect
sb-grid Auto-fit columns of at least --sb-grid-min; gap --sb-grid-gap (default --sb-space-4).
sb-grid-fill Auto-fill instead of auto-fit, keeping empty columns.
sb-grid-sm, sb-grid-lg Minimum column width 10rem and 22rem.
sb-grid-2, -3, -4 Fixed column counts; they collapse to one column below 40rem.
sb-grid-dense Dense auto-flow.
sb-grid-span-2 Item spans two columns (one column below 40rem).
sb-grid-span-full Item spans every column.
--sb-grid-min, --sb-grid-gap Minimum column width and gap for one instance.

sb-center centers a block with a maximum measure.

sb-center, 24rem, text centered
intrinsic
xy
<div class="sb-stack sb-stack-3">
<div class="sb-center sb-center-text" style="--sb-center-max: 24rem"><div class="sb-card sb-card-flat sb-card-sm sb-card-body">sb-center, 24rem, text centered</div></div>
<div class="sb-center sb-center-intrinsic"><span class="sb-badge sb-badge-primary">intrinsic</span></div>
<div class="sb-center sb-center-xy" style="--sb-center-min-height: 5rem"><span class="sb-badge sb-badge-outline">xy</span></div>
</div>
Class / property Effect
sb-center Centered block with maximum width --sb-center-max (default 65ch) and inline padding --sb-center-pad (default 0).
sb-center-text Centers the text too.
sb-center-intrinsic Centers children by their own width.
sb-center-xy Centers its content both ways; minimum height --sb-center-min-height.

sb-sidebar puts a fixed-width side element beside a fluid main element and wraps them into one column when the main would drop below half the width. The first child is the side, and the last is the main.

side
main
main
side (sb-sidebar-end)
<div class="sb-stack sb-stack-3">
<div class="sb-sidebar" style="--sb-sidebar-width: 10rem">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">side</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">main</div>
</div>
<div class="sb-sidebar sb-sidebar-end" style="--sb-sidebar-width: 10rem">
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">main</div>
<div class="sb-card sb-card-flat sb-card-sm sb-card-body">side (sb-sidebar-end)</div>
</div>
</div>
Class / property Effect
sb-sidebar Side first, main last.
sb-sidebar-end Main first, side last.
--sb-sidebar-width Side width (default 16rem).
--sb-sidebar-gap Gap (default --sb-space-6).
--sb-sidebar-main-min Minimum main width before wrapping (default 50%).

The roles mirror the element defaults, so any tag can carry a role: <p class="sb-h2"> looks like an h2 without changing the document outline. Use the real heading element when the text is a heading.

sb-eyebrow

sb-display-lg

sb-display-md

sb-display-sm

sb-h1 heading

sb-h2 heading

sb-h3 heading

sb-h4 heading

sb-h5 heading

sb-h6 heading

sb-lead introduces an article in a larger, muted face.

sb-mono: 0123456789 tabular figures

sb-text-muted

sb-text-subtle

<div class="sb-stack">
<p class="sb-eyebrow">sb-eyebrow</p>
<p class="sb-display-lg sb-gradient-text">sb-display-lg</p>
<p class="sb-display-md">sb-display-md</p>
<p class="sb-display-sm">sb-display-sm</p>
<p class="sb-h1">sb-h1 heading</p>
<p class="sb-h2">sb-h2 heading</p>
<p class="sb-h3">sb-h3 heading</p>
<p class="sb-h4">sb-h4 heading</p>
<p class="sb-h5">sb-h5 heading</p>
<p class="sb-h6">sb-h6 heading</p>
<p class="sb-lead">sb-lead introduces an article in a larger, muted face.</p>
<p class="sb-mono">sb-mono: 0123456789 tabular figures</p>
<p class="sb-text-muted">sb-text-muted</p>
<p class="sb-text-subtle">sb-text-subtle</p>
</div>
Class Effect
sb-display-sm, -md, -lg Display face, bold, tight tracking, at the 5xl, 6xl and 7xl token sizes.
sb-h1 to sb-h4 Display face, balanced wrapping, at 2.5, 2, 1.5 and 1.25rem.
sb-h5 Body face, semibold, 1.125rem.
sb-h6, sb-eyebrow Small uppercase mono label with wide tracking, in the subtle ink.
sb-lead Large, muted introductory paragraph.
sb-mono Mono face with tabular figures.
sb-text-muted, sb-text-subtle Secondary and tertiary text ink.

sb-prose styles unclassed rich text: the output of Markdown, a CMS or hand-written HTML. Every rule uses :where(), so they carry no specificity: a utility or component class on an element inside the prose always wins. The measure is 65ch.

A lead paragraph introduces the article. Everything below is plain HTML inside .sb-prose.

Body copy runs at a 65ch measure with relaxed leading. It carries strong, emphasis, a link, inline code, Ctrl + K, a highlight, deleted and inserted text, CEF, H2O and E = mc2.

Third level

Headings use the display face; h1 and h2 are larger, and h2 gets a hairline beneath it.

Fourth level

Fifth level in the body face
Sixth level eyebrow
  • Unordered items get a glowing primary dot
  • Nested lists
    • use a hollow dot
    • and tighter spacing
  1. Ordered markers are mono digits in the primary ink
  2. Second step
  • Task list item, done
  • Task list item, open
Flavor
One of dusk, midnight, blackout or daybreak.

The city never sleeps, it just dims the neon a little.

A fixer in Watson
resource "static-bloom-demo"
version  "1.0.0"
web_ui_page "dist/index.html"
Button heights by size
SizeHeight
xs1.75rem
sm2rem
md2.5rem
lg3rem
Collapsed details

Details use a panel fill with a hairline.

Alerts flow inside prose

Block spacing matches paragraphs.

<article class="sb-prose">
<p class="sb-lead">A lead paragraph introduces the article. Everything below is plain HTML inside <code>.sb-prose</code>.</p>
<p>Body copy runs at a 65ch measure with relaxed leading. It carries <strong>strong</strong>, <em>emphasis</em>, <a href="#sb-prose">a link</a>, <code>inline code</code>, <kbd>Ctrl</kbd> + <kbd>K</kbd>, <mark>a highlight</mark>, <del>deleted</del> and <ins>inserted</ins> text, <abbr title="Chromium Embedded Framework">CEF</abbr>, H<sub>2</sub>O and E = mc<sup>2</sup>.</p>
<h3>Third level</h3>
<p>Headings use the display face; h1 and h2 are larger, and h2 gets a hairline beneath it.</p>
<h4>Fourth level</h4>
<h5>Fifth level in the body face</h5>
<h6>Sixth level eyebrow</h6>
<ul>
<li>Unordered items get a glowing primary dot</li>
<li>Nested lists
<ul><li>use a hollow dot</li><li>and tighter spacing</li></ul>
</li>
</ul>
<ol>
<li>Ordered markers are mono digits in the primary ink</li>
<li>Second step</li>
</ol>
<ul>
<li><input type="checkbox" class="sb-checkbox sb-checkbox-sm" checked aria-label="Done" /> Task list item, done</li>
<li><input type="checkbox" class="sb-checkbox sb-checkbox-sm" aria-label="To do" /> Task list item, open</li>
</ul>
<dl>
<dt>Flavor</dt>
<dd>One of dusk, midnight, blackout or daybreak.</dd>
</dl>
<blockquote>
<p>The city never sleeps, it just dims the neon a little.</p>
<cite>A fixer in Watson</cite>
</blockquote>
<pre><code>resource "static-bloom-demo"
version "1.0.0"
web_ui_page "dist/index.html"</code></pre>
<div class="sb-prose-scroll">
<table>
<caption>Button heights by size</caption>
<thead><tr><th>Size</th><th>Height</th></tr></thead>
<tbody>
<tr><th>xs</th><td>1.75rem</td></tr>
<tr><th>sm</th><td>2rem</td></tr>
<tr><th>md</th><td>2.5rem</td></tr>
<tr><th>lg</th><td>3rem</td></tr>
</tbody>
</table>
</div>
<details>
<summary>Collapsed details</summary>
<p>Details use a panel fill with a hairline.</p>
</details>
<div class="sb-alert sb-alert-info"><div class="sb-alert-content"><p class="sb-alert-title">Alerts flow inside prose</p><p class="sb-alert-description">Block spacing matches paragraphs.</p></div></div>
</article>

sb-prose-sm

Smaller body for sidebars and footnotes.

sb-prose-lg

Larger body for long reads.

<div class="sb-prose sb-prose-sm"><h3>sb-prose-sm</h3><p>Smaller body for sidebars and footnotes.</p></div>
<div class="sb-prose sb-prose-lg"><h3>sb-prose-lg</h3><p>Larger body for long reads.</p></div>
Class / element Effect
sb-prose Container: 65ch measure, relaxed leading, styles for headings, lists, links, code, blockquotes, tables, figures, images, details and more.
sb-prose-sm, sb-prose-lg Smaller and larger base type.
sb-prose-wide Lifts the measure.
sb-prose-scroll Put around a <table> so it scrolls sideways instead of widening the page.
.sb-lead inside prose Scales to 1.2em of the prose size.
.sb-alert, .sb-card inside prose Get the same block spacing as paragraphs.
h1 to h6 Display face; h2 has a hairline underneath, h6 is the mono eyebrow.
Task lists A ul whose items start with a checkbox (.sb-checkbox) loses its bullets.

The effect utilities live in @layer utilities, so they win over component styles. They are decorative: the content must read correctly without them, and the animated ones stop under prefers-reduced-motion.

sb-glow, sb-glow-sm and sb-glow-lg add a bloom as a box-shadow in the current glow color, which is the primary accent unless you change it. The bloom is dimmed on Daybreak. sb-glow-<name> sets --sb-glow-color for the element and its children.

sb-glow-sm
sb-glow
sb-glow-lg
sb-glow sb-glow-ion
sb-glow sb-glow-danger
sb-glow sb-glow-acid

sb-text-glow

sb-gradient-text

sb-gradient-text + sb-text-glow

<div class="sb-grid sb-grid-sm" style="padding: var(--sb-space-2)">
<div class="sb-card sb-card-body sb-glow-sm">sb-glow-sm</div>
<div class="sb-card sb-card-body sb-glow">sb-glow</div>
<div class="sb-card sb-card-body sb-glow-lg">sb-glow-lg</div>
<div class="sb-card sb-card-body sb-glow sb-glow-ion">sb-glow sb-glow-ion</div>
<div class="sb-card sb-card-body sb-glow sb-glow-danger">sb-glow sb-glow-danger</div>
<div class="sb-card sb-card-body sb-glow sb-glow-acid">sb-glow sb-glow-acid</div>
</div>
<p class="sb-h3 sb-text-glow">sb-text-glow</p>
<p class="sb-h3 sb-gradient-text">sb-gradient-text</p>
<p class="sb-h3 sb-gradient-text sb-text-glow">sb-gradient-text + sb-text-glow</p>
Class Effect
sb-glow, sb-glow-sm, sb-glow-lg Bloom around the box: medium, small and large.
sb-text-glow Bloom on text (text-shadow).
sb-glow-plasma, -laser, -ember, -sodium, -halogen, -acid, -coolant, -frost, -ion, -ultraviolet, -orchid, -chrome Glow color: one class per palette accent.
sb-glow-primary, -secondary, -info, -success, -warning, -danger Glow color: one class per intent.
sb-gradient-text Plasma-to-ultraviolet gradient clipped to the glyphs. The element shrinks to its text width. Combine with sb-text-glow for a drop-shadow bloom.

These three each take a different part of the element, so they can be combined: brackets use ::before, static uses ::after, and scanlines paint into background-image. sb-brackets and sb-static make the element position: relative (sb-static also isolates it).

sb-brackets
custom color, size and width
sb-scanlines
sb-static
all three combined
<div class="sb-grid sb-grid-sm" style="padding: var(--sb-space-2)">
<div class="sb-card sb-card-body sb-brackets">sb-brackets</div>
<div class="sb-card sb-card-body sb-brackets" style="--sb-brackets-color: var(--sb-ion); --sb-brackets-size: 20px; --sb-brackets-width: 2px">custom color, size and width</div>
<div class="sb-card sb-card-body sb-scanlines">sb-scanlines</div>
<div class="sb-card sb-card-body sb-static">sb-static</div>
<div class="sb-card sb-card-body sb-static sb-brackets sb-scanlines">all three combined</div>
</div>
Class / property Effect
sb-brackets Four L-shaped HUD corner ticks with a bloom, drawn inside the box.
--sb-brackets-color Tick color (default primary).
--sb-brackets-size Tick length (default 12px).
--sb-brackets-width Tick thickness (default 1.5px).
--sb-brackets-inset Offset from the box edge (default -1px).
sb-scanlines Horizontal scanline texture, 3px pitch.
sb-static Film-grain noise overlay in overlay blend mode, with pointer-events: none.
--sb-static-opacity Grain strength (default 0.05 on light flavors, 0.09 on dark ones).

sb-glass is a tinted panel with a backdrop blur and saturation boost, for text over game imagery. It needs something behind it to blur.

sb-glass

A blurred, tinted panel for text over game imagery.

<div class="sb-glass" style="padding: var(--sb-space-4); border-radius: var(--sb-radius-lg)">
<p class="sb-h5">sb-glass</p>
<p>A blurred, tinted panel for text over game imagery.</p>
</div>
sb-pulse-glow sb-flicker Visually hidden text follows: you can only hear this
<div class="sb-cluster">
<span class="sb-badge sb-badge-solid sb-pulse-glow">sb-pulse-glow</span>
<span class="sb-badge sb-badge-solid sb-badge-danger sb-flicker">sb-flicker</span>
<span class="sb-badge sb-badge-outline">Visually hidden text follows:<span class="sb-sr-only"> you can only hear this</span></span>
</div>
Class Effect
sb-pulse-glow Slow pulsing bloom (2.4s, infinite).
sb-flicker Stepped flicker (6s, infinite). Keep it off anything people must read.
sb-sr-only Hides content visually but keeps it available to screen readers.