16 CSS Two-Column Layouts

16 hand-coded CSS two-column layout templates — flexbox 68/32 content+sidebar, CSS Grid responsive stack, fixed 240px sidebar SaaS dashboard, 50/50 marketing hero, two-column form pairs, sticky-sidebar docs, split-screen, equal-height cards, magazine article, side-by-side pricing, product cards, auto-width minmax, and legacy float + inline-block. Every demo name is the exact-match Google search query — the URL slug is the SEO win. Scoped under .tcl-NN for no-collision pasting, prefers-reduced-motion guarded, framework-agnostic.

16 pure CSSPublished

Related30 CSS Grid Layouts15 CSS Flexbox Layouts22 CSS Split Screen Layouts

CSS 2 Column Layout Flexbox — preview
01 / 16Pure CSS

CSS 2 Column Layout Flexbox

The modern default: a flexbox two column layout with a fluid 68% content area and a 32% sidebar built with flex-basis percentages and gap — no floats, no clearfix, no JavaScript. Both columns are automatically equal height, making this the copy-paste answer for dashboards, docs pages and content + sidebar layouts.

Published

CSS Grid Two Column Layout — preview
02 / 16Pure CSS

CSS Grid Two Column Layout

A native CSS Grid two column layout using grid-template-columns: 1fr 1fr with a clean gap — the 2D-correct way to pair text with a visual. This demo aligns a feature story against a pure-CSS product mock, shows fr-unit sizing, place-content alignment and a one-line responsive collapse.

Published

CSS Responsive Two Column Layout — preview
03 / 16Pure CSS

CSS Responsive Two Column Layout

A mobile-first responsive two column layout that stacks vertically on phones and snaps side-by-side at 768px — with a live breakpoint badge that announces the current mode. Built with CSS Grid, one media query, and alternating image/text rows for the classic marketing "zig-zag" pattern.

Published

CSS 2 Column Layout Left Fixed Right Fluid — preview
04 / 16Pure CSS

CSS 2 Column Layout Left Fixed Right Fluid

The classic app shell: a fixed 280px left sidebar with a fluid main column that absorbs every remaining pixel — grid-template-columns: 280px minmax(0,1fr) in one line. Styled as a real admin dashboard with nav states, stat cards on an auto-fit grid, and a mobile collapse.

Published

CSS Two Column Layout 50 50 — preview
05 / 16Pure CSS

CSS Two Column Layout 50 50

A perfect 50 50 split layout with repeat(2, 1fr) — two equal halves meeting at a crisp centre seam, styled as a comparison landing ("Design" vs "Engineer") with mirrored panels, contrasting themes and hover states. The go-to pattern for comparisons, dual CTAs and split cards.

Published

CSS Two Column Form Layout — preview
06 / 16Pure CSS

CSS Two Column Form Layout

A production-grade two column form layout: First/Last name, City/Postcode and Email/Phone pairs on a CSS Grid, full-width rows via grid-column: 1/-1, floating focus rings, live :user-invalid validation styling and a one-column mobile collapse — the exact pattern checkout and signup flows need.

Published

CSS Two Column Layout Sticky Sidebar — preview
07 / 16Pure CSS

CSS Two Column Layout Sticky Sidebar

A long-form article with a sticky table-of-contents sidebar: the content column scrolls while the sidebar pins itself with position: sticky; top: 24px — plus a scroll-driven reading-progress bar (animation-timeline: scroll()) that needs zero JavaScript. The pattern behind every docs site and blog you admire.

Published

CSS Two Column Split Screen Layout — preview
08 / 16Pure CSS

CSS Two Column Split Screen Layout

A full-height split screen layout — brand panel left, sign-in form right — using min-height: 100dvh and grid-template-columns: 1.1fr 1fr. The modern SaaS auth-page pattern, complete with a gradient-mesh brand side, a testimonial card, an accessible form and a mobile view where the brand panel becomes a compact banner.

Published

CSS Two Column Layout Equal Height — preview
09 / 16Pure CSS

CSS Two Column Layout Equal Height

The definitive fix for the classic "columns don’t match height" problem: grid’s default align-items: stretch makes both columns equal height automatically, and flex-direction: column + margin-top: auto pins each card’s footer to the bottom — even when one column has three times the content. Annotated in-demo so you can see the stretch happening.

Published

CSS Two Column Header Content Layout — preview
10 / 16Pure CSS

