Layout Components (`layouts/layout.css`)

This file provides a comprehensive library of declarative, property-driven layout components that integrate deeply with the framework's design token system. The

This file provides a comprehensive library of declarative, property-driven layout components that integrate deeply with the framework’s design token system. These components use custom HTML elements for semantic, maintainable layouts.

Start with these three

Most pages can begin with layout-stack for vertical rhythm, layout-cluster for wrapping groups, and layout-grid for responsive columns.

The everyday layout toolkit

Resize the page to watch the grid and cluster adapt.

Project activity
24
Open tasks
8
In review
17
Completed
<layout-stack gap="var(--space-md)">
<layout-cluster gap="var(--space-sm)" justify="space-between">
<strong>Project activity</strong>
<button type="button">Export</button>
</layout-cluster>
<layout-grid min-item-size="10rem" gap="var(--space-sm)">
<section>Open tasks</section>
<section>In review</section>
<section>Completed</section>
</layout-grid>
</layout-stack>

The primary layouts support custom-element, class, and data-* hosts. For example, <layout-stack>, .layout-stack, and [data-layout-stack] share the same behavior. Stack children stretch to the available width by default; add .stack-intrinsic to a child that should keep its content width.

Philosophy

  • Declarative & Semantic: Use <layout-grid> instead of classes like .l-grid
  • Property-Driven: Core logic controlled by CSS Custom Properties (e.g., --l-gap) that can be overridden via HTML attributes
  • Token-Integrated: Default values pulled from global design tokens defined in core/base.css
  • Composable & Context-Aware: Designed for nesting, with opt-in container-query hosts when descendants need them

Global Defaults

All layout components inherit these default CSS custom properties:

--l-gap: var(--space-md, 1.5rem);
--l-breakpoint: var(--bp-sm, 30em);
--l-padding: var(--space-md, 1.5rem);
--l-gutters: 1.5rem; /* Side margins for centering layouts */
--l-max-width: 65ch; /* Maximum width for readable content */

These can be overridden globally or per-component.

Base Behaviors

All layout components ([class^="layout-"]) share these base styles:

  • display: block
  • Prevent child overflow with min-width: 0 on direct children

Layouts size from their children by default, including when nested inside flex and grid containers. Add container-query, data-container-query, or the .layout-container class when descendants use the named container helpers:

<layout-stack container-query>
<div class="hide-on-narrow">Hidden below 30rem</div>
</layout-stack>

This opts into container-type: inline-size and names the container layout-container. Override the name with --layout-container-name.

Grid-Based Layouts

<layout-grid>

A responsive grid that automatically fits columns based on minimum item size.

Auto-fitting grid

Each item stays at least 9rem wide, then the grid wraps.

Alpha
Beta
Gamma
Delta

CSS Properties:

  • --l-min-item-size: Minimum size for each item (default: 16rem)
  • --l-gap: Gap between items

HTML Attributes:

  • min-item-size: Override minimum item size
  • gap: Override gap

Usage:

<layout-grid min-item-size="12rem" gap="1rem">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</layout-grid>

<layout-split>

A two-column layout that splits at a breakpoint, stacking on smaller screens.

Split content and supporting detail

Resize the example below 30rem to see the two regions stack.

Article

Main content keeps the larger fraction.

CSS Properties:

  • --l-fraction: Ratio for first column (default: 1fr)
  • --l-breakpoint: Container width to split at
  • --l-gap: Gap between columns

HTML Attributes:

  • fraction: Override column ratio
  • breakpoint: Override breakpoint
  • gap: Override gap
  • force-stack: Force stacked layout
  • no-stack: Prevent stacking

Usage:

<layout-split fraction="2fr" breakpoint="40em">
<div>Content</div>
<div>Sidebar</div>
</layout-split>

Flexbox-Based Layouts

<layout-stack>

A vertical stack with consistent spacing.

Children stretch to the available width by default. Add .stack-intrinsic when a button or other child should keep its natural width.

Stack with an intrinsic action

Invite your team

Send a reusable link or invite people individually.

CSS Properties:

  • --l-gap: Gap between items
  • --l-align: Alignment (default: stretch)

