Design
system
~ Overview Color system Foundation-tokens-reference Semantic tokens reference

Overview

The design system consists of design tokens expressed as css custom properties. The design tokens are then organized into two main layers, foundation and semantic.


Foundation tokens

Foundation tokens are the smallest building blocks. They are primitive values and their describe what they are. For example —radius-1 is the a value that should be used to specify, well how rounded the corners of an element should be.

They serve an important purpose, they constrain the possible values from anything to a subset of pre-defined ones. This both speeds up the decision process and improves consistency through the ui.

The foundational tokens in this design system are an adaptation of the fantastic open props


Semantic tokens

The semantic tokens is an abstraction on top of the foundation tokens that should encode a pattern that should be applied across multiple elements like —color-text.

Themes

A good rule of thumb is that themes should only change semantic layer tokens. This also gives a good indication on whether a token is foundational or semantic.

By default there are two themes setup; light and dark. These mainly changes the colors from light to dark. But there could be more themes that changes other custom properties in the semantic layer like input radius or spacing. These could even complement each other. For example having theme “light” and “spacious” applied at the same time (if a “spacious” theme was created).

For more info about the color setup in the themes see the Color system


Next

Next: Color system

Color system

As mentioned the semantic layer deals quite a bit with colors.

To make it easier to use accessible colors there is a color system in place that helps with generating pallets.

From 4 seed colors: neutral, primary, destructive and constructive 4 swatches are generated with the same names.

primary
Softer Soft Mid Loud Louder
Fill
Text
Stroke
neutral
Softer Soft Mid Loud Louder
Fill
Text
Stroke
destructive
Softer Soft Mid Loud Louder
Fill
Text
Stroke
constructive
Softer Soft Mid Loud Louder
Fill
Text
Stroke

When picking seed colors use a neutral color any color in the 500-range on https://color.surf/ should be fine.

How it works

The system starts with four seed colors that define the base hue for each color family:

1. Seed colors

2. Color scale generation

Each seed color is automatically expanded into an 11-step scale (50-950) using color-mix() in oklab color space:

3. Swatch mapping

The scale values are then mapped to semantic tokens that describe their purpose. These mappings flip between light and dark themes to maintain proper contrast.


Next

Next: Foundation tokens reference

Foundation-tokens-reference

Below is a list of all foundation tokens.


Radius

—radius-1 2px

—radius-2

5px

—radius-3

1rem

—radius-4

4rem

—radius-5

8rem


Size

-.5rem —size-000

-.25rem —size-00

.25rem —size-1

.5rem —size-2

1rem —size-3

1.25rem —size-4

1.5rem —size-5

1.75rem —size-6

2rem —size-7

3rem —size-8

4rem —size-9

5rem —size-10

7.5rem —size-11

10rem —size-12

15rem —size-13

20rem —size-14

30rem —size-15

Content Size

20ch —size-content-1

45ch —size-content-2

60ch —size-content-3

Fluid size

.5rem > 1vw < 1rem —size-fluid-1

1rem > 2vw < 1.5rem —size-fluid-2

1.5rem > 3vw < 2rem —size-fluid-3

2rem > 4vw < 3rem —size-fluid-4

4rem > 5vw < 5rem —size-fluid-5

5rem > 7vw < 7.5rem —size-fluid-6

7.5rem > 10vw < 10rem —size-fluid-7

10rem > 10vw < 15rem —size-fluid-8

15rem > 30vw < 20rem —size-fluid-9

20rem > 40vw < 30rem —size-fluid-10


Layer

—layer-important
—layer-5
—layer-4
—layer-3
—layer-2
—layer-1

Shadows

—shadow-1
—shadow-2
—shadow-3
—shadow-4
—shadow-5
—shadow-6
—inner-shadow-0
—inner-shadow-1
—inner-shadow-2
—inner-shadow-3
—inner-shadow-4

Typography

Font Family

The quick brown fox jumps over the lazy dog

IBM Plex Mono (body/code font) —ff

The quick brown fox jumps over the lazy dog

Departure Mono (display font) —ff-display

Font Size

