// LOADING
// LOADING
// LOADING_ARTICLE
Grid and Flexbox are both CSS layout mechanisms, both widely supported, and both capable of producing similar-looking results in many situations. The question isn't which is better — it's which fits the problem. Using Grid where you need Flexbox (or vice versa) produces code that fights the browser instead of working with it.
Flexbox is a one-dimensional layout system. It arranges items along a single axis — either a row or a column — and lets items grow, shrink, and wrap. The children influence each other's sizes.
Grid is a two-dimensional layout system. You define rows and columns explicitly, then place items into cells. Items can span multiple rows and columns. The parent controls the layout, not the children.
This single distinction resolves most "which do I use?" questions before you write a line of CSS.
Use Flexbox when you're arranging items along a line and want them to respond naturally to available space:
css/* Classic: space items in a nav bar */ .navbar { display: flex; justify-content: space-between; align-items: center; gap: 1rem; } /* Wrapping tag list */ .tags { display: flex; flex-wrap: wrap; gap: 0.5rem; }
Flex is content-driven. The items tell the container how much space they need, and the container distributes it. This is ideal when item sizes vary and you want natural flow.
Use Grid when you're designing a layout with explicit rows and columns:
css/* Two-column layout: sidebar + main */ .layout { display: grid; grid-template-columns: 260px 1fr; grid-template-rows: auto 1fr auto; min-height: 100vh; gap: 1.5rem; } /* Responsive card grid */ .card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.5rem; }
The auto-fill + minmax pattern is one of Grid's most powerful features — it creates a responsive multi-column layout without a single media query. Cards flow into as many columns as fit at the current container width.
Grid's placement API is where it really diverges from Flexbox. You can explicitly position items and make them span multiple tracks:
css.hero-banner { display: grid; grid-template-columns: repeat(12, 1fr); grid-template-rows: auto; } .hero-image { grid-column: 1 / 8; /* span columns 1–7 */ grid-row: 1 / 3; /* span rows 1–2 */ } .hero-text { grid-column: 8 / 13; /* span columns 8–12 */ }
Achieving this kind of placement with Flexbox requires nested containers, absolute positioning, or negative margins — all hacks. Grid makes it declarative.
Real layouts use both. Grid for the macro layout (page structure, section grids), Flexbox for the micro layout (items within a card, navigation links, button groups).
tsx// React component using both function BlogCard({ post }: { post: Post }) { return ( // Grid: card content laid out in rows <article style={{ display: 'grid', gridTemplateRows: 'auto 1fr auto', gap: '0.75rem' }}> <img src={post.cover} alt={post.title} /> <div> <h2>{post.title}</h2> <p>{post.excerpt}</p> </div> {/* Flexbox: row of tags + read time */} <footer style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> <div style={{ display: 'flex', gap: '0.5rem' }}> {post.tags.map(tag => <span key={tag}>{tag}</span>)} </div> <span>{post.readTime} min read</span> </footer> </article> ); }
Using nested Flexbox to create a grid: Three nested flex containers to make a 3-column layout is the most common over-engineering. One display: grid with grid-template-columns: repeat(3, 1fr) replaces all of it.
Using Grid for a simple centered element: display: grid; place-items: center; works but display: flex; justify-content: center; align-items: center; is equally clear and doesn't carry the mental overhead of a grid context.
Forgetting align-items default differences: Flexbox's default align-items is stretch. Grid's default is also stretch. Both will stretch children to fill the cross-axis unless you override it — something that surprises developers coming from float-based layouts.
If you're working in a Next.js project with Tailwind CSS, the utility classes map directly to these properties: flex, grid, grid-cols-*, gap-*, justify-*, items-*. The mental model is the same — choose Grid or Flex based on the layout dimension, then pick the utilities that express it. For responsive layout patterns, this works well alongside the component-level approach covered in CSS Container Queries: Responsive Design Beyond Media Queries.
For a real-world example of how these layout strategies come together in a production project, take a look at the work on /projects.
The practical rule: if you're thinking about a line of items, use Flexbox. If you're thinking about a grid of rows and columns, use Grid. Both are production-ready, both are essential, and mixing them is normal and correct. The choice is about matching the tool to the layout dimension — not about which is newer or more impressive.