Modern Responsive Navbar with CSS-Grid and Media Query

THANK YOU to Chris Nwamba for contributing this awesome article.

CSS Grid is evolving really fast.

As it stands, there is absolutely no reason why you should not be using it right now. Yes, I understand how had new technologies are hard to adapt especially the evolving ones. As for CSS Grid, it’s more of overdue requirement in how we we build user experiences.

Some of these requirements lie below responsive patterns. Responsive patterns are tricky. Honestly they are hard when not thoroughly designed and thought through. What CSS Grid can do for you is make it easier to adapt to changing viewports by simply redefining the Grid’s definition. I have seen these in a lot of examples including Rachael’s article on Media Queries in 2018 as well as Jo’s article on Common Responsive Layouts with CSS Grid.

I thought maybe I should do one that shows how we can make a common navigation bar using CSS Grid and Media Queries.


If you want to get right to it, see the Codepen of Modern Response Nav Menus.

The example in this article would work in most use-cases but feel free to reach out if you have a more optimal way of doing this.

Choosing a Breakpoint

“If you start with your design for the smallest device and start to drag your browser window wider, when do the lines become too long to read comfortably?” Rachael asked as she went ahead to as further: “When could you make better use of the screen?”

Her point is, stop picking breakpoints like this: 320, 640, 800, 1200, etc. Breakpoints like this are too rigid since there are varying device widths in the tech market. 

Instead consider the smallest possible, then start there. When the width increases and your design starts looking awkward or texts starts spreading too wide, add a breakpoint.

For our menu, I am just going to take 300px

Grid and Columns

The only part of CSS Grid you need to know for the following example is the grid value of display and the grid-template-columns property. 

grid  value is like flex value. It tells the browser that every direct children of the element should be treated as a grid item. Hence, it’s the grid container. 

grid-template-columns is also assigned to the grid container element but tells the browser how to arrange the grid items in columns (there’s also grid-template-rows). Hence, it defines the grid‘s columns.

Assuming you have following as an idea for you grid:


Setting the columns this way should get you kicking:

    grid-template-column: 400px 150px 400px 

There are other ways to set the values. For example, you can use relative values or even use a repeat function to repeat related values. You can learn about them on this CSS Tricks post.

Mobile Viewports

We are using the term “mobile” to describe anything that falls between 0 and 300. Before we craft some styles, here is a truncated version of the markup:

    <!-- Navbar SVG logo -->
      <div class="logo">
        <svg width="112" height="28" viewBox="0 0 112 34">
      <!-- User acount -->
      <div class="account">
        <div>Welcome Udoka</div>
        <div><strong>My Account</strong></div>

      <!-- Cart -->
      <div class="cart">
        <svg width="24" height="24" viewBox="0 0 34 34">

Basically three hr-separated sections which should look like these at the end of the day:


The mobile (<= 300) version has a vertical menu which is basically how things flow normally on the web unless they are inlined.

    nav > div {
      font-size: 1.6em;
      min-height: 50px;
      padding: 1rem 4rem;

    nav {
      display: grid;
      justify-items: center;
      text-align: center;

This is enough to hand you a vertical menu:


There you have a mobile navigation bar. You can take a look at the supporting Codepen for other supporting styles.

Larger Viewports

Anything above 300px or thereabout would start looking weird as a menu. You can see this from the GIF image shown above. When enlarged to a desktop viewport, it feels awkward and takes had unnecessary white space.

At this point, we need to add a breakpoint. The only important thing that will change is the grid layout. You can do this using the grid-template-column property we discussed earlier:

    @media (min-width: 30rem) {
      nav {
        grid-template-columns: 1fr auto auto;
        justify-items: start;
    // fr and auto are relative units.

What we are saying with the value is:

  1. Set the logo to take all available width (1fr)

  2. After you have sized account menu and cart menu with their required widths (auto auto)

Trust me, you just made a responsive navigation bar!


The contributors to JavaScript January are passionate engineers, designers and teachers. Emily Freeman is a developer advocate at Kickbox and curates the articles for JavaScript January.