CSS Grid is an official CSS specification that is widely supported by browsers and it has high a adaption rate.
Below screengrab from caniuse.com shows the current support of CSS Grid across various popular browsers.
One of the interesting thing about CSS grid is that it is two dimensional i.e. we can work in both rows and columns - much similar to old fashioned tables
The very first thing that we require to make an element behave as the grid is to by declaring display: grid
or display: inline-grid
on an element.
The element to whom above CSS property is applied is called grid container and the child items of a container are called grid items
We start with very basic markup
<div style={{ }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
As we can see, right now the items are stacked on top of each other.
Let’s now add display:grid
property to make it grid container
<div style={{ display: 'grid' }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
Alright, now the parent is turned into a grid however there is no effect on the layout.
By default each grid item is taking 100% available width hence they are laid out in a column.
What if we want to position items horizontally?
To position the items horizontally we need to define another property grid-template-columns
and give each column its size as follow
grid-template-columns: 100px 100px 100px;
Let’s define property grid-template-columns
on-grid container and give each of grid items size of 100px
<div style={{ display: 'grid', 'grid-template-columns': '100px 100px 100px' }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
Now, it’s not necessary to know the sizes beforehand and that is where grid gets powerful - you can define sizes using fractions units or mix it with fixed values
Let’s update the markup and instead of 100px
use fr
i.e. fraction units
<div style={{ display: 'grid', 'grid-template-columns': '1fr 1fr 1fr' }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
Well, as you can see, all grid items are distributed equally and occupying 100%
of available with - isn’t that cool?
To achieve this, we can change the syntax as follows
'grid-template-columns': '2fr 1fr 1fr'
Instead of 1fr
for item “One”, we just changed it to “2fr”
<div style={{ display: 'grid', 'grid-template-columns': '2fr 1fr 1fr' }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
Now, grid item “One” takes half of the available space and rest is occupied by grid item “Two” and “Three”
Imagine doing all this math manually 😃
Since we know we have three items and we are using fr
units here, we can simply change the syntax as follow
'grid-template-columns': '1fr 1fr'
This will automatically move grid item “Three” to next row
<div style={{ display: 'grid', 'grid-template-columns': '1fr 1fr' }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
We can also simplify the above syntax using repeat
keyword as follows.
So, instead of
'grid-template-columns': '1fr 1fr'
We can just write
'grid-template-columns':repeat(2, 1fr) ;
There is no impact on output
<div style={{ display: 'grid', 'grid-template-columns': 'repeat(2, 1fr)' }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
The grid items are aligned very close to each other, let’s add some gap to let them breathe.
To add gap, we can simply define
grid-gap: 10px;
This will add a 10px
gap between both columns and rows.
<div style={{ display: 'grid', 'grid-template-columns': 'repeat(2, 1fr)', 'grid-gap': '10px' }}> <div style={{ background: 'cornsilk' }}>One</div> <div style={{ background: 'darkseagreen' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
What if we just want to add a gap to either column or rows?
The solution is simple, instead of just gap
we can either use property grid-column-gap
or grid-row-gap
and assign them desired value
We can even tell the grid to move the item from its default location and start from some other row or column.
But before that, we need to understand a few things
To understand the above properties, I am using below screengrab from Firefox developer tools. Firefox developer tools are great for visualizing CSS Grids, flexbox, animations, etc…
grid-column-start
is from where the column starts. For example in case of grid item “One”, the value of grid-column-start
is 1
grid-column-end
is having a value of 2 for grid item “One”
If we combine the above two things, it means grid item “One” starts from column 1 and end at column 2
Similarily, grid-row-start
is having a value of 1 for grid item “One”
and, grid-row-end
is having a value of 2
Again, if we combine the above two things, it means grid item “One” starts from row 1 and end at row 2
To, switch the position we just need to tell where the item is going to start and where it’s going to end as follows - keep in mind these properties need to be defined on grid items and not grid container
<div style={{ display: 'grid', 'grid-template-columns': 'repeat(2, 1fr)', 'grid-gap': '10px' }}> <div style={{ background: 'cornsilk', 'grid-column-start': '2', 'grid-column-end': '3', 'grid-row-start': '1', 'grid-row-end': '2' }}>One</div> <div style={{ background: 'darkseagreen', 'grid-column-start': '1', 'grid-column-end': '2', 'grid-row-start': '1', 'grid-row-end': '2' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
That’s nice - without dealing with floats and CSS positioning, we can to do this hard work in a few lines of code and most importantly, we are sure it will work.
Using, the same properties that we learned above we can make item “Two” span across two rows as follows
<div style={{ display: 'grid', 'grid-template-columns': 'repeat(2, 1fr)', 'grid-gap': '10px' }}> <div style={{ background: 'cornsilk', 'grid-column-start': '2', 'grid-column-end': '3', 'grid-row-start': '1', 'grid-row-end': '2' }}>One</div> <div style={{ background: 'darkseagreen', 'grid-column-start': '1', 'grid-column-end': '2', 'grid-row-start': '1', 'grid-row-end': '3' }}>Two</div> <div style={{ background: 'darksalmon' }}>Three</div> </div>
By, just changing grid-row-end: 2
to grid-row-end: 3
, we can span item “Two” on two rows.
These are the basics of CSS Grid. I will be covering more advanced properties and the layout’s future post.
I hope you enjoyed the post.
Happy learning!!