Aa
.5rem —font-size-00

Aa
.75rem —font-size-0

Aa
1rem —font-size-1

Aa
1.1rem —font-size-2

Aa
1.25rem —font-size-3

Aa
1.5rem —font-size-4

Aa
2rem —font-size-5

Aa
2.5rem —font-size-6

Aa
3rem —font-size-7

Aa
3.5rem —font-size-8

Font Weight

The quick brown fox

400 —font-weight-regular

The quick brown fox

500 —font-weight-medium

The quick brown fox

700 —font-weight-bold

Line Height

The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.

.95 —font-lineheight-00

The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.

1.1 —font-lineheight-0

The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.

1.25 —font-lineheight-1

The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.

1.375 —font-lineheight-2

The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.

1.5 —font-lineheight-3

The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.

1.75 —font-lineheight-4

The quick brown fox jumps over the lazy dog. The five boxing wizards jump quickly.

2 —font-lineheight-5

Letter Spacing

The quick brown fox

-.05em —font-letterspacing-0

The quick brown fox

.025em —font-letterspacing-1

The quick brown fox

.050em —font-letterspacing-2

The quick brown fox

.075em —font-letterspacing-3

The quick brown fox

.150em —font-letterspacing-4

The quick brown fox

.500em —font-letterspacing-5

The quick brown fox

.750em —font-letterspacing-6

The quick brown fox

1em —font-letterspacing-7


Next

Next: Semantic tokens reference

Semantic tokens reference

Semantic tokens come in all shapes and sizes, below is an overview of all the values.


Typography

For ui elements the typescale is limited to 4 sizes. --h1,--h2,--p and --p2. This combined with text color provides enough visual hierarcy for normal ui.

Long form text like the documentation you’re reading now might need a bigger typescale and for that usecase .typesetting exists, see #doc-css-restyle

Font Families

IBM Plex Mono

Aa

Regular

Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Xx Yy Zz Åå Ää Öö

Medium

Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Xx Yy Zz Åå Ää Öö

Bold

Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Xx Yy Zz Åå Ää Öö

Departure Mono

Aa

Regular

Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Xx Yy Zz Åå Ää Öö

Bold

Aa Bb Cc Dd Ee Ff Gg Hh Ii Jj Kk Ll Mm Nn Oo Pp Qq Rr Ss Tt Uu Vv Xx Yy Zz Åå Ää Öö

Type Scale

The type scale provides consistent sizing across all text elements:

Heading 1

—h1

2rem bold / 1.1 (Departure Mono)

Heading 2

—h2

1.5rem medium / 1.1 (IBM Plex Mono)

Body text for paragraphs and general content.

—p

1rem regular / 1.4 (IBM Plex Mono)

Small text for captions and secondary information.

—p2

0.875rem regular / 1.4 (IBM Plex Mono)


Sizing

—menu-height Simply the height of the menu. Since the menu is position absolute this is usefull when creating page layouts that needs to add padding so the top element is not positioned below the menu

—body-margin This value referes to the inset or padding of the main content. Think of it as the closest content that is not full width should be from the edge of a element.

—radius-box UIs have a lot of boxes. We have a dedicated .box class that can be used, but for other places where box styling is disired —radius-box can be used


Input elements

There are a lot of input elements. They should all have consistent styling. These custom properties are used to style both the custom elements like <m-input> as well as the native <input/> elements

—color-input-fill —color-input-stroke —color-input-text —color-input-stroke-focus —color-input-fill-focus —color-input-text-focus —color-input-fill-error —color-input-stroke-focus-error —color-input-text-focus-error —radius-input —radius-input

Borders

In adition to all the stroke variants of colors (like --color-primary-stroke), that can be used to set the border color, there are other custom propertise that should be used for consistent border styling

—border-width How thick should the border be.

—border Collects border widht, style and default-color into a variable that can be used with border: var(--border)

—border-strong Same as --border but the strong variant.


Colors

The color system adapts to light and dark themes. Each color is defined with multiple variants for different use cases.

