Deep Tech Point
first stop in your tech adventure

Responsive grid layout example with explanation

August 7, 2021 | CSS

This article will take you to the very beginning of working with a grid layout. We will present a super simple code for the layout of the page. We will start with a mobile view first and include a media query for a desktop version. We will go through the code and explain why we did this and that. Let’s start at the beginning, but first, let’s take a look at how our page is constructed.

The basic structure of the page

We start with an html tag, beneath the head tag in which we place the style tag, where we will work with our CSS. We will get back to the style tag in a bit, but first, let’s cover the body part of the page.

<html>
<head>
<style>
....
</style>
</head>
<body class="forum-body">
    <div class="container">
        <header>HEADER</header>
        <nav>NAV</nav>
        <article>ARTICLE</article>
        <aside>ASIDE</aside>
        <footer>FOOTER</footer>
    </div>

</body>
</html>

After the head tag comes the body tag, where we define our divs. For the sake of simplicity and readability, we use header, nav, article, aside, and footer tags, which behave like a div tag, but are this way more descriptive:

In addition, we’ve put everything inside the DIV tag and named it a class “container”. The container is an essential part of a grid layout. This is where we define grid properties that control the behavior of grid items (header, nav, article, aside, footer).

Let’s have a look at what is inside the style tag

First, let’s make sure margins of the body won’t cause us headaches, so let’s give it a margin of zero:

body {
        margin: 0;
    }

We could avoid that line of code by including normalize.css file in our document. Some developers use it as a reset stylesheet for better cross-browser consistency in the default styling of HTML elements.

Notice there isn’t a dot (.) in front of the body tag when defining its CSS? “body” tag is a type selector and not having a dot in front of it is a standard for a type selector (in our case we used body, and later on header, nav, article, aside, and footer). Type selector is sometimes also referred to as a tag name selector or element selector because it selects an HTML tag/element in your document.
“.container” on the other hand is a class selector, which starts with a dot (.) character. Maybe you’re asking yourself, how do I know when should I use a tag selector and when a class selector? It depends on the intended semantics, however, you should try to be as specific as possible. Usually, we use tag selector for the general purpose of page styling, while tag.classname and .classname for the exceptions or to override the above rule, or when we want to be as specific as possible when targeting elements.

Defining a grid layout and it’s properties

Next, let’s continue reading the code and check that .container class that we’ve mentioned a second ago. In this part we are defining the grid container and it’s properties – a gap, how many columns the grid will have, what areas the grid will contain and through this also how many rows the grid will have:

.container {
        display: grid;
        grid-gap: 0.3em;
        grid-template-columns: 1fr;
        grid-template-areas: "header"
                             "nav"
                             "article"
                             "aside"
                             "footer";
    }

First, we said we want our div with a class name .container to be displayed as a grid. So, we finally defined our grid layout here in a CSS styling section with display: grid;.
Second, we defined our grid-gap to be 0.3em (which is about 5px {{{if we don;t define font-size}}}) with grid-gap: 0.3em;. Our editor (we worked in Visual Studio Code but it really doesn’t matter which editor you use) said that the grid-gap property is obsolete, which means that in newer browsers it could become useless. We checked it online and saw it is still very well supported in the majority of browsers, so we decided to go with it anyway. Instead of grid-gap property, we could simply use gap property, which is a shorthand for row-gap and column-gap.
Third, we defined the number of our columns: grid-template-columns: 1fr; This part (1fr) says we have only one column (if there were three values defined, for example, 1fr 1fr 1fr it would mean we have three columns of equal width). Why only one column? We are starting with a mobile view, so for readability’s sake, we will put all our items in one column, one after another.
What does 1fr mean? It’s a unit that was invented with a grid layout. It means a fraction of viewport and it is super cool because it works well with a responsive layout and adopts a fraction of available viewport space. If you would like to learn more about fractions, you should read more about them in this article: The fr unit and the CSS grid layout
Fourth, we defined our grid-template-areas: with their item names in quotes and in the following order: header comes first, then nav, article, aside and footer at the bottom. All these areas will be structured in one column, one after another, which will work out in five rows and they all will take the entire width of the viewport.

Styling our divs with a help of CSS

    
   header {
        grid-area: header;
        padding: 2em;
        background-color: aqua;
        text-align: center;
    }
    nav {
        grid-area: nav;
        padding: 1em;
        background-color: greenyellow;
        text-align: center;
    }
    article {
        grid-area: article;
        padding: 10em;
        background-color: blueviolet;
        text-align: center;
    }
    aside {
        grid-area: aside;
        padding: 5em;
        background-color: burlywood;
        text-align: center;
    }
    footer {
        grid-area: footer;
        padding: 2em;
        background-color: cyan;
        text-align: center;
    }

OK, so what is going on here?
We are defining each tag selector here in more details:

Defining grid-area property is an inevitable part of a grid layout because we used grid-template-area property. Padding, background color, and text-align are however just a beautification of the layout. For example, our items do differentiate a bit more and their borders are more defined when we specify a background color. Padding is there to add a bit more whitespace for increased page readability, and text-align is there, well, to align the text to the center.

Media queries and the breaking point for the layout change

   @media (min-width: 1281px) { 
        /* hi-res laptops and desktops */ 
        .container {
            grid-template-columns: 1fr 3fr 1.5fr;
            grid-template-areas: "header header header"
                                "nav article aside" 
                                "footer footer footer";
        }
    } 

What is this all about?

   @media (min-width: 1281px) { 
        /* hi-res laptops and desktops */

The @media query is an important ingredient of the recipe for responsive design – it allows specified CSS to be applied depending on the device when it matches the media query criteria.
This part of the code says that when the viewport is 1281px or wider, which is the case with hi-resolution laptops and desktops, the layout of the page will change. So our .container that previously contained only one column will rearrange its layout. So, when the viewport reaches that 1281px breaking point, we are all of a sudden in a desktop view.
We already mentioned above that we specified the “mobile (view) first” – as the name suggests, it means that we start the product design from the mobile end which has more restrictions, then expand its features to create a tablet or desktop version. We decided to go with that approach because, for example, more than half of the visitors to our page come from mobile devices, so we gave that view an advantage.
Below you will find a shortlist with the best breakpoints that will help you target different devices, such as desktop, tablet and mobile. There could be some discrepancies and we’re sure you’ll find examples with slightly different targeting values, but basically you can use these:

Next, in the code we have three columns which we define with

grid-template-columns: 1fr 3fr 1.5fr;

You can see the values aren’t the same. The first column will take 1fr, the second 3fr, and the third column will take 1.5fr of the viewport.
For the desktop view, we will have three rows – they are specified indirectly through grid-template-areas: