Vanilla Breeze

layout-columns

Multi-column text flow with measure constraints, column breaks, and vertical rhythm. Handles responsive column layout as a pure CSS layer — no JavaScript required.

Attributes

Attribute Values Default Description
data-layout-column-count auto, 1, 2, 3 absent (single column) Column strategy. auto uses CSS column-width for responsive columns. Numbers set explicit column count.
data-layout-measure narrow, normal, wide normal (65ch) Constrains single-column line length. No effect when multi-column is active.
data-layout-align start, justify start Text alignment. justify enables automatic hyphenation.

How It Works

The layout-columns element is a column flow primitive. It controls:

  • Measure — constrains line length to a readable width (65ch default)
  • Column flow — responsive or explicit multi-column layout via CSS columns
  • Break hygiene — prevents blockquotes, figures, tables, lists from splitting across columns
  • Vertical rhythm — intelligent spacing between headings, paragraphs, and blocks (same rules as layout-text)
  • Inline padding — gutter so content doesn't touch screen edges on mobile

It does not set font family, hyphenation defaults, or drop caps — those belong to the <article> element's existing data-prose and data-drop-cap attributes.

Usage Examples

Single Column (Default)

Without any attributes, layout-columns provides a measure-constrained container with vertical rhythm:

Auto Columns

The recommended responsive pattern. The browser fits as many columns as the container allows, based on a minimum column width of 38ch:

Explicit Two Column

Force a fixed column count. Best for controlled-width contexts:

Narrow Measure

Tighter line length for sidebars and captions:

Attribute Form

Like other layout primitives, you can use data-layout="columns" directly on a semantic element instead of wrapping in <layout-columns>:

Inside reader-view

layout-columns is the inner surface for reader-view, which adds paged reading mode:

Column Strategy

The correct CSS multi-column idiom for responsive use is column-width, not column-count. The browser determines how many columns fit:

Viewport Auto Columns
390px (iPhone)~1 column
820px (iPad)~2 columns
1200px (desktop)~3 columns

For explicit counts (data-layout-column-count="2"), column-width: unset is applied to prevent the two CSS properties from fighting each other.

Custom Properties

Override column behaviour per-instance without new attributes:

Property Default Description
--column-min-width 38ch Minimum column width for auto mode
--column-gap var(--size-2xl) Gap between columns

Spacing Rules

Vertical rhythm matches layout-text:

Context Spacing
Default (between elements)var(--size-m)
Before h2var(--size-2xl)
Before h3var(--size-xl)
Before h4/h5/h6var(--size-l)
After any headingvar(--size-s)
Before/after figures and prevar(--size-l)

Best Practices

  • Prefer auto over explicit counts — let the browser choose. Use explicit counts only in known-width containers.
  • Use data-layout-align="justify" with multi-column — ragged-right lines disrupt column rules in multi-column layouts.
  • Pair with article[data-prose] — layout-columns handles flow, article handles typographic quality (hyphenation, limits).
  • Don't nest inside layout-text — use one or the other. They serve the same rhythm role.

Related