CSS is a very important web development technology. For a long time, we have used common CSS properties to lay out HTML elements. These properties include floats, inline-block and positional styles. In recent years, we have seen a number of modern CSS techniques that make it easier to create dynamic HTML layouts.
Some of these powerful techniques include CSS Grid and CSS Flexbox. they change the way we layout HTML elements in an incredibly simple way.
When we talk about Flexbox and Grid layouts, we understand the concept of containers and items. In this case, a container is a block of HTML that can contain other HTML elements. An item is an HTML element that can be placed inside a container.
Here’s a simple example of an HTML item inside an HTML container.
<div>
<div>One</div>
<div>Two Two</div>
<div>Three Three Three</div>
<div>Four Four Four Four</div>
<div>Five Five Five Five Five</div>
</div>
In this example, the outermost div
is a container element and the other divs
are container items.
This guide will discuss the differences and relationships between Grid and Flexbox layouts.
What is CSS Flexbox
Flexbox is a layout mode in CSS3. It is a more proficient way of designing, aligning and spreading the space between items in a container to control their arrangement.
With Flexbox, we can arrange items from left to right, right to left, top to bottom, or bottom to top, while controlling the spacing, alignment, and order of the items in the container.
What is CSS Grid
A CSS grid is a collection of styles that allows you to control page layout based on rows and columns. In a grid system, containment elements are used to define a row in the layout.
You then apply the class attribute to the item elements and then span them across the desired number of columns. This allows you to create more complex nested layouts.
CSS Grid and CSS Flexbox
Let’s look at some of the common differences between the two layouts.
One-dimensional versus two-dimensional
Flexbox arranges items in a one-dimensional layout. This can be in rows or columns.
Flexbox layout is best suited for arranging items horizontally or vertically. It is one-dimensional and can only fit into one row or column.
A perfect example of a one-dimensional layout is a header navigation bar or footer.
Let’s see how to implement a header navigation menu using Flexbox.
<div class="nav">
<div>HOME</div>
<div>ABOUT</div>
<div>CONTACT</div>
<div>SIGN UP</div>
<div>SIGN IN</div>
</div>
Design the header with some CSS.
.nav {
display: flex;
background: seagreen;
height: 50px;
align-items: center;
gap: 10px;
}
.nav div {
color: whitesmoke;
margin-left: 20px;
}
Most common header layouts are laid out in one direction, and using Flexbox is easier thanks to its one-dimensional capabilities.
On the other hand, a grid is a two-dimensional layout, which means you can layout items in rows and columns.
An example of a basic 2D layout.
<div class="container">
<div class="item item1"></div>
<div class="item item2"></div>
<div class="item item3"></div>
<div class="item item4"></div>
<div class="item item5"></div>
<div class="item item6"></div>
</div>
.container {
display: grid;
grid-template-columns: 150px 150px 150px;
grid-gap: 1rem;
grid-template-rows: 150px 150px;
}
.item {
background-color: #1EAAFC;
color: #fff;
border: 6px solid #171717;
}
We specify a grid with display: grid
and then identify rows and columns with grid-template-columns
and grid-template-rows
. This defines a two-dimensional layout. In this case, the size of each column and row is 150px
.
Content and Layout
Flexbox is content based, so content comes first. By content first, we mean that it helps you align content and move blocks and items around in the container.
On the other hand, the CSS grid focuses on laying out the external/skeleton layout of the page.
To understand the concept of content vs. layout, let’s go back to the header navigation bar design discussed above. We can target an item within the header (container) and decide where to display it.
To get the core difference, let’s say we want to move the Sign In
and Sign Up
menus to the left, which we can do with Flexbox and CSS Grid.
Use Flexbox.
.nav {
display: flex;
background: seagreen;
height: 50px;
align-items: center;
gap: 1px;
}
.nav div {
margin-left: 20px;
margin-right: 20px;
color: whitesmoke;
}
div:nth-child(4) {
margin-left: auto;
}
We specify a child of the container (the nth child (4) and determine its position). This is what we mean by Flexbox being content-based.
On the other hand, we can achieve the same effect with CSS Grid. The header is one-dimensional and Flexbox is better at this, but we’ll go through an example using CSS Grid to differentiate between layout and content.
.nav {
display: grid;
grid-template-columns: repeat(10, 1fr);
background: seagreen;
height: 50px;
align-items: center;
gap: 1px;
}
.nav div {
margin-left: 20px;
margin-right: 20px;
color: whitesmoke;
}
And the results look pretty much the same.
Note, however, that we specified ten columns, each taking up a fraction of a unit. To drive this point home, let’s look at how the grid layout works internally.
Use a web browser to inspect the parent div
element.
This is fantastic. We can see the grid is divided into ten cells. This is where the layout concept is first applied. First, we define the layout and then we fix the items into the grid cells.
If we were to move the items Sign In
and Sign Up
to the left and apply margin-left: auto
, as we did in the Flexbox example, it wouldn’t work. We can do this with CSS Grid.
.nav {
display: grid;
grid-template-columns: repeat(10, 1fr);
background: seagreen;
height: 50px;
align-items: center;
gap: 1px;
}
.nav div {
margin-left: 20px;
margin-right: 20px;
color: whitesmoke;
}
div:nth-child(4) {
grid-column: 9;
color: rgb(64, 35, 97);
}
div:nth-child(5) {
grid-column: 10;
color: rgb(64, 35, 97);
}
The layout has ten columns. To move these items to the left, first specify the cell (layout first) where you want to display the content.
These simple examples explain the concept of content and layout prioritization.
Gap properties
Typically, you would include a margin attribute to create a gap around the item.
One of the structural differences between CSS Grid and CSS Flexbox is that you only create gaps around items that use Grid layouts.
The good news is that CSS has added features to support the implementation of gaps around items, which are called the gap property. Both layouts support this property.
It allows you to control the space around items in the container, between columns and rows.
Let’s see how we can accomplish this.
Here, I have nine items in a Flexbox container.
<div class="gap">
<div>A</div>
<div>B</div>
<div>C</div>
<div>D</div>
<div>E</div>
<div>F</div>
<div>G</div>
<div>H</div>
<div>I</div>
</div>
.gap {
display: flex;
flex-wrap: wrap;
}
.gap>div {
background-color: rgba(10, 129, 209, .5);
border: 1px solid #000;
color: #000;
padding: 20px;
font-size: 150%;
}
Use margin to create a gutter around the item.
.gap {
display: flex;
border: 3px solid rgba(6, 109, 243, 0.911);
flex-wrap: wrap;
max-width: 800px;
}
.gap>div {
background-color: rgba(10, 129, 209, .5);
border: 1px solid #000;
color: #000;
padding: 20px;
font-size: 150%;
margin: 6px;
}
When I introduce margin of 6px
, notice how the space around the item is created. margin creates some extra white space that can be avoided by using the gap attribute.
The Gap property obviously creates grooves. You can optionally create spaces between rows and columns.
By specifying column-gap
, the gap is applied.
.gap {
display: flex;
border: 3px solid rgba(6, 109, 243, 0.911);
flex-wrap: wrap;
column-gap: 6px;
max-width: 800px;
}
.gap>div {
background-color: rgba(10, 129, 209, .5);
border: 1px solid #000;
color: #000;
padding: 20px;
font-size: 150%;
}
When we apply wrap, we force Flexbox to create rows and columns on a small screen. We can also use row-gap
, to create grooves around them.
.gap {
display: flex;
border: 3px solid rgba(6, 109, 243, 0.911);
flex-wrap: wrap;
column-gap: 6px;
row-gap: 6px;
max-width: 800px;
}
.gap>div {
background-color: rgba(10, 129, 209, .5);
border: 1px solid #000;
color: #000;
padding: 20px;
font-size: 150%;
}
To create spacing between rows and columns, we can use gaps and specify the units for both.
For example, gap: 6px 6px
, we will get the same result as applying column-gap: 6px
and row-gap: 6px
.
Note that you can mix pixel and percentage values when using the gap property. You don’t have to stick to a single unit. For example, 6px 6%
, 6px 6rem
or 6% 6rem
.
When using a grid, you would use grid-gap
. grid-gap
Deprecated, we have a gap
attribute that works on both layouts.
Note: This is not a difference between the two. It used to be when only the Grid supported gaps. Since this is a recent update, you may find a tutorial explaining the difference between gaps being a property.
Wrap is a property used to wrap items inside a container. It is applied when you want the item to fit in the available space of the container.
This is one of the common properties needed to solve some problems, such as child elements not staying within the container element.
Wrapping allows us to wrap an element to the next row if there is not enough room for it in the current content column.
Both layouts use the concept of wrapping. They handle wrapping differently.
Here is an example.
We are checking the ability to stretch and shrink items based on the amount of space available in our container.
Here’s a very basic wrapping example using a Flexbox layout.
<div class="row-flex">
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
<div>1 2 3 4 5 6 7 8 9 0</div>
</div>
.row-flex {
display: flex;
}
When you resize the screen to below 600px, not every item is visible – this is where the concept of wrap comes into play. Specifying the wrap attribute within the container solves this problem.
.row-flex {
display: flex;
flex-wrap: wrap;
}
We are using wrap inside the container to wrap the Flexbox item to the available container size.
Here is an example of a Flexbox and Grid layout.
<h1>Flexbox</h1>
<div class="flex">
<div>One</div>
<div>Two Two</div>
<div>Three Three Three</div>
<div>Four Four Four Four</div>
<div>Five Five Five Five Five</div>
</div>
<h1>Grid</h1>
<div class="grid">
<div>One</div>
<div>Two Two</div>
<div>Three Three Three</div>
<div>Four Four Four Four</div>
<div>Five Five Five Five Five</div>
</div>
Style containers and items with some CSS.
/* Flexbox row styles */
.flex {
margin-bottom: 2em;
border: 3px solid #000;
display: flex;
flex-wrap: wrap;
gap: 2px 2px;
max-width: 700px;
}
.flex>div {
background-color: rgba(130, 184, 219, 0.5);
border: 2px solid rgb(104, 182, 235);
color: #000;
padding: 20px;
font-size: 150%;
flex: 1 1 250px;
}
/* Grid row styles */
.grid {
max-width: 700px;
border: 3px solid #000;
background-color: #fff;
color: #444;
gap: 2px 2px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.grid>div {
background-color: rgba(170, 132, 167, 0.5);
border: 2px solid rgb(239, 189, 235);
color: #000;
padding: 20px;
font-size: 150%;
}
Apply the wrap attribute to the container as it is the containing element for these items. It will control the wrapping of these items.
Let’s do this.
When we apply the wrap property, the CSS should be styled like this.
/* Flexbox row styles */
.flex {
margin-bottom: 2em;
border: 3px solid #000;
display: flex;
flex-wrap: wrap;
gap: 2px 2px;
max-width: 700px;
}
.flex>div {
background-color: rgba(130, 184, 219, 0.5);
border: 2px solid rgb(104, 182, 235);
color: #000;
padding: 20px;
font-size: 150%;
flex: 1 1 250px;
}
/* Grid row styles */
.grid {
max-width: 700px;
border: 3px solid #000;
background-color: #fff;
color: #444;
gap: 2px 2px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
}
.grid>div {
background-color: rgba(170, 132, 167, 0.5);
border: 2px solid rgb(239, 189, 235);
color: #000;
padding: 20px;
font-size: 150%;
}
For Flexbox layouts, we are applying.
-
flex-wrap: wrap
Push items into rows or columns.
flex: 1 1 250px
Give items a width of 250 and allow them to grow and shrink as the screen size shrinks.
In the case of Grid.
-
grid-template-columns
Create columns.
minmax()
A function that gives each item a width of 250px.-
repeat()
function wraps column repetitions into rows and columns.
Observation: The flexible layout loses its context. If you look at item 5, when wrapping is applied, it loses its context. The wrap tries to squeeze the item to fill the available space. Also, when pushed down, item 5 is not the same size as the other items.
This is because Flexbox is one-dimensional and it arranges items into rows or columns.Wrap forces Flexbox to form rows and columns, depriving Flexbox of its one-dimensional context.
You could say that a grid is just a grid. Items don’t lose their grid background. They are all the same size and they all fall in the grid lines. It doesn’t lose its context as a grid.
This has to do with the fact that grid layouts are two-dimensional, which works well for layouts with rows and columns. In our example, the grid wrapping has forced the item into rows and columns and has not lost its two-dimensional context.
In terms of applications, the concept of grid wrapping works best when you want to push items while keeping the width constant. A good example of this is the image section we use in web design (explained later in this guide).
A fair use case for Flexbox wrapping is this subscription form, which doesn’t have to have the same size when you push items to different screen sizes.
<div class="subscribe-container">
<form>
<input type="email" placeholder="Email Address">
<input type="text" placeholder="Name">
<input class="subscribe-button" type="submit" value="Subscribe">
</form>
</div>
.subscribe-container {
max-width: 800px;
margin: 60px auto;
background-color: rgba(130, 184, 219, 0.5);
border: 5px solid rgb(98, 143, 228);
}
.subscribe-container form {
display: flex;
flex-wrap: wrap;
}
.subscribe-container form input {
margin: 15px;
border: 1px solid rgb(98, 143, 228);
padding: 0.4rem;
}
.subscribe-container form input {
flex: 1 1 200px;
}
.subscribe-container form input[type="submit"] {
border-radius: 3px;
background-color: rgba(17, 228, 10, 0.5);
color: rgb(98, 143, 228);
}
.subscribe-container form input[type="email"] {
flex: 1 1 250px;
}
In this case, each item takes up as much space as possible as the container expands or shrinks on different screen sizes.
Flexbox Layout and Grid Layout
Some of the most common questions about both include.
Does CSS Grid replace CSS Flexbox and is it better than CSS Flexbox?
Should I use CSS Grid instead of CSS Flexbox or CSS Flexbox instead of CSS Grid?- When should you use one of them?
- Which is the best choice for designing web page layouts?
Each layout has its advantages. They all work in different ways. The best and easiest way to produce complex, simple designs is to combine both layouts in a way that stands out.
Let’s illustrate where CSS grids can be implemented to work with CSS Flexbox to create something awesome.
Above is an example of a web design representation. By implementation, the design is done using a grid layout. Take a look at the code used to implement it.
There are some situations during implementation that require you to use Flexbox layouts, such as headers and footers.
When the design is realized, we can represent the content and design of the example.
Continue on to see the code used to implement the above design.
The main layout skeleton is made with a CSS grid, as previewed using the Web Browser Inspector tool.
.container {
max-width: 1250px;
margin: 0 auto;
padding: 0 60px;
display: grid;
grid-template-columns: 0.4fr 0.3fr 0.3fr;
grid-column-gap: 10px;
grid-row-gap: 15px;
background-color: #fff;
}
Let’s break down the page.
As we said, the layout and its contents incorporate CSS Grid and CSS Flexbox properties.
The header consists of a navigation menu and a logo. They are aligned in one direction, so the Flexbox layout will handle their alignment perfectly.
<div class="header">
<p class="logo"><a href="#"><i class="fa fa-home" aria-hidden="false"></i></a></p>
<nav>
<ul>
<li><a href="#">HOME</a></li>
<li><a href="#">ABOUT</a></li>
<li><a href="#">Contact</a></li>
<li><a href="#">SIGN UP</a></li>
<li><a href="#">SIGN IN</a></li>
</ul>
</nav>
</div>
In this case, the header is a perfect example of implementing Flexbox within a CSS grid.
.header {
grid-column: 1 / 4;
grid-row: 1 / 2;
text-transform: uppercase;
border-bottom: 2px solid #b0e0ea;
padding: 20px 0;
display: flex;
gap: 5px;
align-items: center;
}
Similarly, the navigation menu adapts well to the Flexbox layout.
.header nav ul {
display: flex;
list-style-type: none;
}
Another case of embracing one-dimensional flexibility is the Extra Content section.
<div class="extra">
<div class="content-block-info">
<h3>View Grid Help</h3>
<p>See tips and tricks for CSS Grid Layouts...</p>
<button>Read</button>
</div>
<div class="content-block-info">
<h3>View Flexbox Help</h3>
<p>See tips and tricks for Flexbox layouts...</p>
<button>Read</button>
</div>
<div class="content-block-info">
<h3>View Combined Help</h3>
<p>See tips and tricks for combined layouts...</p>
<button>Read</button>
</div>
</div>
.extra {
grid-column: 2 / 4;
grid-row: 4 / 5;
padding: 1rem;
display: flex;
flex-wrap: wrap;
border: 1px solid #ececec;
justify-content: space-between;
}
Each content-block-info
, is vertically aligned; therefore, a one-dimensional layout is appropriate for its design.
To wrap this illustration, the image section consists of images. This can be achieved with a Flexbox layout, by wrapping the image to fit the size of the layout.
But with a grid layout, the image works fine on a 2D layout.
.related-images {
grid-column: 1 / 3;
grid-row: 5 / 6;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 1rem;
}
CSS Grid and Flexbox layouts can do a lot of things. But in some ways CSS Grid is better and more convenient, while in other ways Flexbox is more convenient and the right choice.
When to Consider Flexbox
It is ideal for implementing layouts with fewer items such as headers and footers when you need a small layout.
Flexbox is ideal if you are considering aligning your content in one direction. It allows us to create a Flexbox container and determine its orientation, either horizontally or vertically. This will help distribute your content evenly in one direction.
Flexbox will be a perfect choice when you consider content first.
When to Consider Grids
Larger layouts with multiple rows and columns are two-dimensional.The CSS grid will help you with complex designs like the one we used in the web design above because of its ability to support multi-directional designs. It enables you to design the big picture of your layout and components.
When the design of your layout is choosing to arrange the items in your container, a CSS grid will be ideal for manipulating the design of your layout.
The best option is to combine both layouts.Flexbox containers can be used inside Grid containers and vice versa. Adopt the practice of using Flexbox layouts inside Grid containers when designing web pages so that your content moves in the right direction.