16 CSS Two-Column Layouts12 / 16

Pure CSSMIT licensed

CSS Two Column Article Layout

True newspaper-style text flow: one continuous article poured into two columns with column-count: 2, a hairline column-rule between them, a spanning headline (column-span: all), a drop cap and a pull-quote that text wraps around — CSS Multi-column, the two column layout grid and flexbox can’t do.

Published

Live Demo
Try it

The code

<section class="tcl-12" aria-label="Two column article layout demo">
  <article class="tcl-12__article" lang="en">
    <header class="tcl-12__top">
      <span class="tcl-12__section">Craft · Typography</span>
      <span class="tcl-12__date">31 July 2026</span>
    </header>
    <div class="tcl-12__flow">
      <h1 class="tcl-12__hed">The quiet return of the two-column page</h1>
      <p class="tcl-12__dek">Screens got wide. Lines got long. The oldest layout in publishing is fixing a very modern readability problem.</p>
      <p class="tcl-12__body tcl-12__body--first">For five hundred years, printers solved wide pages the same way: split the text. The column was never decoration — it was a reading tool, keeping each line short enough that the eye could find its way back to the next one without effort.</p>
      <p class="tcl-12__body">The web forgot this for a while. Fluid layouts stretched paragraphs to two hundred characters on desktop monitors, and readability research kept measuring what typographers already knew: comprehension drops as measure grows past about seventy-five characters.</p>
      <aside class="tcl-12__pull"><p>“The column was never decoration — it was a reading tool.”</p></aside>
      <p class="tcl-12__body">CSS Multi-column brings the printer’s fix to the browser in one declaration. Unlike grid, it flows a single story through the gaps — fill the first column, spill into the second — and balances their heights automatically, hyphenating and breaking with rules the specification borrowed directly from print.</p>
      <p class="tcl-12__body">Used with restraint — a feature, an editor’s letter, fine print — it reads beautifully. Used on a three-thousand-word essay it sends readers scrolling back to the top, which is why the pattern thrives in short-form editorial and nowhere else.</p>
    </div>
  </article>
</section>
.tcl-12,
.tcl-12 *,
.tcl-12 *::before,
.tcl-12 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.tcl-12 {
  width: 100%;
  min-height: 100vh;
  --ink: oklch(0.22 0.01 60);
  --accent: oklch(0.5 0.12 30);
  font-family: Georgia,'Iowan Old Style',serif;
  color: var(--ink);
  background: oklch(0.975 0.006 80);
  padding: clamp(24px,4vw,56px);
}

.tcl-12__article {
  max-width: 820px;
  margin-inline: auto;
}

.tcl-12__top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: 1px solid oklch(0.85 0.02 70);
  padding-bottom: 10px;
  margin-bottom: 22px;
  font-family: 'Segoe UI',system-ui,sans-serif;
}

.tcl-12__section {
  font: 700 11px/1 inherit;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
}

.tcl-12__date {
  font: 500 12px/1 inherit;
  color: color-mix(in oklab,var(--ink) 55%,transparent);
}

.tcl-12__flow {
  column-count: 2;
  column-gap: 3rem;
  column-rule: 1px solid oklch(0.86 0.02 70);
}

.tcl-12__hed {
  column-span: all;
  font-size: clamp(28px,4.2vw,44px);
  line-height: 1.08;
  letter-spacing: -.02em;
  font-weight: 700;
  margin-bottom: 10px;
  text-wrap: balance;
}

.tcl-12__dek {
  column-span: all;
  font-style: italic;
  font-size: clamp(15px,2vw,18px);
  line-height: 1.5;
  color: color-mix(in oklab,var(--ink) 65%,transparent);
  margin-bottom: 26px;
  text-wrap: pretty;
}

.tcl-12__body {
  font-size: 14.5px;
  line-height: 1.8;
  margin-bottom: 14px;
  text-wrap: pretty;
  hyphens: auto;
}

