Home / Articles / Layout /

layout

Full-bleed layout with CSS Grid

One grid column template replaces the old pattern of opening and closing wrapper divs. Content stays centered, full-bleed sections stretch edge to edge.

The problem with wrappers

The standard content-width pattern — max-width plus margin-inline: auto — works for constraining text, but it traps everything inside a fixed-width box. When a hero image or a background section needs to span the full viewport, you have two bad options: close the wrapper, insert a full-width element, and reopen the wrapper — or use negative margins and 100vw hacks that break on scrollbars.

Both approaches create fragile HTML structure or layout bugs. CSS Grid solves this with a single container that controls all widths.

The grid-based solution

Place a three-column grid on the main content area. The outer columns are flexible gutters. The center column is the content width. All children land in the center column by default.

.content {
  display: grid;
  grid-template-columns:
    1fr
    min(65ch, 100% - 2rem)
    1fr;
}

.content > * {
  grid-column: 2;
}

The min(65ch, 100% - 2rem) expression handles both desktop and mobile: on wide screens, content maxes out at 65 characters; on narrow screens, it takes the full width minus 1rem of padding on each side. No max-width, no margin: auto, no breakpoints needed.

Full-bleed children

Any child that needs to span the entire viewport gets a single override:

.full-bleed {
  grid-column: 1 / -1;
}

That places the element across all three columns — from the first line to the last. Hero images, background sections, and full-width dividers all use this one class. The HTML stays flat — no opening and closing wrappers.

Adding a breakout width

Some designs need a third width — wider than content but not fully edge-to-edge. Extend the grid to five columns with named lines for clarity.

.content {
  display: grid;
  grid-template-columns:
    [full-start] 1fr
    [breakout-start] 1fr
    [content-start] min(60ch, 100% - 2rem) [content-end]
    1fr [breakout-end]
    1fr [full-end];
}

.content > *       { grid-column: content; }
.breakout           { grid-column: breakout; }
.full-bleed         { grid-column: full; }

Named grid lines let you write grid-column: breakout instead of counting column numbers. Feature images, pull quotes, and wide code blocks fit naturally into the breakout track without going full-bleed.

Images and backgrounds in full-bleed

Full-bleed images need to fill their grid column without overflowing. Combine the grid placement with width: 100% and object-fit.

.full-bleed img {
  width: 100%;
  height: 50vh;
  object-fit: cover;
}

.full-bleed-section {
  grid-column: 1 / -1;
  padding: 4rem max(1rem, (100% - 65ch) / 2);
  background: oklch(0.19 0.02 260);
}

The padding expression on full-bleed background sections re-creates the content column's centering within the section itself. Text inside the section aligns with the content column above and below, maintaining visual continuity.

Practical strategy for 2026

CSS Grid has been Baseline since 2017 — Chrome 57+, Safari 10.1+, Firefox 52+. The min() function used in the column template is Baseline from 2020 — Chrome 79+, Safari 11.1+, Firefox 75+. Named grid lines are part of the original Grid specification. This pattern has zero browser compatibility concerns in 2026.

The full-bleed grid pattern eliminates the need for wrapper gymnastics. Define one grid on the content container, and every element — constrained, breakout, or full-bleed — is a single grid-column value.