Introduction
When I started building websites, one of the things that took me some time to understand was how to properly arrange elements on a page.
At first, I used margins, padding, position, and sometimes even unnecessary HTML elements just to get things positioned where I wanted them.
It worked, but the CSS quickly became difficult to maintain.
Then I started learning CSS Flexbox and CSS Grid.
These two CSS layout systems completely changed the way I approached website layouts.
Today, I use Flexbox and Grid instead of trying to manually position everything.
In this guide, I will explain both from the beginning, including:
- What Flexbox is
- Flex container and flex items
- Main axis and cross axis
- Important Flexbox properties
- Creating rows and columns
- Alignment and spacing
- Wrapping elements
- What CSS Grid is
- Grid rows and columns
- Grid gaps
- Grid templates
- Spanning multiple columns and rows
- Responsive layouts
- Flexbox vs Grid
- When I use Flexbox and when I use Grid
- Practical examples
What Is CSS Flexbox?
Flexbox, short for Flexible Box Layout, is a CSS layout system designed mainly for arranging elements along one dimension.
That means I can primarily arrange elements:
- Horizontally in a row
- Vertically in a column
For example:
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
I can turn the parent into a flex container:
.container {
display: flex;
}
By default, the children are placed in a row.
Visually, it becomes something like:
One Two Three
This is one of the simplest uses of Flexbox.
Flex Container and Flex Items
There are two important terms I need to understand.
Flex Container
The element where I write:
display: flex;
is called the flex container.
For example:
.container {
display: flex;
}
Here, .container is the flex container.
Flex Items
The direct children of the flex container are called flex items.
For example:
<div class="container">
<div>One</div>
<div>Two</div>
<div>Three</div>
</div>
The three inner <div> elements are flex items.
An important point is that Flexbox primarily controls the direct children of the flex container.
The display: flex Property
Everything starts with:
.container {
display: flex;
}
Without this, the container behaves normally.
With it, its direct children become flex items.
For example:
.container {
display: flex;
gap: 20px;
}
Now the items will be arranged next to each other with a 20px gap.
Understanding the Main Axis and Cross Axis
This is one of the most important concepts in Flexbox.
When I started learning Flexbox, I initially focused only on properties like justify-content and align-items.
Later I realized that understanding the axes makes these properties much easier.
Flexbox has two axes:
Main Axis
Cross Axis
By default, the main axis is horizontal.
Main Axis
-------------------------------->
[ One ] [ Two ] [ Three ]
|
|
v
Cross Axis
So when:
.container {
display: flex;
}
the main axis goes from left to right.
But if I change the direction:
.container {
display: flex;
flex-direction: column;
}
the main axis becomes vertical.
[ One ]
[ Two ]
[ Three ]
This is important because justify-content works along the main axis, while align-items works along the cross axis.
flex-direction
The flex-direction property controls the direction of flex items.
There are four main values:
flex-direction: row;
flex-direction: row-reverse;
flex-direction: column;
flex-direction: column-reverse;
Row
This is the default.
.container {
display: flex;
flex-direction: row;
}
Result:
One Two Three
Row Reverse
.container {
display: flex;
flex-direction: row-reverse;
}
The order is reversed:
Three Two One
Column
.container {
display: flex;
flex-direction: column;
}
Result:
One
Two
Three
Column Reverse
.container {
display: flex;
flex-direction: column-reverse;
}
The order becomes:
Three
Two
One
justify-content
I use justify-content to control how flex items are positioned along the main axis.
For example:
.container {
display: flex;
justify-content: center;
}
This centers the items along the main axis.
Some commonly used values are:
justify-content: flex-start;
justify-content: center;
justify-content: flex-end;
justify-content: space-between;
justify-content: space-around;
justify-content: space-evenly;
flex-start
.container {
display: flex;
justify-content: flex-start;
}
Items stay at the beginning.
One Two Three
center
.container {
display: flex;
justify-content: center;
}
Items move to the center.
One Two Three
flex-end
.container {
display: flex;
justify-content: flex-end;
}
Items move toward the end.
One Two Three
space-between
.container {
display: flex;
justify-content: space-between;
}
The first item goes to the beginning and the last item goes to the end.
One Two Three
This is very useful for navigation bars.
space-around
.container {
display: flex;
justify-content: space-around;
}
Space is distributed around the items.
space-evenly
.container {
display: flex;
justify-content: space-evenly;
}
The available space is distributed evenly.
align-items
align-items controls alignment along the cross axis.
For example:
.container {
display: flex;
align-items: center;
}
If the flex direction is a row, this generally means vertical alignment.
This is extremely useful when I want to vertically align items.
For example:
.navbar {
display: flex;
align-items: center;
}
Now the logo, links, and buttons can be vertically aligned.
Common values include:
align-items: flex-start;
align-items: center;
align-items: flex-end;
align-items: stretch;
Centering an Element With Flexbox
One of my favorite simple Flexbox tricks is centering something both horizontally and vertically.
.container {
display: flex;
justify-content: center;
align-items: center;
}
If the container has a height:
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
I can place the child right in the center of the viewport.
For example:
<div class="container">
<button>Login</button>
</div>
This is much cleaner than trying to calculate margins manually.
gap
The gap property is one of the properties I use frequently with Flexbox.
.container {
display: flex;
gap: 20px;
}
It creates space between flex items.
For example:
One 20px Two 20px Three
I can also use:
row-gap: 20px;
column-gap: 30px;
Or simply:
gap: 20px 30px;
The first value controls row spacing and the second controls column spacing.
flex-wrap
By default, flex items try to stay on one line.
Sometimes there isn’t enough space.
I can allow them to move to another line using:
.container {
display: flex;
flex-wrap: wrap;
}
For example:
One Two Three Four
Five Six Seven
This is particularly useful for responsive cards.
Building a Responsive Card Layout With Flexbox
Suppose I have several cards:
<div class="cards">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
<div class="card">Card 4</div>
</div>
I can write:
.cards {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 1 1 250px;
}
Now the cards can automatically wrap when the available width becomes smaller.
This is a very practical Flexbox pattern.
The flex Property
The flex shorthand controls how a flex item grows and shrinks.
For example:
.card {
flex: 1;
}
If multiple items have:
flex: 1;
they can share the available space.
For example:
<div class="container">
<div class="box">One</div>
<div class="box">Two</div>
<div class="box">Three</div>
</div>
.box {
flex: 1;
}
The three boxes can occupy equal portions of the available space.
flex-grow
This controls how much a flex item can grow relative to other items.
.first {
flex-grow: 2;
}
.second {
flex-grow: 1;
}
The first item can receive twice as much additional space as the second.
flex-shrink
This controls how much an item can shrink when there isn’t enough space.
.box {
flex-shrink: 1;
}
This is the default behavior.
flex-basis
flex-basis defines the initial size of a flex item along the main axis.
.card {
flex-basis: 250px;
}
For practical layouts, I often see combinations like:
.card {
flex: 1 1 250px;
}
This means:
grow: 1
shrink: 1
basis: 250px
align-self
Sometimes I don’t want to change the alignment of every flex item.
I can override the alignment for one particular item using align-self.
.special {
align-self: flex-end;
}
For example:
<div class="container">
<div>One</div>
<div class="special">Two</div>
<div>Three</div>
</div>
Only the special item receives the different cross-axis alignment.
order
Flexbox also allows me to change the visual order of items.
.first {
order: 2;
}
.second {
order: 1;
}
The visual order can change without changing the HTML order.
I use this carefully because the HTML order can matter for accessibility and keyboard navigation.
What Is CSS Grid?
Now let’s move to CSS Grid.
While Flexbox is mainly designed for one-dimensional layouts, CSS Grid is designed for two-dimensional layouts.
Grid allows me to work with:
Rows
Columns
For example:
+---------+---------+---------+
| | | |
| 1 | 2 | 3 |
| | | |
+---------+---------+---------+
| | | |
| 4 | 5 | 6 |
| | | |
+---------+---------+---------+
This is where Grid becomes extremely powerful.
Creating a CSS Grid
Just like Flexbox, I start by changing the display property:
.container {
display: grid;
}
But I normally also define columns.
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}
This creates three equal columns.
Understanding fr
The fr unit means a fraction of the available space.
For example:
grid-template-columns: 1fr 1fr 1fr;
means three equal columns.
| 1fr | 1fr | 1fr |
I can also create different proportions:
grid-template-columns: 2fr 1fr;
This gives the first column twice the available share of the second.
| 2fr | 1fr |
Creating Grid Rows
I can explicitly define rows as well.
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 100px 200px;
}
This creates two columns and two rows.
Grid Gap
Just like Flexbox, Grid supports gap.
.container {
display: grid;
gap: 20px;
}
I can also use:
row-gap: 20px;
column-gap: 30px;
Or:
gap: 20px 30px;
A Simple CSS Grid Example
HTML:
<div class="grid">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
</div>
CSS:
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
The result is:
+-------+-------+-------+
| One | Two | Three |
+-------+-------+-------+
| Four | Five | Six |
+-------+-------+-------+
The repeat() Function
Instead of writing:
grid-template-columns: 1fr 1fr 1fr;
I can write:
grid-template-columns: repeat(3, 1fr);
This means:
Create 3 columns, each taking 1 fraction of the available space.
For five equal columns:
grid-template-columns: repeat(5, 1fr);
This makes the CSS easier to read.
grid-column
Grid allows me to control where an item starts and ends.
For example:
.featured {
grid-column: span 2;
}
This makes the item span two columns.
Example:
+---------+---------+---------+
| | | |
| Featured | Item 2 |
| | | |
+---------+---------+---------+
This is useful for dashboards, galleries, and magazine-style layouts.
grid-row
Similarly, I can make an item span multiple rows.
.featured {
grid-row: span 2;
}
This allows one item to become taller than the others.
Explicit Grid Placement
I can also specify exact column positions.
.item {
grid-column: 1 / 3;
}
This means the item starts at grid line 1 and ends at grid line 3.
Therefore, it occupies two columns.
I can do the same with rows:
.item {
grid-row: 1 / 3;
}
This makes it occupy two rows.
grid-template-areas
One of the Grid features I particularly like is grid-template-areas.
It allows me to visually describe a page layout.
For example:
.layout {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
}
Then I assign areas:
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.main {
grid-area: main;
}
.footer {
grid-area: footer;
}
This makes the layout very easy to understand.
The structure is essentially:
+----------+----------------+
| Sidebar | Header |
| +----------------+
| | Main |
| | |
| +----------------+
| | Footer |
+----------+----------------+
For larger page layouts, this can be much easier to maintain than manually positioning every element.
Responsive CSS Grid
One of the most useful Grid techniques is creating responsive columns.
For example:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}
This is a very powerful pattern.
Let’s break it down.
auto-fit
The browser tries to fit as many columns as possible.
minmax(250px, 1fr)
Each column should ideally be at least 250px wide, but it can grow to use available space.
This means I can create a responsive card layout without necessarily writing multiple media queries.
auto-fit vs auto-fill
You may also see:
repeat(auto-fill, minmax(250px, 1fr))
and:
repeat(auto-fit, minmax(250px, 1fr))
They are similar, but their behavior differs when there is extra available space and fewer items than the possible number of tracks.
For many common responsive card layouts, I prefer:
repeat(auto-fit, minmax(250px, 1fr))
because the existing cards can expand to use the available space.
Aligning Items in CSS Grid
Grid also provides alignment properties.
For example:
.container {
display: grid;
align-items: center;
}
I can also use:
justify-items: center;
And:
place-items: center;
For example:
.container {
display: grid;
place-items: center;
}
This is a convenient way to center grid items.
justify-content and align-content in Grid
Grid also supports:
justify-content
align-content
These properties control how the entire grid is positioned when there is extra space inside the grid container.
For example:
.container {
display: grid;
justify-content: center;
}
The grid itself can be centered horizontally.
This is slightly different from justify-items, which controls the alignment of items inside their grid areas.
Flexbox vs CSS Grid
This is one of the most common questions beginners ask.
Should I use Flexbox or Grid?
My simple rule is:
If I am primarily working in one direction, I think about Flexbox first. If I am controlling rows and columns together, I think about Grid first.
Here’s a simple comparison:
| Feature | Flexbox | CSS Grid |
|---|---|---|
| Main purpose | One-dimensional layout | Two-dimensional layout |
| Rows | Yes | Yes |
| Columns | Yes | Yes |
| Row + column control | Limited | Excellent |
| Navigation bars | Excellent | Possible |
| Simple alignment | Excellent | Excellent |
| Card layouts | Excellent | Excellent |
| Complex page layouts | Possible | Excellent |
| Dashboard layouts | Possible | Excellent |
| Responsive layouts | Excellent | Excellent |
When I Use Flexbox
I generally think about Flexbox for smaller layout relationships.
For example:
Navigation
.navbar {
display: flex;
align-items: center;
justify-content: space-between;
}
Button groups
.buttons {
display: flex;
gap: 10px;
}
Centering
.container {
display: flex;
justify-content: center;
align-items: center;
}
Horizontal cards
.cards {
display: flex;
gap: 20px;
}
Flexbox is excellent when the layout is primarily concerned with a single direction.
When I Use CSS Grid
I generally think about Grid when the layout has a clear row and column structure.
For example:
Dashboard
.dashboard {
display: grid;
grid-template-columns: 250px 1fr;
}
Image gallery
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
}
Main website layout
.layout {
display: grid;
grid-template-columns: 250px 1fr;
}
Responsive card grid
.cards {
display: grid;
grid-template-columns: repeat(
auto-fit,
minmax(250px, 1fr)
);
gap: 20px;
}
Grid is especially useful when I want stronger control over rows and columns.
Can I Use Flexbox and Grid Together?
Absolutely.
I don’t consider Flexbox and Grid competitors.
In real projects, I often use both.
For example, I might use Grid for the overall page:
.page {
display: grid;
grid-template-columns: 250px 1fr;
}
Then use Flexbox inside the navigation:
.nav {
display: flex;
flex-direction: column;
gap: 10px;
}
And use another Flexbox layout inside a card:
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
This combination is completely normal.
A Practical Responsive Website Layout
Let’s imagine that I am building a simple website with:
- Header
- Sidebar
- Main content
- Cards
I could use Grid for the overall structure.
<div class="layout">
<header class="header">
My Website
</header>
<aside class="sidebar">
Navigation
</aside>
<main class="main">
<div class="cards">
<div class="card">Card 1</div>
<div class="card">Card 2</div>
<div class="card">Card 3</div>
</div>
</main>
</div>
CSS:
.layout {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-areas:
"sidebar header"
"sidebar main";
}
.header {
grid-area: header;
}
.sidebar {
grid-area: sidebar;
}
.main {
grid-area: main;
}
.cards {
display: grid;
grid-template-columns: repeat(
auto-fit,
minmax(220px, 1fr)
);
gap: 20px;
}
Here I am using Grid at two different levels.
The outer Grid controls the page structure.
The inner Grid controls the cards.
I could then use Flexbox inside individual cards.
This is how these layout systems can work together.
Flexbox and Grid Are Not Replacements for Everything
Although Flexbox and Grid are powerful, I don’t try to use them for every CSS problem.
I still use:
margin
padding
position
width
height
max-width
min-width
when appropriate.
For example, if I simply need to add space inside a card:
.card {
padding: 20px;
}
I don’t need Flexbox or Grid.
The goal is not to use the newest CSS feature everywhere.
The goal is to choose the simplest tool that solves the problem.
Common Mistakes Beginners Make
1. Using position: absolute for everything
When I was learning CSS, it was tempting to use:
position: absolute;
whenever something didn’t align properly.
But this often creates problems when the screen size changes.
For normal layouts, I prefer Flexbox or Grid.
2. Not understanding the Flexbox axes
If justify-content and align-items seem confusing, I recommend first asking:
What is my main axis?
If I have:
flex-direction: row;
the main axis is horizontal.
If I have:
flex-direction: column;
the main axis is vertical.
Once I understand that, these properties become much easier.
3. Using too many media queries
Sometimes I see developers manually define a different number of columns for every screen size.
For example:
@media (...) {
...
}
@media (...) {
...
}
@media (...) {
...
}
Media queries are useful, but Grid’s:
repeat(auto-fit, minmax(250px, 1fr))
can solve many responsive card layouts with much less CSS.
4. Forgetting gap
Instead of adding margins to every child:
.card {
margin-right: 20px;
}
I can often use:
.container {
display: flex;
gap: 20px;
}
or:
.container {
display: grid;
gap: 20px;
}
I find gap much cleaner for spacing between layout items.
Flexbox Cheat Sheet
Here are the Flexbox properties I recommend remembering:
display: flex;
flex-direction: row;
flex-direction: column;
justify-content: center;
align-items: center;
flex-wrap: wrap;
gap: 20px;
flex: 1;
flex-grow: 1;
flex-shrink: 1;
flex-basis: 250px;
align-self: center;
order: 1;
The most important ones for beginners are:
display: flex
flex-direction
justify-content
align-items
flex-wrap
gap
flex
CSS Grid Cheat Sheet
The most useful Grid properties include:
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 100px 200px;
gap: 20px;
grid-column: span 2;
grid-row: span 2;
grid-template-areas:
"header header"
"sidebar main";
grid-area: main;
place-items: center;
For responsive cards, remember this pattern:
grid-template-columns: repeat(
auto-fit,
minmax(250px, 1fr)
);
It is one of the most useful Grid patterns I use.
What Should I Learn First?
If you are completely new to CSS layouts, I recommend this order:
Step 1: Understand normal CSS flow
Learn:
Block elements
Inline elements
Margin
Padding
Width
Height
Step 2: Learn Flexbox
Focus on:
display: flex
flex-direction
justify-content
align-items
gap
flex-wrap
flex
Step 3: Learn CSS Grid
Focus on:
display: grid
grid-template-columns
grid-template-rows
gap
fr
repeat()
minmax()
grid-column
grid-row
grid-template-areas
Step 4: Build real layouts
Try building:
Navigation bar
Login page
Card layout
Pricing section
Dashboard
Image gallery
Blog layout
Portfolio page
This is where the concepts start becoming natural.
Final Thoughts
For me, Flexbox and Grid are two of the most important CSS concepts to understand after learning basic selectors and properties.
If I need to arrange elements mainly in one direction, I usually think about Flexbox.
If I need to control rows and columns together, I usually think about CSS Grid.
I don’t see them as competing technologies.
They solve slightly different layout problems, and I can use them together in the same project.
If you are learning CSS right now, don’t try to memorize every property.
Start with a small project.
Build a navbar with Flexbox.
Then build a card layout.
Then build a responsive gallery with Grid.
Finally, build an entire page using Grid for the main structure and Flexbox inside individual components.
Once you do that a few times, CSS layouts become much less frustrating because you start thinking in terms of layout systems instead of manually positioning individual elements.