Text Colors

  • var(--color-text)
    Default text color. Used as the main text color throughout the UI. Provides good and legible contrast for our content.
  • var(--color-text-mid)
    Mid text color. Used for introduction paragraphs and help texts that are coupled with form elements.
  • var(--color-text-softer)
    Softer text color. Used for disabled buttons, footers, table headings, captions and placeholder texts.
  • var(--color-text-link)
    Link text color. Used for all paragraph level links in a user interface.

Background Colors

  • var(--color-background)
    Default application background color. Should be set to either html or body element.
  • var(--color-surface)
    Default application surface color. Use this for card backgrounds.
  • var(--color-surface-raised)
    Raised surface color. Use this when you need to separate a specific layer from the surface color, e.g. table headers.

Stroke Colors

  • var(--color-stroke)
    Default stroke color. Used for borders and dividers.
  • var(--color-stroke-strong)
    Strong stroke color for highlighting specific parts in the user interface.
  • var(--color-stroke-hover)
    Stroke color for hover states.

Special Colors

  • var(--color-button-hover)
    Background color for button hover states.
  • var(--color-button-active)
    Background color for button active states.
  • var(--color-icon)
    Default icon color.
  • var(--color-icon-hover)
    Icon color on hover.

Color Scale Variants

The color system includes four semantic scales: primary, neutral, constructive, and destructive. Each scale has consistent variants:

Primary Colors

  • var(--color-primary-fill-softer)
    Subtlest fill. Use for backgrounds that need minimal emphasis.
  • var(--color-primary-fill-soft)
    Soft fill. Use for secondary backgrounds.
  • var(--color-primary-fill-mid)
    Mid-range fill. Use for button backgrounds and UI elements.
  • var(--color-primary-fill-loud)
    High contrast fill. Use for emphasized elements.
  • var(--color-primary-fill-louder)
    Highest contrast fill. Use for maximum emphasis.
  • var(--color-primary-text-on-soft)
    Text color to use on soft fill backgrounds.
  • var(--color-primary-text-on-mid)
    Text color to use on mid fill backgrounds.
  • var(--color-primary-text-on-loud)
    Text color to use on loud fill backgrounds.
  • var(--color-primary-text-colorful)
    Colorful text variant. Use for links and emphasized inline text.
  • var(--color-primary-stroke-softer)
    Subtlest stroke. Use for subtle borders.
  • var(--color-primary-stroke-soft)
    Soft stroke. Use for default borders.
  • var(--color-primary-stroke-mid)
    Mid-range stroke. Use for emphasized borders and focus indicators.

Neutral Colors

  • var(--color-neutral-fill-softer)
    Subtlest fill. Use for backgrounds that need minimal emphasis.
  • var(--color-neutral-fill-soft)
    Soft fill. Use for secondary backgrounds.
  • var(--color-neutral-fill-mid)
    Mid-range fill. Use for button backgrounds and UI elements.
  • var(--color-neutral-fill-loud)
    High contrast fill. Use for emphasized elements.
  • var(--color-neutral-fill-louder)
    Highest contrast fill. Use for maximum emphasis.
  • var(--color-neutral-text-on-soft)
    Text color to use on soft fill backgrounds.
  • var(--color-neutral-text-on-mid)
    Text color to use on mid fill backgrounds.
  • var(--color-neutral-text-on-loud)
    Text color to use on loud fill backgrounds.
  • var(--color-neutral-text-colorful)
    Colorful text variant. Use for links and emphasized inline text.
  • var(--color-neutral-stroke-softer)
    Subtlest stroke. Use for subtle borders.
  • var(--color-neutral-stroke-soft)
    Soft stroke. Use for default borders.
  • var(--color-neutral-stroke-mid)
    Mid-range stroke. Use for emphasized borders and focus indicators.

