Skip to content

Beam

Compositions

Layout primitives in beam.css. They own flow, gaps and columns — never colour or type — and every gap reads a density token, so switching density re-flows them all.

Build in CUBE order: composition first (the layout), then utilities for one-off tweaks, then a block only when a component needs its own styles. Variations go through data-* attributes, not new classes. Values in parentheses below are the defaults.

.b-flow / .b-stack

Vertical rhythm between siblings. The gap is a stack-* density token.

data-space
xs · sm · (md) · lg · xl · 2xl
data-split-after
on a .b-stack child: push the rest to the end
Heading
Paragraph
Actions
HTML
<div class="[ b-flow ]" data-space="sm">
  <div class="[ b-box ]" data-tone="neutral">Heading</div>
  <div class="[ b-box ]" data-tone="neutral">Paragraph</div>
  <div class="[ b-box ]" data-tone="neutral">Actions</div>
</div>

.b-cluster

Inline items that wrap: tags, toolbars, button rows.

data-gap
xs · sm · (md) · lg
data-justify
end · center · between
data-align
start · stretch
Tag 1
Tag 2
Tag 3
Tag 4
Tag 5
Tag 6
HTML
<div class="[ b-cluster ]" data-gap="sm">
  <div class="[ b-box ]" data-tone="neutral">Tag 1</div>
  <div class="[ b-box ]" data-tone="neutral">Tag 2</div>
  <div class="[ b-box ]" data-tone="neutral">Tag 3</div>
  <div class="[ b-box ]" data-tone="neutral">Tag 4</div>
  <div class="[ b-box ]" data-tone="neutral">Tag 5</div>
  <div class="[ b-box ]" data-tone="neutral">Tag 6</div>
</div>

.b-repel

Two groups pushed to opposite ends; wraps gracefully when narrow.

--repel-gap
custom property; default inline-md
Title
Cancel
Save
HTML
<div class="[ b-repel ]">
  <div class="[ b-box ]">Title</div>
  <div class="[ b-cluster ]" data-gap="sm">
    <div class="[ b-box ]" data-tone="neutral">Cancel</div>
    <div class="[ b-box ]">Save</div>
  </div>
</div>

A fixed-ish aside next to a fluid main; stacks when main would drop below half the width. No media query.

data-side
right
--sidebar-width
default 20rem
--sidebar-content-min
default 50%
Aside
Main content
HTML
<div class="[ b-sidebar ]">
  <div class="[ b-box ]" data-tone="neutral">Aside</div>
  <div class="[ b-box ]">Main content</div>
</div>

.b-switcher

Side by side above the density threshold, stacked below it. Rows never exceed the limit.

data-limit
2 · 3 · (4)
threshold
--beam-threshold (density)
One
Two
Three
HTML
<div class="[ b-switcher ]" data-limit="3">
  <div class="[ b-box ]">One</div>
  <div class="[ b-box ]">Two</div>
  <div class="[ b-box ]">Three</div>
</div>

.b-grid

Intrinsic auto-fit grid for cards and tiles. Columns appear as space allows.

data-min
xs 10rem · sm 13rem · (16rem) · lg 20rem · xl 26rem
data-gap
sm · (md) · lg
Card 1
Card 2
Card 3
Card 4
Card 5
HTML
<div class="[ b-grid ]" data-min="sm">
  <div class="[ b-box ]">Card 1</div>
  <div class="[ b-box ]">Card 2</div>
  <div class="[ b-box ]">Card 3</div>
  <div class="[ b-box ]">Card 4</div>
  <div class="[ b-box ]">Card 5</div>
</div>

.b-layout-grid

12-column page grid. Mobile-first: full width below sm unless data-span-sm; data-span from md; data-span-lg from lg.