HTML Attributes:

  • gap: Override gap
  • align: Override alignment (stretch, center, start, end)

Usage:

<layout-stack gap="2rem" align="center">
<div>Item 1</div>
<div>Item 2</div>
</layout-stack>

<layout-cluster>

Groups items that wrap onto new lines, useful for tags or buttons.

Wrapping action cluster

The cluster wraps buttons while preserving their intrinsic widths.

CSS Properties:

  • --l-gap: Gap between items (default: var(—space-sm, 0.75rem))
  • --l-justify: Justification (default: flex-start)
  • --l-align: Alignment (default: center)

HTML Attributes:

  • gap: Override gap
  • justify: Override justification
  • align: Override alignment

Usage:

<layout-cluster gap="0.5rem" justify="center">
<button>Tag 1</button>
<button>Tag 2</button>
<button>Tag 3</button>
</layout-cluster>

<layout-reel>

A horizontally scrolling container. Set an item size so the overflow is intentional, keep the native scrollbar visible by default, and add tabindex="0" when the reel itself should be keyboard-scrollable.

Visible scrollbar and themed track

Every card has a fixed track size, so the row reliably overflows. Drag the scrollbar, shift-wheel, swipe, or focus the reel and use the arrow keys.

FoundationSemantic defaults

Native elements inherit the same token system.

ComponentsThree host forms

Use custom tags, classes, or data attributes.

LayoutContainer aware

Components adapt to the space they actually receive.

PlatformProgressive first

Modern features enhance a resilient baseline.

ThemingToken controlled

Change intent once instead of patching selectors.

Snapping reel with a hidden scrollbar

The data-attribute host uses the same API. Hiding the bar changes only its presentation; touch, wheel, and keyboard scrolling still work.

Step 1Choose a semantic host

Start with the native element that already carries the right meaning.

Step 2Add the component contract

Apply the custom tag, data attribute, or matching class.

Step 3Theme with tokens

Override the smallest semantic variable that expresses your intent.

Step 4Enhance when supported

Layer in snapping or modern platform behavior without losing the baseline.

CSS Properties:

  • --l-gap: Gap between items
  • --l-reel-item-size: Shared flex basis for direct children
  • --l-reel-scroll-padding: Logical inline scroll padding, especially useful with snapping
  • --l-reel-scrollbar-thumb: Scrollbar thumb color
  • --l-reel-scrollbar-thumb-hover: Hovered thumb color
  • --l-reel-scrollbar-track: Scrollbar track color
  • --l-reel-scrollbar-size: WebKit scrollbar track height
  • --l-reel-scrollbar-size-thin: Track height for the thin variant

HTML Attributes:

  • gap: Override gap
  • item-size: Direct-child flex basis, such as 14rem or clamp(12rem, 75%, 20rem)
  • scroll-padding: Logical inline scroll padding
  • scrollbar="auto|thin|hidden": Choose the native scrollbar presentation
  • snap: Opt into proximity snapping at each direct child
  • no-scrollbar: Legacy alias for scrollbar="hidden"

Usage:

<layout-reel item-size="14rem" gap="1rem" scrollbar="thin" snap tabindex="0">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</layout-reel>

<layout-switcher>

Switches from vertical stack to horizontal row when items have enough space.

Threshold-based switcher

The same two regions stack or sit side-by-side based on the container width.

Profile

Account details and avatar.

Notifications

Email and push preferences.

CSS Properties:

  • --l-threshold: Space threshold for switching (default: 30rem)
  • --l-gap: Gap between items

HTML Attributes:

  • threshold: Override threshold
  • gap: Override gap

Usage:

<layout-switcher threshold="25rem">
<div>Title</div>
<div>Description</div>
</layout-switcher>

Wrapper & Centering Layouts

<layout-pad>

Adds consistent padding to content.

Logical padding controls

Change block and inline padding independently without writing directional rules.

Padded content

Block and inline space use the same token vocabulary.

CSS Properties:

  • --l-padding: Padding value
  • --l-padding-inline: Horizontal padding
  • --l-padding-block: Vertical padding