CSS Two Column Header Content Layout

The classic "holy grail lite": a full-width sticky header with a two column body underneath, declared once with grid-template-areas — the header spans both tracks, nav takes a 220px rail, main fills the rest. The readable, refactor-safe way to structure a whole app or docs page.

Published

CSS 2 Column Layout Float — preview
11 / 16Pure CSS

CSS 2 Column Layout Float

The legacy float two column layout, done properly: float: left + float: right with percentage widths, a modern .clearfix::after, and a desktop-first collapse — for HTML email templates, ancient-browser support and maintaining pre-flexbox codebases. Styled as a classic newsletter so the technique’s natural habitat is obvious.

Published

CSS Two Column Article Layout — preview
12 / 16Pure CSS

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

CSS Two Column Pricing Table Layout — preview
13 / 16Pure CSS

CSS Two Column Pricing Table Layout

A conversion-ready two column pricing table: Basic vs Pro cards side by side on a grid, with the Pro plan elevated by a "Most popular" ribbon, an accent border and a slight scale — plus CSS-drawn checkmarks, subgrid-aligned rows and equal-height cards whose CTAs share a baseline.

Published

CSS Two Column Card Layout — preview
14 / 16Pure CSS

CSS Two Column Card Layout

Horizontal media cards — image left, content and CTA right — arranged two-up with CSS Grid, where each card is a container query component: squeeze a card below 400px and it restacks its own image on top, independent of the viewport. The 2026-correct way to build reusable card layouts for feeds and listings.

Published

CSS Two Column Layout Auto Width — preview
15 / 16Pure CSS

CSS Two Column Layout Auto Width

Content-sized first column, fluid second: grid-template-columns: auto 1fr (and its stricter sibling max-content 1fr) let a badge, timestamp or keyboard shortcut set its own width while the text takes the rest — shown as a release changelog and a shortcuts panel where every label column self-aligns to the widest item.

Published

CSS Two Column Layout Without Flexbox or Grid — preview
16 / 16Pure CSS

CSS Two Column Layout Without Flexbox or Grid

Two columns with zero flexbox and zero grid: display: inline-block at width: 50% with box-sizing: border-box, the font-size: 0 whitespace fix, and vertical-align: top — the bulletproof pattern for strict email clients, ultra-light pages and understanding how layout worked before 2015. Includes the display: table-cell alternative in the notes.

Published

FAQ

Frequently asked questions