data-span · data-span-sm · data-span-lg
1–12
data-start
column start
data-cols
4 · 6 · 8 · (12) · 16
.b-subgrid
child that aligns to the parent tracks
data-gap
sm · (md) · lg
12
8 (lg: 9)
4 (lg: 3)
3 (sm: 6)
3 (sm: 6)
3 (sm: 6)
3 (sm: 6)
sub 2
sub 10
HTML
<div class="[ b-layout-grid ]">
  <div class="[ b-box ]" data-span="12">12</div>
  <div class="[ b-box ]" data-span="8" data-span-lg="9">8 (lg: 9)</div>
  <div class="[ b-box ]" data-span="4" data-span-lg="3">4 (lg: 3)</div>
  <div class="[ b-box ]" data-span="3" data-span-sm="6">3 (sm: 6)</div>
  <div class="[ b-box ]" data-span="3" data-span-sm="6">3 (sm: 6)</div>
  <div class="[ b-box ]" data-span="3" data-span-sm="6">3 (sm: 6)</div>
  <div class="[ b-box ]" data-span="3" data-span-sm="6">3 (sm: 6)</div>
  <div class="[ b-subgrid ]" data-span="12">
    <div class="[ b-box ]" data-tone="neutral" data-span="2">sub 2</div>
    <div class="[ b-box ]" data-tone="neutral" data-span="10">sub 10</div>
  </div>
</div>

.b-app-shell

Header / nav / main / aside / footer by named areas. Nav appears at md, aside at lg (with data-aside).

data-area
header · nav · main · aside · footer
data-aside
show the aside column at lg
--nav-width / --aside-width
default 16rem / 20rem
header
nav
main
aside
footer
HTML
<div class="[ b-app-shell ] [ b-demo-shell ]" data-aside>
  <div data-area="header">header</div>
  <div data-area="nav">nav</div>
  <div data-area="main">main</div>
  <div data-area="aside">aside</div>
  <div data-area="footer">footer</div>
</div>

.b-cover

A full-height block with one vertically centred principal child — hero sections, empty states.

data-cover="center"
the centred child
--cover-height
default 100dvh
--cover-padding
default inset-lg
Top
Centred
Bottom
HTML
<div class="[ b-cover ] [ b-box ]" data-tone="neutral" style="--cover-height: var(--beam-width-3xs)">
  <div class="[ b-box ]">Top</div>
  <div class="[ b-box ]" data-cover="center">Centred</div>
  <div class="[ b-box ]">Bottom</div>
</div>

.b-center / .b-wrapper / .b-region

.b-wrapper sets page width and side padding; .b-region sets section padding; .b-center caps line length.

.b-wrapper data-max
sm · md · (container) · xl · full
.b-region data-space
xs · sm · (md) · lg · xl
.b-center data-text
center
Wrapper (sm) + centred measure
HTML
<section class="[ b-region ] [ b-box ]" data-tone="neutral" data-space="xs">
  <div class="[ b-wrapper ]" data-max="sm">
    <div class="[ b-center ] [ b-box ]" data-text="center">Wrapper (sm) + centred measure</div>
  </div>
</section>

.b-reel / .b-frame

.b-reel is a horizontal scroller with snap; .b-frame is an aspect-ratio box for media.

--reel-item
item width, default 18rem
.b-frame data-ratio
square · 4-3 · (16:9) · 21-9
1
2
3
4
5
6
HTML
<div class="[ b-reel ]" style="--reel-item: var(--beam-width-3xs)">
  <div class="[ b-frame ] [ b-box ]" data-ratio="4-3">1</div>
  <div class="[ b-frame ] [ b-box ]" data-ratio="4-3">2</div>
  <div class="[ b-frame ] [ b-box ]" data-ratio="4-3">3</div>
  <div class="[ b-frame ] [ b-box ]" data-ratio="4-3">4</div>
  <div class="[ b-frame ] [ b-box ]" data-ratio="4-3">5</div>
  <div class="[ b-frame ] [ b-box ]" data-ratio="4-3">6</div>
</div>