Md Toy Blog

CSS Grid vs. Flexbox

Wed Feb 06 2019 00:00:00 GMT+0000 (Coordinated Universal Time)

Grid is 2D positioning whereas Flexbox is 1D positioning. See this great Flexbox guide and this great Grid guide.

For a quick and gentle introduction to both topics watch Academind's video by Max

Browser support for these technologies requires vendor prefixing of directives, use an autoprefixer to automate this process.


The Grid allows you to define … a grid … with rows and columns:

.my-div {
    display: grid; /* grid directives will now apply */
    grid-template-rows: 80px auto 10vh; /* create 3 rows with the 1st occupying a fixed hieght, and the 2nd spanning calc(100vh - 10vh - 80px) */
    grid-template-columns: 33.3% 33.3% auto; /* create 3 columns of 1/3 of the space each. Always use auto for one of the cols to avoid rounding errors */


We have set up our grid cells and their respective size (slicing them with columns and rows).

How do we place content inside the cells ?

We first need to give names to cells, and tell the grid how to group them. Yes, you can group cells. For example if we need to have an element span two cells. To do so we define areas: named rectangular groups of adjacent cells. Areas will be used to place the content inside their spanned cells.

Use one "…" per row. And one area-name per column inside that row. If you use the same name in two adjacent columns of the same row then they will be united.

Since we have 9 cells (3x3 rows and cols), we will have 3 parameters delimited by "" in the directive. And inside each of those quote pairs we will have one name area per column "area1 myarea2 my3col".

.my-div {
    /* ... */
    grid-template-area: "header-icon headernavbr headernavbr" /* 1st row's two last cols will be united */
                        "mycontainer mycontainer mycontainer" /* the main container will span the 2nd row and 3 cols */
                        "footer1 footer2 footer3";            /* reserve 3 cols for each footer part in the last row */



Now that we have specified our Grid and given names to each of the areas, we can start using the areas.

Using the Grid named areas

In order assign content to the named areas

Here is how you place some element into a grid area.

img {
    grid-area: header-icon;

ul.main-nav {
    grid-area: headernavbr; /* Will span last 2 cols of 1st row */

div.content {
    grid-area: mycontainer;

div.quick-contact {
    grid-area: footer2;


What is great is that you do not need to use html markup and place divs inside one another to make them appear inside some visual boundary. There is a clear separation of html markup used exclusively to group conceptual content and css styles being used for the visual part.

Noticed how pleasing is this ability to reference areas inside style brackets ? It's not the "usual/old" CSS way, were we could use selectors only outside the curly braces. Of course named areas are not selectors but they allow referencing stuff.


Flexbox is unidimensional but bidirectional. So a Flexbox can only deal with a single stack of cells, but it can be set to be horizontal like a row or vertical like a column. The flexbox has the ability to span several rows (columns) when the viewport is not wide (high) enough, but it is still 1D. For this behavior to happen, we use : flex-wrap: wrap, (other directives are: nowrap and wrap-reverse.

In our grid example we are using a navigation. And if you have not already changed it's styles, you will notice that it is vertically stacked by default. How would you go about making it horizontal ? There is of course the usual way: display: inline, another way is to make the li float: left | right. Using flexbox for this purpose will allow you to better control what happens when the viewport changes size.

Here is an example of using Flexbox. We will start by assigning the Flexbox behavior to the container element. We will also specify the direction of the flex container. Next we will tell how to

ul.main-nav {
    display: flex; /* inline-flex will make the container (and not the items!) display inline*/
    flex-direction: row; /* default value, others are: row-reverse | column | column-reverse */

    /* horizontal alignment */
    justify-content: flex-end; /* others are: flex-start | center | space-between | space-around | space-evenly */

    /*vertical alignment */
    align-items: center; /* others are: flex-start | flex-end | stretch | baseline */

    height: 100%;


You can also reorder the way the elements appear inside the flexbox. This is a rule that is applied to the elements themselves:

ul.main-nav li.home {
    order: -100; /* increase distance to establish higher priority */

ul.main-nav li.pages { /* all pages have same priority, which is lower than home */
    order: 1;

ul.main-nav { /* we want the contact to be on the right */
    order: 2;

There are many more ways to manipulate the layout. Reading the full guides from CSS Tricks will really make you a better web design implementer.