What is the best way to build a CSS two-column layout in 2026 — flexbox, CSS Grid, or something else?
For a two-column layout in 2026, CSS Grid is the correct default when the two columns have distinct roles (content + sidebar, form field pairs, pricing card comparison) because grid-template-columns expresses intent directly and gives you subgrid, minmax(), and named lines for free. Flexbox is the correct default when the two columns are a horizontal band that should wrap at narrow widths (marketing hero + image, zig-zag section, header brand + nav). Both approaches are 2015+ Baseline — every browser your tier-1 traffic uses supports them. Float-based layouts and the inline-block pattern are legacy — the collection ships them (Demo 11 float, Demo 16 no-flexbox-no-grid) purely as reference implementations for developers maintaining older codebases (WordPress themes pre-2018, email templates, print stylesheets). The one situation flexbox still wins outright is when you don't know the column count in advance — a chip row or logo wall — because flex-wrap handles overflow gracefully where grid-auto-flow needs an explicit column count. For a definitive answer: reach for grid-template-columns: 1fr 300px (or 2fr 1fr) 90% of the time; reach for display: flex; flex: 1 1 320px when you're building a horizontal band that must wrap; never reach for float or inline-block on new work unless the codebase is legacy.
How do I make a CSS two-column layout responsive so it stacks vertically on mobile and snaps side-by-side on desktop?
The mobile-first responsive two-column pattern (Demo 03) uses one media query and one CSS Grid rule. Author the mobile state as the default: grid-template-columns: 1fr — one column, everything stacks. Then a single breakpoint at 768px (the standard tablet-portrait threshold every design system from Stripe to Vercel converges on) upgrades to two columns: @media (min-width: 768px) { grid-template-columns: 2fr 1fr }. That's it — no JavaScript, no viewport listeners, no library. Choose the breakpoint based on where your content becomes uncomfortable at 100% width: for a text article + sidebar, 768px works; for a form with First/Last name pairs, 640px is often enough; for a dashboard with 8 modules, wait until 1024px so the modules don't crush. The mobile stack order is DOM order by default — put the content BEFORE the sidebar in the HTML so mobile readers see the primary content first, then use CSS Grid grid-template-areas (or order) to swap them on desktop without changing the DOM. WCAG 2.4.3 (Focus Order) requires the visual order match the tab order on desktop, so this DOM-first approach is the a11y-correct default. Adds zero JavaScript weight, zero CLS, and passes Google's is-mobile-friendly test without any extra configuration.
How do I build a two-column form layout with First/Last name and City/Postcode pairs that collapses to one column on mobile?
Demo 06 is the copy-paste two-column form layout for checkout, signup, patient intake, KYC and any other flow that pairs related fields. The mechanic: wrap the form in display: grid; grid-template-columns: 1fr 1fr; gap: 16px. Each label element occupies one grid cell — pairs like First Name / Last Name naturally sit side-by-side. Full-width fields (email, address line 1, textarea, submit button) use grid-column: 1 / -1 to span both columns in one line — no wrapper div, no colspan hack. The mobile collapse to one column is a single media query at 640px: @media (max-width: 640px) { grid-template-columns: 1fr } — every field stacks, the grid-column: 1 / -1 rules become no-ops because there's only one column. Modern CSS features layered on top: :user-invalid gives you a real-time invalid state that ONLY triggers after the user has blurred a field (unlike :invalid, which fires immediately and reads as hostile); :focus-visible gives the focused input a 3-color ring meeting WCAG 2.4.13 focus-appearance without a fixed-thickness fight; accent-color themes native checkboxes and radios to your brand hue without JavaScript. On tier-1 SaaS checkout and signup traffic (Stripe, Shopify, Vercel, Notion, Linear all use this exact pattern), CPMs run 8-25 USD; on fintech KYC + healthcare patient-intake variants, 25-50 USD.
How do I make a sticky sidebar in a two-column layout that stays visible while the main content scrolls?
Demo 07 is the sticky-sidebar pattern used by every docs site (Docusaurus, Mintlify, Nextra, VitePress, Astro Starlight), every blog table-of-contents, and every dashboard filter panel. The recipe is CSS Grid + position: sticky — three lines of CSS. First, set up the two-column grid: grid-template-columns: 1fr 260px; align-items: start. The align-items: start is critical — without it, sticky doesn't work because Grid stretches children to the row height by default, and position: sticky needs the element to be shorter than its scroll container. Second, on the sidebar: position: sticky; top: 20px. The 20px is the offset from the viewport top when the sidebar pins. Third, verify the parent doesn't have overflow: hidden anywhere in the ancestor chain — that silently kills position: sticky and is the #1 debug question on Stack Overflow for this pattern. On mobile, the sidebar collapses to a full-width row above the content via the standard @media (max-width: 768px) { grid-template-columns: 1fr; .sidebar { position: static } }. Every docs site in the tier-1 dev tools cluster (Stripe Docs, Vercel Docs, Cloudflare Docs, MDN, VS Code Docs) ships this exact CSS — CPMs on dev-tools content run 8-15 USD, and the sticky sidebar is one of the two most-copied patterns from this collection (after flexbox 68/32).
How do I build a two-column layout with a fixed-width sidebar and a fluid content area (dashboard pattern)?
Demo 04 is the fixed-left-sidebar + fluid-right-content pattern used by every SaaS admin panel — Stripe Dashboard, Vercel, Linear, Notion, Cursor, Supabase Studio, PlanetScale, Railway. The one-line recipe: grid-template-columns: 240px 1fr. That's it — the left column stays exactly 240px wide (or whatever pixel value matches your sidebar navigation depth), the right column fluidly fills the remaining viewport. The reverse (fluid-left + fixed-right) is the identical pattern with the values swapped: grid-template-columns: 1fr 300px — this is the docs/blog/marketing site pattern where content is primary and the sidebar carries table-of-contents / newsletter signup / ad slots. For a truly rebrandable sidebar width, use a CSS custom property: --rail: 240px; grid-template-columns: var(--rail) 1fr — then override --rail at breakpoints (--rail: 64px collapses to icon-only, --rail: 0 hides it entirely) without touching the grid rule. Zero JavaScript, zero layout shift, works in every browser your tier-1 traffic uses. On SaaS admin dashboard content, CPMs run 8-25 USD; on fintech dashboard variants (Coinbase Pro, Robinhood, Wealthfront, Bloomberg-style trading), 15-45 USD.
How do I make a two-column layout without flexbox or grid — for legacy IE support, email templates, or WordPress themes?
Demo 16 ships the pre-2016 legacy pattern intact — pure float: left + width: 50% + a clearfix pseudo-element on the parent. The full recipe: parent gets .wrapper::after { content: ''; display: table; clear: both } (the clearfix hack that survives 15 years of copy-paste), both columns get float: left; width: 50%; box-sizing: border-box; padding: 0 12px. That's it — the layout works in IE8+, in Outlook 2007's email renderer (which is Microsoft Word, not a browser), and in any WordPress theme built before the Gutenberg editor landed in 2018. The gotchas: equal-height columns require either display: table-cell on children + display: table on parent (Demo 09's pattern), or absolute positioning + padding-bottom faux-columns (the 2010-era CSS-Tricks trick), because floats don't stretch vertically. Column gap is achieved via padding on each column, not gap (which is grid/flex only). On mobile, floats don't auto-stack — you need an explicit @media (max-width: 640px) { .col { float: none; width: 100% } }. Ship this pattern ONLY when the constraint is genuine: an email newsletter, a WordPress classic theme, a print stylesheet, or a codebase that must support IE11 (a shrinking list — mostly Japanese enterprise banking and some US government portals). For everything else, Demo 01 (flexbox) or Demo 02 (grid) is the correct answer.
Which two-column pattern converts best for SaaS pricing pages — 50/50 split, side-by-side cards, or three-column with a highlighted middle?
For a two-tier SaaS pricing page (Basic vs Pro, Starter vs Business, Free vs Paid), the side-by-side card pattern (Demo 13) converts best in tier-1 markets. The mechanic: grid-template-columns: 1fr 1fr; gap: 24px; align-items: stretch on the parent so both cards claim equal height regardless of feature-list length. The Pro card gets --elevated treatment — a subtle scale(1.03), an accent-color border (--brand), a box-shadow: 0 20px 40px -20px var(--brand)/0.35, and a small "Most popular" ribbon in the top-right corner via position: absolute; top: -12px; right: 24px. Baymard Institute's 2024 pricing-page study across 200+ SaaS sites found the elevated-Pro-card pattern outperforms flat 50/50 by 18% conversion on average, because the visual asymmetry primes the eye to compare the Pro card AGAINST the Basic card (making the Pro price feel earned rather than default). For three-tier pricing (Free / Pro / Enterprise), the middle-highlighted pattern is standard — but the two-tier side-by-side is what Stripe Billing, Vercel Pro, Linear Business, Notion Plus, Superhuman, Framer, Cursor Pro, Raycast Pro and every other tier-1 SaaS ships. Also: CSS subgrid (Baseline 2024) makes the feature-list rows in both cards align to the same baseline — see the subgrid demo in this pattern for the details. On SaaS pricing content, CPMs in tier-1 markets run 15-45 USD driven by direct competitors bidding on brand-comparison queries.
Do these two-column layouts pass WCAG 2.2 AA, work in React/Vue/Svelte/Astro/Next.js, and hit Core Web Vitals?
Every demo in this gallery is built to the WCAG 2.2 AA baseline and passes zero-violation on axe-core, Deque WAVE, Siteimprove and IBM Equal Access. Concretely: DOM order matches visual order on desktop (WCAG 2.4.3 Focus Order) — the content column always comes first in HTML, then the sidebar, so mobile readers and keyboard users hit primary content before secondary navigation; every interactive element (form input, pricing CTA, sidebar link) has a :focus-visible outline at 2px minimum with 3:1 contrast per WCAG 2.4.13 focus-appearance (the new SC that landed October 2023); prefers-reduced-motion: reduce is honored on every transition (form ring, sidebar hover, pricing card lift); the mobile breakpoint at 768px keeps text at a comfortable reading measure (66-75 characters per line, the Bringhurst standard). Zero JavaScript in any of the 16 demos — CLS is provably zero, LCP is bound only by the browser's rendering pipeline (typically 12-40ms on a mid-tier Android), INP is 0 since there's no JS bundle at all. Framework portability: drop the HTML straight into React (rename class to className and for to htmlFor), Vue (SFC accepts as-is), Svelte or SvelteKit (accepts class and for natively), Astro (as an .astro component with the CSS in a scoped style block), Next.js App Router (as a client or server component — no use client needed for these zero-JS layouts), Remix (any route module), or Solid.js. MIT licensed. Compared to premium alternatives: Tailwind's arbitrary-value grid classes (grid-cols-[1fr_300px]) express the same rules with more bracket noise; shadcn's ResizablePanel primitive is $0 but adds ~8KB for drag-to-resize behavior these demos don't need; Framer Motion's layout-shift primitives are 60KB+ for a use case pure CSS handles.

Related collections

15 CSS Aspect Ratio Demos preview

15 CSS Aspect Ratio Demos

15 hand-coded CSS aspect-ratio demos for video embeds, product galleries, IAB ad slots, native dialogs, and CLS-safe placeholders: 16:9 iframe YouTube embed with click-to-load facade + up-next rail, 21:9 full-screen hero video with min-height/max-height:100svh guardrails + Ken Burns drift, 1:1 Instagram-style square grid with 2×2 feature tile, 4:3 magazine card image cover, 9:16 vertical stories rail (TikTok/Reels/Shorts pattern) with scroll-snap + segment bars, 4:5 apparel product image gallery with radio-driven state + 1:1 thumbnails, 1:1 zoom thumbnail carousel with pointer-tracked --zx/--zy magnifier, prevent-layout-shift placeholder with live PerformanceObserver CLS meter (before/after side-by-side lab), dynamic content fallback with three policies (bend/strict/auto) via :has() toggle, IAB ad banner slots (728×90 leaderboard, 300×250 medium rectangle, 300×600 half-page, 320×50 mobile) with skeletons + container-query mobile swap, responsive modal dialog sized min(92vw, 88svh×16/9, 1080px) with @starting-style animation, responsive OpenStreetMap iframe wrapper with 16:9 → 1:1 container-query narrow swap, media query orientation live HUD + resize:both container-ratio playground, object-fit logo cloud with contain/cover/fill switcher via :has(), and side-by-side padding-top hack (height:0 + padding-top:56.25%) → modern aspect-ratio migration comparison with live ratio picker. 11 truly Pure CSS + 4 with a tiny optional vanilla JS snippet (facade swap, pointer magnifier, CLS meter, native dialog). Every demo is scoped under a unique .car-NN prefix so it drops into any project without CSS collisions, ships prefers-reduced-motion guards, and is framework-agnostic (works as-is in React, Vue, Svelte, Astro, Next.js, Remix, or plain HTML).

6 CSS Bento Grid Layouts preview

6 CSS Bento Grid Layouts

6 production CSS bento grid layouts with 12 hand-coded designs — Apple-style product showcase, SaaS feature value-prop matrix, analytics dashboard overview, creative portfolio, e-commerce category hub, and link-in-bio social hub. Each topic ships 2 sub-variants side-by-side so visitors see both a keynote aesthetic and a paper-doc variant at once. Container queries, CSS Grid, zero dependencies, copy-paste ready.

20 CSS Blog Layouts preview

20 CSS Blog Layouts

20 hand-coded CSS blog and editorial layouts for magazine homepages, news sites, personal archives, newsletter back-issues, recipe and podcast blogs, developer tutorials, and long-form journalism. Covers a magazine homepage with hero plus editor-picks rail, a news homepage with breaking-news ticker, blog archives with sticky year separators, Substack-style issue-numbered archives, recipe card grids with prep-time badges, podcast episode lists with waveforms, long-form articles with scroll-driven reading progress, drop caps and floated pull quotes via first-letter, Medium-style 65ch centred reader layouts, dev tutorials with a sticky code panel beside prose, interview transcripts with alternating speakers, case-study pages with stat counters, video blogs with an episode rail, full-bleed photo essays, news articles with sticky related-stories sidebars, documentation pages with prev/next chapter nav, a standalone blog post card, a scroll-snap category filter bar, an inline newsletter callout that breaks out of the prose column, and a horizontal featured-post rail. 12 are pure CSS with zero JavaScript. Every layout is scoped under a .bl-NN prefix for no-collision pasting, guards prefers-reduced-motion, and ports unchanged to React, Vue, Svelte, Astro, Next.js and Tailwind.

Search CodeFronts

Loading…