Back to Basic will answer some of my questions when I first started learning CSS. Personally, I think when you start learning CSS, it will be very hard, because CSS has about 520 properties that we can use. Of course, we won't use it all, there are many properties that I still didn't know, but there are plenty of properties that we need to understand to be proficient in CSS. This blog will not cover CSS from the really basic ones, but I will try to show you the implementation.
If you never have used flexbox or grid before, you can check this flexbox guide and grid guide from css-tricks.
Question
When should we use flex or grid?
When I first started learning CSS and know about flexbox and grid, I got confused about when to use flexbox and grid. In this blog, I will try to explain my approach on how to choose between flexbox and grid according to the condition.
Use Case of Using Flex
I always use flex to give a layout that only has 1 dimension (horizontal only or vertical). In this blog, I will give you some example of flexbox use case with some of my project that I have made.
1. Container that has all elements in the center both horizontally and vertically
We usually see this in a landing page
Example:
To achieve this layout, we only need 3 lines of CSS, I suggest you to memorize this combination, because you will use this in many cases.
.container {
/* make sure the parent element has height */
min-height: 100vh;
/* css to align vertically and horizontally */
display: flex;
align-items: center;
justify-content: center;
}
/* If you want to make a full-page,
make sure the container has a height of the viewport */
2. Divide page into parts
This layout also commonly seen, usually to divide the container into 2 parts with the same width, we can also make it divide into 3, 4, or as many as you want.
This layout can be easily achieved by using flex, let's see the HTML first
<div class="container">
<div class="content">
<h1>Hello Bambang</h1>
<p>welcome to my page</p>
<button>click me</button>
</div>
<img class="content" src="https://unsplash.it/700/600" alt="unsplash" />
</div>
As we can see, that div.container
has 2 items which is div.content
and img.content
, so we can make layout that is equal parts.
.container {
min-height: 100vh;
display: flex;
}
.content {
/* this will make it divides in equal parts */
width: 100%;
/* you should use flex-basis for this, but flex-basis didn't really works on images, so I use width */
/* flex-basis: 100%; */
/* other tag like div works well tho! */
}
div.content {
/* the first flexbox use case */
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
img.content {
object-fit: cover;
}
by using width: 100%
we make the child element to take as much space as possible. Because both of them wants to be 100%, so they compromise and span over 50%.
Keep note that you should replace
width: 100%
withflex-basis: 100%
for IE compatibility purposes (credits to Ihor Vorotnov), but I specifically use width on this one because flex-basis did not really work with images. On other tag like div or headings it works okay.
We could also hard code the width or flex-basis to 50%, but adding this defeat the purpose of dividing content to equal parts because we need to change the percentage each time we add a new child.
If we want to make a responsive design with this layout, we can utilize
flex-direction
.container {
min-height: 100vh;
display: flex;
/* add this to make the flex stacked vertically */
flex-direction: column;
}
@media (min-width: 700px) {
.container {
flex-direction: row;
}
}
So, when we are in a mobile view, flex will stacked vertically (like how HTML normally works), and when we get into larger viewport, flex will make the child elements stack horizontally (check the codepen for demo)
3. Creating Navbar (using space-between)
Creating a simple navbar will be very often to do and usually, the layout is spaced apart where the left side is the logo and the right side is the navigation.
<nav>
<h3>Home</h3>
<ul>
<li>Route</li>
<li>Route</li>
</ul>
</nav>
nav
has 2 children which are h3
and ul
. Next, we just need to reset the base style and split the children element with space-between
nav {
background-color: lightblue;
display: flex;
align-items: center;
/* this property will make the child spaced apart */
justify-content: space-between;
}
ul {
/* remove bullet style */
list-style: none;
display: flex;
}
ul > li + li {
/* add space between navigation links */
margin-left: 2em;
}
All of the examples above actually can be made with a grid too. But, by using grid we need to write more CSS than using flexbox
Use Case of Using Grid
Grid is usually used to make a more complex layout. My way of deciding is: if using flex is too hard, then use grid.
Layouting with flex actually can also be implemented for the complex layout, but using grid will be much easier.
1. Making 2 dimensional layout
I usually use grid to create this layout because there is a gap
feature to space them out. Spacing things out using flex is going to be harder if we want to make the design responsive
Layout like this will be very easy if using grid, we only need to make it into 2 columns.
<div class="container">
<div class="item">item1</div>
<div class="item">item2</div>
<div class="item">item3</div>
</div>
We will simplify the layout by using div.container
and 3 div.item
.container {
/* container base layout */
max-width: 700px;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1em;
}
.item {
border: 0.2px solid white;
height: 15em;
}
By using grid-template-columns: repeat(2, 1fr)
we set the grid to divide the columns into two, and the item
will follow the rule that we set. Last, we add the gap: 1em
to create some whitespace.
Grid will be very helpful in responsive design, we only need to change the rules on grid-tem to be 1 column when it is on smaller screen size, and make it to 2 columns in the larger screens
.container {
/* container base layout */
max-width: 700px;
margin: 0 auto;
display: grid;
/* no need to add grid template, because grid defaults to 1 column */
gap: 1em;
}
@media (min-width: 700px) {
.container {
grid-template-columns: repeat(2, 1fr);
}
}
2. Make layout with different sizes
I recommend you to use Firefox Dev Tools to see lines indicating the grid numbers.
We approach this kind of layout by making 4 columns and 2 rows, then we assign the row and col placement on each of the elements. For example, the first picture spans over 2 columns and 2 rows. Check this if you have not understand the grid numbering system.
<div class="container">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
<div class="item item4">item4</div>
</div>
We will simplify the layout by using .container
as the parent.
.container {
max-width: 700px;
margin: 0 auto;
display: grid;
/* makes the grid into 4 columns and 2 rows */
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 1fr);
}
.item {
border: 1px solid white;
min-height: 10rem;
}
.item1 {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
.item2 {
grid-column: 3 / 5;
}
/* you can also give value to item 3 and 4,
but because it follows the natural flow of the grid I won't continue */
For responsive design, we can put the image according to the rows and columns that we want, we can also change the template
Summary
Use Grid if using flex is getting too complicated
Originally posted on my personal site, find more blog posts and code snippets library I put up for easy access on my site š
Top comments (32)
The one-line summary says it all! Nice examples to highlight the differences. I would like to quote from devopedia.org/css-grid-layout :
"CSS Grid doesn't replace Flexbox. Grid items can be flex parents and vice versa."
Thanks for your addition!
It does
Your example #2 (divide page into parts) won't work in Safari. There's no need to hack around with 100% width, there ape specific flexbox properties for that - flex-grow and/or flex-basis:
Also, this is actually the case when grid would be better / simpler / easier:
Thanks for your addition! I edited the post!
It turns out that using flex-basis won't work with images. But it is fine on other tags
Why not "grid-template-columns: 1fr 1fr"? This will produce the same right?
Correct, I usually use fraction unit too.
Will be nice if you explain what:
means.
One third? Nope. One column and three rows? nope. One ror and three columns? nope.
It is not intuitive to mw
I think a lot of people struggle with grid untill you realize that you are not positioning items in terms of colum- and row-areas, but instead lines.
Lets say we draw 3 colums. That gives us 4 vertical lines. So if the container needs to fill out the 3 AREAS you need to write:
grid-column: 1/4; This means that you start at line 1 and end at line 4.
Oh my god! Thank you.
That totally make it click for me.
Thanks
Your' welcome šš
You can look it up at the link that I referred, after that with the numbering illustration I put up, it should be intuitive enough! Good luck š
Nice article ...in short Use flex for one dimensionl group of things ie things that need to be placed in a row only, or things that need to be placed column only. ie nav bar = things in a row. With flex you cannot control both row and column.
Use CSS grid for 2 dimensional placement where you want to cotrol the row and column placements. ie the complex layouts of a website.
In flex box you can acheive many things that CSS grid can do, but you have to start nesting containers, which ends up over complicating.
Great recap!
Grid and Flex box actually goes well together, but grid is simpler and removes a lot of unnecessary code
Thank you!
*insert Thank you! meme
;)
Great article!
Note that the
gap
property can also be used to add spacing between your elements in a flexbox layout: caniuse.com/flexbox-gap.It is supported by all major browsers by now :-)
Thanks for your addition. Yep, finally ios & safari is supported, we can start using it now, no more
.flex > * + *
š¬With those tiny bits of rows and columns? Wow, Grid says divide and conquer! Adjust in order to fit into any tiny bit of space available; Flexboxes even admit they would employ the services of a grid if necessary! Flexbox has the ability to line things up in one dimension (horizontal) but hey, grids with their rows and columns do the same in 2-dimensions! Rows x Columns.. capable of adjusting based on what's going into the grid.
I do everything with grid, it is less code and who cares about IE.
Nice! I think with
grid-auto-flow
it can easily replace flexbox now, it is also easier to understand grid than flexbox.Yes grid makes just more sense and you can picture it in your head
Great overview!
I love how the text in the "Divide page into parts" codepen is "Hello Bambang".