HTML Attributes:

  • padding: Override padding
  • padding-x: Override horizontal padding
  • padding-y: Override vertical padding

Usage:

<layout-pad padding="2rem">
<p>Content with padding</p>
</layout-pad>

<layout-center>

Centers content horizontally with max-width for readability. The maximum width includes the component’s gutters, so it remains overflow-safe as a full-width child of layout-stack, grid, or flex layouts.

Readable centered measure

The max width controls line length while gutters protect the edges on small screens.

Readable by default

Long-form content stays comfortable to scan instead of stretching across the entire preview.

CSS Properties:

  • --l-max-width: Maximum width (default: 65ch)
  • --l-gutters: Side padding (default: var(—space-md, 1.5rem))

HTML Attributes:

  • max-width: Override max width
  • gutters: Override gutters
  • and-text: Also center text

Usage:

<layout-center max-width="50ch" and-text>
<p>Centered content</p>
</layout-center>

<layout-inline-center>

Centers content horizontally without a max-width constraint, useful for full-width centering. Its gutters are included in its rendered width.

Full-width inline centering

Unlike layout-center, the content can use the full available width while its contents remain centered.

Centered action

CSS Properties:

  • --l-gutters: Side padding (default: var(—space-md, 1.5rem))

HTML Attributes:

  • gutters: Override gutters
  • and-text: Also center text

Usage:

<layout-inline-center gutters="2rem" and-text>
<p>Centered content without width limit</p>
</layout-inline-center>

<layout-frame>

Creates responsive media containers with fixed aspect ratios.

Aspect-ratio frame

The frame reserves media space before the asset loads and keeps the ratio responsive.

4:3 media frame

CSS Properties:

  • --l-aspect-ratio: Aspect ratio (default: 16 / 9)

HTML Attributes:

  • ratio: Override aspect ratio

Usage:

<layout-frame ratio="4/3">
<img src="image.jpg" alt="Framed image">
</layout-frame>

Complex Layout Patterns

<layout-sidebar>

Sidebar layout that stacks on small screens.

Content with a supporting sidebar

The regions wrap when the content can no longer keep its minimum width.

Main content

The main region grows to use the remaining space.

CSS Properties:

  • --l-breakpoint: Breakpoint for stacking
  • --l-side-width: Sidebar width (default: 20rem)
  • --l-content-min: Minimum content width (default: 50%)
  • --l-gap: Gap between areas

HTML Attributes:

  • breakpoint: Override breakpoint
  • side-width: Override sidebar width
  • content-min-width: Override content min width
  • side: Sidebar position (“left” or “right”)
  • gap: Override gap

Mark the supporting region with slot="aside", data-layout-sidebar-aside, or .layout-sidebar__aside. The data/class forms are useful in template systems that reserve or consume slot.

Usage:

<layout-sidebar side="right" side-width="15rem">
<main>Main content</main>
<aside data-layout-sidebar-aside>Sidebar</aside>
</layout-sidebar>

<layout-page>

Standard page layout with header, main, and footer.

Page regions and slots

Header, main, and footer remain named landmarks while layout-page owns the vertical frame.

Northstar

Workspace

Main content grows into the available frame.

Updated just now

CSS Properties:

  • --l-min-height: Minimum height (default: 100vh)
  • --l-gap: Gap between sections

HTML Attributes:

  • min-height: Override min height
  • gap: Override gap

Usage:

<layout-page min-height="100vh">
<header slot="header">Header</header>
<main slot="main">Main content</main>
<footer slot="footer">Footer</footer>
</layout-page>

Browser Support

  • Modern browsers with CSS Grid and Flexbox support
  • Container queries require recent browser versions
  • Custom elements work in all modern browsers
  • Fallbacks provided for older browsers where possible

Integration Notes

  • Import this file into the components layer in index.css
  • Add container-query, data-container-query, or .layout-container only when descendants use named container-query helpers
  • Custom properties can be overridden globally in core/theme.css or per-component
  • Combine with other framework components for complete layouts
  • core/base.css: Defines global design tokens used by these components
  • core/theme.css: Theme-specific overrides
  • components/: Other UI components that work well with these layouts