Design Cluster
Modern CSS Layout Toolkit: Flexbox, Grid, Container Queries
Five years ago, "I need to center this div" was a punchline. Today, it is two lines of CSS. Layout in CSS has undergone a quiet revolution while nobody was watching. Flexbox handles one-dimensional arrangements. Grid handles two-dimensional arrangements. Container queries let components respond to their container, not the viewport. Logical properties make RTL support free. And clip-path, mask, and aspect-ratio handle the shape effects that used to require SVG or background images.
If your mental model of CSS layout is still "floats and negative margins," the modern toolkit is going to feel like cheating. This guide walks through the pieces, explains when to reach for each one, and shows the playgrounds that cut the learning curve from weeks to days.
Flexbox: one dimension at a time
Flexbox arranges items along a single axis. That is the whole mental model. You declare a flex container and its items line up horizontally (or vertically, or along any axis you choose) with rules for how they grow, shrink, align, and wrap. Flexbox is wrong for two-dimensional layouts — a photo gallery with equal rows and columns is not a flex problem — but it is the right answer for toolbars, navigation, cards in a row, form field groups, and any other single-axis arrangement.
The three most confusing properties are flex-grow, flex-shrink, and flex-basis. Flex-basis is the starting size of the item before growing or shrinking. Flex-grow is the proportion of leftover space the item takes (0 = none, 1 = its share of whatever is left). Flex-shrink is the proportion of overflow it gives up. Most real-world flex items want one of three shorthand values: flex: 1 (grow to fill), flex: 0 0 auto (do not grow or shrink, keep content size), or flex: 0 1 200px (start at 200px, shrink if needed, do not grow).
The fastest path to flex literacy is a playground. CSS Flexbox Generator gives you sliders and toggles for every flex property, live-previews the result, and copies the CSS. The MDN Flexbox guide is the canonical reference once you are past the "what is this" phase.
Grid: two dimensions at once
Grid is Flexbox's two-dimensional sibling. You declare rows, columns, and gaps on a container, and items slot into the tracks. Grid shines anywhere you need to align across rows and columns at the same time — photo galleries, dashboards, magazine-style layouts, anything with "this needs to line up with that."
The power move in Grid is grid-template-areas, which lets you name regions and reference them by name:
.layout {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 60px 1fr auto;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
This is a full application shell in 12 lines and no media queries. To make it responsive, redeclare the template areas inside a media query or container query and the layout snaps to a different shape. The ASCII-art nature of grid-template-areas makes it self-documenting — the structure of the layout is visible in the CSS itself.
For building grid layouts visually before writing the CSS, CSS Grid Generator handles the track sizing and area naming in a drag-and-drop interface. Pair it with YAML Validator if you are keeping design tokens in YAML and generating CSS variables from them; the design-token flow is underrated for teams maintaining a design system.
Container queries: component-local responsiveness
Container queries are the missing piece of responsive design and they finally shipped across browsers. Instead of "when the viewport is narrower than 768px, restyle this card," you can now say "when this card's container is narrower than 400px, restyle the card." The card adapts to wherever it is placed, not to where the browser is.
.card-container {
container-type: inline-size;
container-name: card;
}
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
The first block declares a container. The second block is a container query that applies when the container is at least 400px wide. The card becomes a two-column layout once it has room, regardless of what the viewport is doing. This is how you write component libraries that work in every context without conditionals in your JavaScript. The MDN container queries guide covers the full syntax.
Clip-path, mask, and shape effects
CSS shapes used to mean "download an SVG or slice an image." Now the browser can clip elements to any polygon, ellipse, or arbitrary SVG path directly:
.card {
clip-path: polygon(0 0, 100% 0, 100% 80%, 90% 100%, 0 100%);
}
That produces a card with a corner "cut" at the bottom right — the kind of decorative shape that used to require an absolutely positioned image or a complex SVG. For authoring the exact polygon coordinates without doing the math by hand, CSS Clip-Path Generator has a visual editor that lets you drag points around and copies the resulting CSS.
Masks are the more powerful cousin: instead of clipping to a shape, you apply a grayscale image as a mask where black is transparent and white is opaque. The CSS mask property lets you combine gradients and images to produce faded-edge effects, text reveals, and decorative overlays. See the W3C CSS Masking Module for the canonical spec.
Filters for adjustment without editing assets
The CSS filter property applies image processing at render time. Blur, brightness, contrast, grayscale, hue-rotate, and drop-shadow are the most useful. They stack, they composite cheaply, and they save you from shipping multiple versions of the same asset.
.muted-photo { filter: grayscale(0.6) brightness(0.9); }
.hover-photo:hover { filter: saturate(1.2) brightness(1.05); }
The filters cascade and animate smoothly, so interactive effects like "desaturate on hover" are one line instead of a preprocessing pipeline. CSS Filter Generator lets you dial in each filter component with a live preview so you can find the right combination before committing.
Common traps
Reaching for Grid when Flexbox is enough
Grid is more powerful but also more to think about. If the layout is truly one-dimensional, Flexbox is simpler and cleaner. Save Grid for layouts where alignment across rows and columns genuinely matters.
Forgetting min-width: 0 on flex items
Flex items have a default minimum size of their content, which means long text can blow out the layout. Setting min-width: 0 on flex items allows them to shrink below their content size, which is usually what you actually want.
Container queries without declaring a container
A container query does nothing unless some ancestor has container-type set. If your media-like queries seem to be ignored, check that you have declared a container somewhere above them.
Ignoring logical properties
Use padding-inline, padding-block, margin-inline-start, etc. instead of padding-left, padding-top. Your layout automatically supports RTL languages without a rewrite, and the intent is clearer — "inline padding" is about text flow, not screen orientation.
Adjacent tools worth bookmarking
More CSS and design helpers that pair with layout work: Color Gradient Generator for filling grid cells with gradients, Color Palette Generator for consistent tokens across your layout components, Contrast Ratio Checker for verifying text on layered backgrounds, and Color Picker when you need to sample an exact value from a design mockup.
Related pillar guide
This cluster post is part of the design and image track. For the broader foundation on visual optimization and design, see Image Optimization: The Complete Guide.
FAQ
Flexbox or Grid for a photo gallery?
Grid. A photo gallery needs alignment across rows as well as within rows — if the photos are different sizes, Flexbox will leave ragged edges unless you manually size everything. Grid handles it with grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)).
When should I use container queries instead of media queries?
Any time the component's layout depends on how much space it has, not on the viewport width. Cards in a grid, widgets in a dashboard, and any reusable component that appears in multiple contexts benefit from container queries.
Is CSS Subgrid supported yet?
Yes, in all major browsers as of 2024. Subgrid lets a nested grid inherit the parent's track sizes, which is exactly what you want for aligning a column of cards where each card has its own internal grid.
Should I use aspect-ratio instead of the padding hack?
Yes. aspect-ratio: 16 / 9 is cleaner, more readable, and works everywhere. The padding-bottom hack is obsolete.
How do I align two items vertically in Flexbox?
Set align-items: center on the flex container. The items align along the cross axis. If your flex container is flex-direction: row, that is vertical centering. If it is flex-direction: column, it is horizontal centering. The cross axis is always perpendicular to the main axis.
Closing thought
CSS layout is a completed problem now. The vocabulary is rich, the browsers all ship the same features, and the playgrounds let you explore each one in minutes. Every "I can't figure out how to make this layout work" puzzle in 2026 has an answer in two or three lines of modern CSS, usually involving one of the four primitives above. Trust the toolkit.