CSS Flexbox and Grid: The Complete Guide for Modern Layouts
Flexbox and Grid are the two layout systems that replaced floats, tables, and positioning hacks in modern CSS. Every frontend developer needs to know both β and more importantly, needs to know when to use each one.
This guide covers both systems with practical examples and real-world layout patterns.
Flexbox vs Grid: When to Use Each
Flexbox is one-dimensional β it lays out items in a row OR a column. Grid is two-dimensional β it controls rows AND columns simultaneously.
A simple rule of thumb:
- Use Flexbox for components: navigation bars, button groups, card headers, aligning items in a single direction
- Use Grid for page layouts and complex two-dimensional arrangements
In practice, you will use both β Grid for the page structure, Flexbox for the components inside.
CSS Flexbox
The Flex Container
Apply display: flex to a parent element to make its children flex items:
css.container { display: flex; }
By default, flex items sit in a row and shrink to fit their content.
flex-direction
Controls the main axis direction:
css.container { flex-direction: row; /* default β left to right */ flex-direction: row-reverse; /* right to left */ flex-direction: column; /* top to bottom */ flex-direction: column-reverse; /* bottom to top */ }
justify-content
Aligns items along the main axis (horizontal for row, vertical for column):
css.container { justify-content: flex-start; /* default β pack to start */ justify-content: flex-end; /* pack to end */ justify-content: center; /* center items */ justify-content: space-between; /* equal gaps, no edge gap */ justify-content: space-around; /* equal gaps including edges */ justify-content: space-evenly; /* truly equal gaps everywhere */ }
align-items
Aligns items along the cross axis (vertical for row, horizontal for column):
css.container { align-items: stretch; /* default β fill cross axis */ align-items: flex-start; /* align to start */ align-items: flex-end; /* align to end */ align-items: center; /* center vertically */ align-items: baseline; /* align text baselines */ }
The Classic Centering Solution
Before Flexbox, centering an element both horizontally and vertically was painful. Now it is two lines:
css.container { display: flex; justify-content: center; align-items: center; }
flex-wrap
By default, flex items try to fit on one line. flex-wrap: wrap lets them wrap to new lines:
css.container { display: flex; flex-wrap: wrap; gap: 16px; } .item { flex: 1 1 200px; /* grow, shrink, minimum 200px wide */ }
This pattern creates a responsive grid-like layout without media queries β items wrap when they run out of space.
Flex Item Properties
These go on the children, not the container:
css.item { flex-grow: 1; /* how much to grow relative to siblings */ flex-shrink: 1; /* how much to shrink if needed */ flex-basis: 0; /* initial size before grow/shrink */ /* shorthand */ flex: 1; /* flex-grow: 1; flex-shrink: 1; flex-basis: 0 */ flex: 0 0 200px; /* fixed 200px, do not grow or shrink */ } .item-special { align-self: flex-end; /* override align-items for this item only */ order: -1; /* change visual order without changing HTML */ }
Common Flexbox Layout: Navigation Bar
css.navbar { display: flex; justify-content: space-between; align-items: center; padding: 0 24px; height: 60px; } .nav-logo { flex: 0 0 auto; } .nav-links { display: flex; gap: 24px; list-style: none; } .nav-actions { display: flex; gap: 12px; align-items: center; }
CSS Grid
The Grid Container
css.container { display: grid; }
Defining Columns and Rows
css.container { display: grid; grid-template-columns: 200px 1fr 1fr; /* fixed + two flexible columns */ grid-template-rows: auto 1fr auto; /* header, main, footer */ gap: 24px; }
The fr unit means "fraction of available space." 1fr 1fr 1fr creates three equal columns.
The repeat() Function
css.grid { /* Three equal columns */ grid-template-columns: repeat(3, 1fr); /* Responsive columns β as many as fit, minimum 250px each */ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
auto-fill with minmax is one of the most powerful CSS patterns β a fully responsive grid with no media queries.
Placing Items
By default, Grid auto-places items. You can also place them explicitly:
css.item { grid-column: 1 / 3; /* span from column line 1 to 3 */ grid-row: 1 / 2; /* row line 1 to 2 */ /* shorthand */ grid-column: 1 / span 2; /* start at 1, span 2 columns */ grid-column: 2 / -1; /* from column 2 to the last line */ }
Grid Template Areas
Named areas make complex layouts readable:
css.page { display: grid; grid-template-areas: "header header header" "sidebar main main" "footer footer footer"; grid-template-columns: 250px 1fr 1fr; grid-template-rows: 60px 1fr 60px; min-height: 100vh; } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .main { grid-area: main; } .footer { grid-area: footer; }
This defines the entire page layout visually in CSS. Changing layouts for different screen sizes is as simple as redefining the grid-template-areas.
Alignment in Grid
Grid has both justify (inline/row axis) and align (block/column axis) for both the container and individual items:
css.container { justify-items: center; /* align all items horizontally */ align-items: center; /* align all items vertically */ justify-content: space-between; /* distribute columns */ align-content: space-between; /* distribute rows */ } .item { justify-self: end; /* override for this item horizontally */ align-self: start; /* override for this item vertically */ }
Responsive Layout Patterns
Card Grid (no media queries needed)
css.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 24px; }
Cards automatically reflow from 1 to 2 to 3+ columns as the viewport grows.
Holy Grail Layout
css.page { display: grid; grid-template: "header" 60px "main" 1fr "footer" 60px / 1fr; min-height: 100vh; } @media (min-width: 768px) { .page { grid-template: "header header" 60px "sidebar main" 1fr "footer footer" 60px / 240px 1fr; } }
Sidebar Layout with Flexbox
css.layout { display: flex; min-height: 100vh; } .sidebar { flex: 0 0 260px; overflow-y: auto; } .content { flex: 1; overflow-y: auto; padding: 24px; }
Common Mistakes
Using Grid for everything β Flexbox is simpler and better for one-dimensional layouts like navbars, button rows, and form fields.
Forgetting gap β Use gap instead of margins on flex/grid items. It is cleaner and does not add space on the outer edges.
Overcomplicating with explicit placement β Grid auto-placement is smart. Only place items explicitly when you need to break out of the natural flow.
Not using minmax β minmax(0, 1fr) prevents overflow in grid cells when content is longer than expected.
Common Interview Questions
Q: What is the difference between justify-content and align-items in Flexbox?
justify-content distributes items along the main axis (horizontal for row, vertical for column). align-items aligns items along the cross axis (perpendicular to the main axis).
Q: What does flex: 1 mean?
It is shorthand for
flex-grow: 1; flex-shrink: 1; flex-basis: 0Q: How do you make a responsive grid without media queries?
cssgrid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
Q: What is the difference between auto-fill and auto-fit?
Both create as many columns as fit. auto-fill keeps empty columns in the grid (affecting alignment). auto-fit collapses empty columns β items stretch to fill the container.
Practice CSS on Froquiz
Layout skills are tested in every frontend interview. Explore our quizzes on Froquiz to sharpen your CSS, JavaScript, and React knowledge.
Summary
- Flexbox β one-dimensional layouts (row or column); use for components
- Grid β two-dimensional layouts; use for page structure and complex arrangements
justify-contentcontrols main axis distribution;align-itemscontrols cross axis alignmentrepeat(auto-fill, minmax(250px, 1fr))β responsive grid with no media queriesgrid-template-areasβ name regions for readable layout definitionsgapis cleaner than margins between flex/grid items- Use both together: Grid for page structure, Flexbox for components inside cells