.tcl-12__body--first::first-letter {
  font-weight: 700;
  color: var(--accent);
  float: left;
  font-size: 52px;
  line-height: .85;
  padding: 4px 8px 0 0;
}

@supports (initial-letter: 3) {
  .tcl-12__body--first::first-letter {
    float: none;
    padding: 0 8px 0 0;
    font-size: inherit;
    initial-letter: 3;
  }
}

.tcl-12__pull {
  break-inside: avoid;
  border-block: 3px solid var(--ink);
  padding: 16px 4px;
  margin: 10px 0 18px;
}

.tcl-12__pull p {
  font-size: 19px;
  line-height: 1.4;
  font-weight: 700;
  letter-spacing: -.01em;
  text-wrap: balance;
}

@media (max-width: 620px) {
  .tcl-12__flow {
    column-count: 1;
    column-rule: none;
  }
}
/* No JavaScript — column-count:2 + column-gap + column-rule flow one text stream through both columns; column-span:all lets the headline escape. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Two-Column Layout from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Two Column Article Layout
Source: https://codefronts.com/layouts/css-two-column-layout/css-two-column-article-layout/

True newspaper-style text flow: one continuous article poured into two columns with column-count: 2, a hairline column-rule between them, a spanning headline (column-span: all), a drop cap and a pull-quote that text wraps around — CSS Multi-column, the two column layout grid and flexbox can’t do.
## HTML
```html
<section class="tcl-12" aria-label="Two column article layout demo">
  <article class="tcl-12__article" lang="en">
    <header class="tcl-12__top">
      <span class="tcl-12__section">Craft · Typography</span>
      <span class="tcl-12__date">31 July 2026</span>
    </header>
    <div class="tcl-12__flow">
      <h1 class="tcl-12__hed">The quiet return of the two-column page</h1>
      <p class="tcl-12__dek">Screens got wide. Lines got long. The oldest layout in publishing is fixing a very modern readability problem.</p>
      <p class="tcl-12__body tcl-12__body--first">For five hundred years, printers solved wide pages the same way: split the text. The column was never decoration — it was a reading tool, keeping each line short enough that the eye could find its way back to the next one without effort.</p>
      <p class="tcl-12__body">The web forgot this for a while. Fluid layouts stretched paragraphs to two hundred characters on desktop monitors, and readability research kept measuring what typographers already knew: comprehension drops as measure grows past about seventy-five characters.</p>
      <aside class="tcl-12__pull"><p>“The column was never decoration — it was a reading tool.”</p></aside>
      <p class="tcl-12__body">CSS Multi-column brings the printer’s fix to the browser in one declaration. Unlike grid, it flows a single story through the gaps — fill the first column, spill into the second — and balances their heights automatically, hyphenating and breaking with rules the specification borrowed directly from print.</p>
      <p class="tcl-12__body">Used with restraint — a feature, an editor’s letter, fine print — it reads beautifully. Used on a three-thousand-word essay it sends readers scrolling back to the top, which is why the pattern thrives in short-form editorial and nowhere else.</p>
    </div>
  </article>
</section>
```
## CSS
```css
.tcl-12,
.tcl-12 *,
.tcl-12 *::before,
.tcl-12 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.tcl-12 {
  width: 100%;
  min-height: 100vh;
  --ink: oklch(0.22 0.01 60);
  --accent: oklch(0.5 0.12 30);
  font-family: Georgia,'Iowan Old Style',serif;
  color: var(--ink);
  background: oklch(0.975 0.006 80);
  padding: clamp(24px,4vw,56px);
}

.tcl-12__article {
  max-width: 820px;
  margin-inline: auto;
}

.tcl-12__top {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  border-bottom: 1px solid oklch(0.85 0.02 70);
  padding-bottom: 10px;
  margin-bottom: 22px;
  font-family: 'Segoe UI',system-ui,sans-serif;
}

.tcl-12__section {
  font: 700 11px/1 inherit;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
}

.tcl-12__date {
  font: 500 12px/1 inherit;
  color: color-mix(in oklab,var(--ink) 55%,transparent);
}

.tcl-12__flow {
  column-count: 2;
  column-gap: 3rem;
  column-rule: 1px solid oklch(0.86 0.02 70);
}

.tcl-12__hed {
  column-span: all;
  font-size: clamp(28px,4.2vw,44px);
  line-height: 1.08;
  letter-spacing: -.02em;
  font-weight: 700;
  margin-bottom: 10px;
  text-wrap: balance;
}

.tcl-12__dek {
  column-span: all;
  font-style: italic;
  font-size: clamp(15px,2vw,18px);
  line-height: 1.5;
  color: color-mix(in oklab,var(--ink) 65%,transparent);
  margin-bottom: 26px;
  text-wrap: pretty;
}

.tcl-12__body {
  font-size: 14.5px;
  line-height: 1.8;
  margin-bottom: 14px;
  text-wrap: pretty;
  hyphens: auto;
}

.tcl-12__body--first::first-letter {
  font-weight: 700;
  color: var(--accent);
  float: left;
  font-size: 52px;
  line-height: .85;
  padding: 4px 8px 0 0;
}

@supports (initial-letter: 3) {
  .tcl-12__body--first::first-letter {
    float: none;
    padding: 0 8px 0 0;
    font-size: inherit;
    initial-letter: 3;
  }
}

.tcl-12__pull {
  break-inside: avoid;
  border-block: 3px solid var(--ink);
  padding: 16px 4px;
  margin: 10px 0 18px;
}

.tcl-12__pull p {
  font-size: 19px;
  line-height: 1.4;
  font-weight: 700;
  letter-spacing: -.01em;
  text-wrap: balance;
}

@media (max-width: 620px) {
  .tcl-12__flow {
    column-count: 1;
    column-rule: none;
  }
}
```

## JavaScript
```js
/* No JavaScript — column-count:2 + column-gap + column-rule flow one text stream through both columns; column-span:all lets the headline escape. */
```

How this works

Grid and flex place BOXES side by side; Multi-column flows one continuous TEXT stream through columns, filling the first and overflowing into the second like a newspaper. One declaration does it: column-count:2; column-gap:3rem; column-rule:1px solid. The browser balances the columns to near-equal height automatically.

The editorial details are all native: the headline escapes the flow with column-span:all; the drop cap is ::first-letter with initial-letter (and a float fallback); the pull-quote uses break-inside:avoid so it never splits across the column break. On narrow screens one media query drops to column-count:1.

Make it yours

  • Prefer a width trigger over a count: column-width:34ch makes the browser fit as many ≥34ch columns as space allows — auto-responsive without a media query.
  • Style the divider via column-rule exactly like a border (try double for vintage newsprint).
  • Tune the drop cap depth with initial-letter:3 → 2 or 4 lines.
  • Add hyphenation for justified fine print: text-align:justify; hyphens:auto (requires a lang attribute).

Gotchas — read before shipping

  • Keep multi-column for MODERATE text lengths — readers must scroll up to continue in column two, so full-length articles belong in a single column with a sidebar (demo 07) instead.
  • Put break-inside:avoid on figures, blockquotes and list items or they split mid-element across the break.
  • Line length is the readability contract: pair column-count with a max-width on the container so columns stay in the 45–75 character range.

Browser support

ChromeSafariFirefoxEdge
114+17.5+121+114+

Floor set by oklch(), color-mix(), text-wrap as this demo is written. The core technique itself goes back further — Chrome 50+.

Multi-column layout is old and universal; initial-letter drop caps need Chrome 110+/Safari 9+ and fall back to the included float-based cap in Firefox.

Techniques used in this demo

Search CodeFronts

Loading…