Build a responsive page shell with CSS Grid and a flex fallback
Use CSS Grid for a two-dimensional page shell, wrap it in @supports, and verify placement with the browser grid overlay.
18 May 2026, 12:26 UTC

Goal
Build a page shell with header, navigation, main content, and footer that uses two-dimensional placement on wide screens and stacks vertically on narrow screens, without JavaScript.
Useful takeaway: start with a flex fallback, enable CSS Grid only inside @supports, define tracks with fixed and fractional units, and verify with the grid overlay before publishing.
Prerequisites
- A stylesheet linked to the page.
- One container element with direct children for header, navigation, main content, and footer.
- A modern evergreen browser. CSS Grid Layout Level 1 is a W3C Recommendation and is supported without vendor prefixes in current evergreen browsers; Internet Explorer 11 and older do not support it.
1. Write the fallback layout first
Older browsers should still receive a readable layout. Flexbox is a one-dimensional layout method, so it works well as a fallback for a column stack.
.shell { display: flex; flex-direction: column; gap: 12px; } header, footer { width: 100%; } nav { width: 200px; flex-shrink: 0; } main { flex: 1; min-width: 0; } @media (max-width: 640px) { .shell { flex-direction: column; } nav { width: auto; } }`flex: 1` tells main content to take remaining space. `min-width: 0` prevents a grid or flex child from refusing to shrink below its content size.
2. Add grid rules inside @supports
The @supports rule applies styles only when the browser supports the queried feature. This keeps grid styles away from browsers that cannot use them.
@supports (display: grid) { .shell { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: auto 1fr auto; gap: 12px; min-height: 100vh; } header { grid-row: 1; grid-column: 1 / 3; } nav { grid-row: 2; grid-column: 1; } main { grid-row: 2; grid-column: 2; } footer { grid-row: 3; grid-column: 1 / 3; } nav { width: auto; } @media (max-width: 640px) { .shell { grid-template-columns: 1fr; grid-template-rows: auto auto 1fr auto; } header { grid-row: 1; grid-column: 1; } nav { grid-row: 2; grid-column: 1; } main { grid-row: 3; grid-column: 1; } footer { grid-row: 4; grid-column: 1; } } }`200px` fixes the navigation track. `1fr` is a fractional unit: it takes a share of the free space left after fixed tracks and gaps. `auto` lets a row follow its content height. `gap` inserts space between tracks but not around the container edges.
3. Expected checks
- Reload the page in Chrome, Firefox, Safari, or Edge.
- Open DevTools, choose the Layout pane, and turn on the grid overlay for the shell element.
- Confirm overlay lines match the header, navigation, main, and footer placement.
- Resize the viewport below 640 pixels and confirm the four children stack vertically.
- Press Tab through the page and confirm focus order follows the DOM order: header, navigation, main content, footer.
4. Diagnostic decision
If items overlap, check whether fixed tracks plus gaps exceed the available width. If the tab order jumps, inspect the DOM order before using grid placement to move content visually; grid should not be used to reorder content away from source order without considering keyboard and screen-reader users.
5. Limitations and recovery
- CSS Grid changes visual placement, not source order. A mismatch between visual and DOM order can confuse keyboard navigation and assistive technology.
- Deeply nested grids or a large number of grid lines can increase repaint cost on complex pages.
- Because editing a stylesheet changes file state, keep a backup copy before editing. If the layout breaks, restore the previous stylesheet or comment out the @supports block to return to the flex fallback.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.