Constructive Colors

  • var(--color-constructive-fill-softer)
    Subtlest fill. Use for backgrounds that need minimal emphasis.
  • var(--color-constructive-fill-soft)
    Soft fill. Use for secondary backgrounds.
  • var(--color-constructive-fill-mid)
    Mid-range fill. Use for button backgrounds and UI elements.
  • var(--color-constructive-fill-loud)
    High contrast fill. Use for emphasized elements.
  • var(--color-constructive-fill-louder)
    Highest contrast fill. Use for maximum emphasis.
  • var(--color-constructive-text-on-soft)
    Text color to use on soft fill backgrounds.
  • var(--color-constructive-text-on-mid)
    Text color to use on mid fill backgrounds.
  • var(--color-constructive-text-on-loud)
    Text color to use on loud fill backgrounds.
  • var(--color-constructive-text-colorful)
    Colorful text variant. Use for success messages and positive feedback.
  • var(--color-constructive-stroke-softer)
    Subtlest stroke. Use for subtle borders.
  • var(--color-constructive-stroke-soft)
    Soft stroke. Use for default borders.
  • var(--color-constructive-stroke-mid)
    Mid-range stroke. Use for emphasized borders.

Destructive Colors

  • var(--color-destructive-fill-softer)
    Subtlest fill. Use for backgrounds that need minimal emphasis.
  • var(--color-destructive-fill-soft)
    Soft fill. Use for secondary backgrounds.
  • var(--color-destructive-fill-mid)
    Mid-range fill. Use for button backgrounds and UI elements.
  • var(--color-destructive-fill-loud)
    High contrast fill. Use for emphasized elements.
  • var(--color-destructive-fill-louder)
    Highest contrast fill. Use for maximum emphasis.
  • var(--color-destructive-text-on-soft)
    Text color to use on soft fill backgrounds.
  • var(--color-destructive-text-on-mid)
    Text color to use on mid fill backgrounds.
  • var(--color-destructive-text-on-loud)
    Text color to use on loud fill backgrounds.
  • var(--color-destructive-text-colorful)
    Colorful text variant. Use for error messages and destructive actions.
  • var(--color-destructive-stroke-softer)
    Subtlest stroke. Use for subtle borders.
  • var(--color-destructive-stroke-soft)
    Soft stroke. Use for default borders.
  • var(--color-destructive-stroke-mid)
    Mid-range stroke. Use for emphasized borders and error indicators.

Css reset

Css restyle

Inputs

Something is wrong

Typesetting

The .typesetting class creates consistent vertical rhythm for text-heavy content using CSS Grid. It styles headings, paragraphs, code blocks, horizontal rules, and maintains proper spacing between all elements.

Features

Use Cases

Apply .typesetting to containers with:

Comparison

With .typesettingWithout .typesetting

Heading 1 - Main Title

This is a paragraph demonstrating body text flow with consistent spacing and readability.

Heading 2 - Section Title

Lorem ipsum with some inline code showing proper vertical rhythm.

Heading 3 - Subsection

Heading 4

Heading 5
Heading 6

function example() {
  return "Code blocks styled nicely";
}

Final paragraph showing consistent vertical rhythm in action.

Heading 1 - Main Title

This is a paragraph demonstrating body text flow without proper spacing.

Heading 2 - Section Title

Lorem ipsum with some inline code showing inconsistent spacing.

Heading 3 - Subsection

Heading 4

Heading 5
Heading 6

function example() {
  return "Code blocks cramped";
}

Final paragraph showing poor vertical rhythm.

Css utils

Utilities for spacing, borders, and layout using data attributes. All utilities use logical properties for better internationalization support.

Structure

CSS utilities use data attributes instead of classes. Write data-padding="3" instead of .p-3, or data-background="surface" instead of .bg-surface.

All utility values map to design system tokens.

Combining Values

Spacing utilities (margin, padding), borders, gaps, and alignment attributes support space-separated values:

<div data-padding="i-5 b-3">

This applies padding-inline: var(--size-5) and padding-block: var(--size-3).

<div data-margin="i-auto b-4">

This applies margin-inline: auto and margin-block: var(--size-4).

Directional Suffixes

Spacing and border utilities use logical property suffixes:

Example: data-padding="i-5" applies horizontal padding, while data-padding="b-3" applies vertical padding.


Borders

Add borders to elements using the [data-border] attribute. Supports directional variants and combinations.

Directional Variants

Combine directions:

<div data-border="bs be">  <!-- top and bottom -->

Use [data-variant] to change border color:

Default Inline Block Variants
[data-border]
[data-border="i"]
[data-border="is"]
[data-border="ie"]
[data-border="b"]
[data-border="bs"]
[data-border="be"]
[data-border] [data-variant="strong"]
[data-border] [data-variant="primary"]
[data-border] [data-variant="neutral"]
[data-border] [data-variant="constructive"]
[data-border] [data-variant="destructive"]

Text Colors

Text color utilities apply semantic text colors using the [data-text] attribute.

General Text

[data-text=""] (default body text)

[data-text=“mid”] (secondary text)

[data-text=“softer”] (tertiary text)

Text on Colored Backgrounds

Use these values when text appears on colored fills to ensure proper contrast:

Where {family} is primary, neutral, constructive, or destructive.


Backgrounds

Apply background colors using the [data-background] attribute. Color families include five intensity levels: softer, soft, mid, loud, and louder.

Use [data-text] for proper text contrast on colored backgrounds.

Surface Colors

[data-background]

[data-background=“surface”]

[data-background=“surface-raised”]

Color Families

Primary Neutral Constructive Destructive

[data-background="primary-softer"] [data-text="on-primary-soft"]

[data-background="primary-soft"] [data-text="on-primary-soft"]

[data-background="primary-mid"] [data-text="on-primary-mid"]

[data-background="primary-loud"] [data-text="on-primary-loud"]

[data-background="primary-louder"] [data-text="on-primary-loud"]

[data-background="neutral-softer"] [data-text="on-neutral-soft"]

[data-background="neutral-soft"] [data-text="on-neutral-soft"]

[data-background="neutral-mid"] [data-text="on-neutral-mid"]

[data-background="neutral-loud"] [data-text="on-neutral-loud"]

[data-background="neutral-louder"] [data-text="on-neutral-loud"]

[data-background="constructive-softer"] [data-text="on-constructive-soft"]

[data-background="constructive-soft"] [data-text="on-constructive-soft"]

[data-background="constructive-mid"] [data-text="on-constructive-mid"]

[data-background="constructive-loud"] [data-text="on-constructive-loud"]

[data-background="constructive-louder"] [data-text="on-constructive-loud"]

[data-background="destructive-softer"] [data-text="on-destructive-soft"]

[data-background="destructive-soft"] [data-text="on-destructive-soft"]

[data-background="destructive-mid"] [data-text="on-destructive-mid"]

[data-background="destructive-loud"] [data-text="on-destructive-loud"]

[data-background="destructive-louder"] [data-text="on-destructive-loud"]


Gaps

Control spacing between flex or grid items using the [data-gap] attribute.

Row and Column Gaps

Use directional prefixes for independent row and column spacing:

Combine row and column gaps:

<div data-gap="r-3 c-5">  <!-- row-gap: var(--size-3); column-gap: var(--size-5) -->

Examples

Item 1
Item 2
Item 3
Item 1
Item 2
Item 3
Item 4

Available sizes: 0, 000, 00, 1-15, fluid-1 through fluid-10


Margin

Add space outside elements using the [data-margin] attribute.

Directional Control

Combine directions:

<div data-margin="i-5 b-3">  <!-- margin-inline: var(--size-5); margin-block: var(--size-3) -->
All Sides
[data-margin="3"]
[data-margin="fluid-5"]
Inline
[data-margin="i-3"]
[data-margin="is-3"]
[data-margin="ie-3"]
[data-margin="i-fluid-3"]
Block
[data-margin="b-2"]
[data-margin="bs-3"]
[data-margin="be-3"]
[data-margin="b-fluid-3"]
Combined
[data-margin="i-5 b-3"]
[data-margin="is-6 be-4"]
[data-margin="i-auto b-2"]

Available sizes: 0, 000, 00, 1-15, fluid-1-10, auto


Padding

Add space inside elements using the [data-padding] attribute.

Directional Control

Combine directions:

<div data-padding="i-body b-3">  <!-- padding-inline: var(--body-margin); padding-block: var(--size-3) -->
All Sides
[data-padding="3"]
[data-padding="fluid-5"]
Inline
[data-padding="i-5"]
[data-padding="is-6"]
[data-padding="ie-6"]
[data-padding="i-fluid-5"]
Block
[data-padding="b-5"]
[data-padding="bs-6"]
[data-padding="be-6"]
[data-padding="b-fluid-5"]
Combined
[data-padding="i-5 b-3"]
[data-padding="is-6 be-4"]
[data-padding="i-body b-3"]

Available sizes: body, 000, 00, 1-15, fluid-1-10


Alignment

Control flexbox and grid alignment using [data-align] and [data-justify] attributes.

data-align

Controls vertical alignment in flex layouts and block-axis alignment in grid.

align-items (default):

align-content (prefix: content-):

Use -items to align individual items. Use content- when working with wrapped flex items or grid tracks.

data-justify

Controls horizontal alignment in flex layouts and inline-axis alignment in grid.

justify-items (default):

justify-content (prefix: content-):

Use -items to align individual items. Use content- when working with wrapped flex items or grid tracks.

Combining Values

Combine values within each attribute:

<div data-align="center content-start">  <!-- align-items + align-content -->
<div data-justify="start content-between">  <!-- justify-items + justify-content -->

Combine both attributes for full control:

<div data-align="center" data-justify="content-between">

Justify Items

Controls main-axis alignment of items within their grid areas.

Center Start End Between Around Evenly
[data-justify="center"]
[data-justify="start"]
[data-justify="end"]
Item
[data-justify="between"]
Item
Item
[data-justify="around"]
Item
Item
[data-justify="evenly"]
Item

Align Items

Controls cross-axis alignment of items within their grid areas.

Center Start End Baseline Stretch
[data-align="center"]
[data-align="start"]
[data-align="end"]
Large
[data-align="baseline"]
Small
[data-align="stretch"]
[data-align="stretch"]

Css layout primitives

A set of layout primitives that can be used to build interfaces with.


Grid

Flexible grid layout with configurable columns and spanning capabilities.

Combine with [data-gap] for spacing between grid items, or combine with [data-justify] and [data-align] for cell alignment.

Basic Grid

A 3-column grid with equal-width columns.

Item 1
Item 2
Item 3
Code
<div class="grid" data-cols="3" data-gap="2">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2</div>
<div class="box" data-variant="surface">Item 3</div>
</div>

Column Spanning

Items can span multiple columns using data-span.

Spans 2 columns
Item
Code
<div class="grid" data-cols="3" data-gap="2">
<div class="box" data-variant="surface" data-span="2">Spans 2 columns</div>
<div class="box" data-variant="surface">Item</div>
</div>

Row and Column Spanning

Items can span both rows and columns simultaneously.

Spans 2 rows
Item 1
Item 2
Spans 2 columns
Code
<div class="grid" data-cols="3" data-gap="2">
<div class="box" data-variant="surface" data-row-span="2">Spans 2 rows</div>
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2</div>
<div class="box" data-variant="surface" data-span="2">Spans 2 columns</div>
</div>

Collection

Responsive grid layout that automatically adapts to available space. Items wrap to new rows as needed, maintaining a minimum card width.

Behavior

By default, Collection uses auto-fill which creates as many columns as will fit, leaving empty space if items don’t fill the row. Use data-variant="fit" to collapse empty columns and stretch items to fill the container.

Combine with [data-gap] for spacing between items.

Basic Collection

Default collection with automatic column creation based on available space.

Card 1
Card 2
Card 3
Code
<div class="collection">
<div class="box" data-variant="surface">Card 1</div>
<div class="box" data-variant="surface">Card 2</div>
<div class="box" data-variant="surface">Card 3</div>
</div>

Custom Card Size

Use data-size to control minimum card width. Larger sizes create wider cards that wrap earlier.

Card 1
Card 2
Card 3
Card 4
Code
<div class="collection" data-size="7" data-gap="3">
<div class="box" data-variant="surface">Card 1</div>
<div class="box" data-variant="surface">Card 2</div>
<div class="box" data-variant="surface">Card 3</div>
<div class="box" data-variant="surface">Card 4</div>
</div>

Auto-Fit Variant

With data-variant="fit", empty columns collapse and items stretch to fill available space.

Card 1
Card 2
Card 3
Code
<div class="collection" data-variant="fit" data-gap="3">
<div class="box" data-variant="surface">Card 1</div>
<div class="box" data-variant="surface">Card 2</div>
<div class="box" data-variant="surface">Card 3</div>
</div>

Content Grid

Full-width grid layout with centered content area and optional breakout zones.

CSS Variables

Control content grid widths with CSS custom properties:

Use Cases

Use Content Grid for article layouts, documentation pages, or any content where most elements should be constrained to a readable width, but some elements (like images or code blocks) need to break out wider or span the full viewport.

Content grids can be nested to create different content width zones within a page.

Width Zones

Children default to content width. Use data-width to break out to wider zones.

Content width (default)
Breakout width
Full width
Code
<div class="content-grid" data-gap="2">
<div class="box" data-variant="surface">Content width (default)</div>
<div class="box" data-variant="surface" data-width="breakout">Breakout width</div>
<div class="box" data-variant="surface" data-width="full">Full width</div>
</div>

Custom Width Variables

Override width variables for specific content grids.

Narrower content (800px max)
Narrower breakout (1000px max)
Code
<div class="content-grid" style="--content-width: 200px; --content-breakout-width: 300px;">
<div class="box" data-variant="surface">Narrower content (800px max)</div>
<div class="box" data-variant="surface" data-width="breakout">Narrower breakout (1000px max)</div>
</div>

Nested Content Grids

Content grids can be nested to create sections with different width constraints.

Outer content width
Nested content grid with narrower width
Nested content grid with narrower width
Back to outer content width
Code
<div class="content-grid">
<div class="box" data-variant="surface">Outer content width</div>

<div class="box content-grid" style="--content-width: 200px; --content-breakout-width: 300px;" data-width="full">
  <div class="box" data-variant="surface">Nested content grid with narrower width</div>
  <div class="box" data-variant="surface" data-width="breakout">Nested content grid with narrower width</div>
</div>

<div class="box" data-variant="surface">Back to outer content width</div>
</div>

Stack

Flex layout for arranging items in a single direction with optional spacing and alignment.

Combine with [data-gap] for spacing. Control alignment with:

Use Cases

Use Stack when you need a single column or row of items with consistent spacing. For multi-dimensional layouts where items wrap, use Collection instead.

Vertical Stack

Default stack direction is vertical (column).

Item 1
Item 2
Code
<div class="stack">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2</div>
</div>

Vertical Stack with Gap

Add spacing between stacked items.

Item 1
Item 2
Code
<div class="stack" data-gap="3">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2</div>
</div>

Horizontal Stack

Use data-direction="row" for horizontal layout.

Item 1
Item 2
Code
<div class="stack" data-direction="row">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2</div>
</div>

Horizontal Stack with Gap

Combine direction and gap for horizontal spacing.

Item 1
Item 2
More content
Code
<div class="stack" data-direction="row" data-gap="3">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2<br>More content</div>
</div>

Vertical Alignment (Cross-Axis)

In horizontal stacks, data-align controls vertical alignment.

Item 1
Item 2
More content
Code
<div class="stack" data-direction="row" data-gap="3" data-align="start">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2<br>More content</div>
</div>
Item 1
Item 2
More content
Code
<div class="stack" data-direction="row" data-gap="3" data-align="end">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2<br>More content</div>
</div>
Item 1
Item 2
More content
Code
<div class="stack" data-direction="row" data-gap="3" data-align="stretch">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2<br>More content</div>
</div>

Horizontal Alignment (Main-Axis)

In horizontal stacks, data-justify controls horizontal alignment.

Item 1
Item 2
More content
Code
<div class="stack" data-direction="row" data-gap="3" data-justify="center">
<div class="box" data-variant="surface">Item 1</div>
<div class="box" data-variant="surface">Item 2<br>More content</div>
</div>