Search code examples
htmlcsscss-grid

Creating navbar with CSS grid


I'm creating a navbar made with CSS grid.

I decided making it with grid so I can re-arrange the sections (items) without modifying the html (just modify the CSS).

Then I created the grid with 3 areas: logo, menus, toggler.

And I added a bit of gap so each items won't stick together.

enter image description here

So far so good, until I tried to remove one/some sections, the gap still there even if the section was gone.

Then I tried to remove the gap and replace with a margin to each section. But the margin won't collapse at the beginning/ending of the grid. It behave differently than on regular block element.

I know it's more practical using a flexbox rather than a grid, but I prefer the grid because the section can be re-arranged without modifying the html. It's possible to move the logo at the top or somewhere else. Something impossible with flex.

Anyone can solve my grid-gap problem? Or maybe you've a different approach for creating the navbar?

See my sandbox:

.navbar {
  background: pink;
  display: grid;
  grid-template-rows: auto;
  grid-template-columns: max-content auto max-content;
  grid-template-areas: "logo menus toggler";
  justify-items: stretch;
  align-items: stretch;
  column-gap: 20px;
}

.logo {
  background: green;
  grid-area: logo;
  width: 60px;
}

.menus {
  background: lightsalmon;
  grid-area: menus;
  display: flex;
  flex-direction: row;
  justify-content: start;
}

.menus * {
  padding: 5px;
}

.toggler {
  background: lightskyblue;
  grid-area: toggler;
}
<p>navbar with complete sections:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without logo:</p>
<nav class="navbar">
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
  <div class="toggler">
    X
  </div>
</nav>

<hr>

<p>navbar without toggler:</p>
<nav class="navbar">
  <div class="logo">
    LoGo
  </div>
  <div class="menus">
    <div>menu-1</div>
    <div>menu-2</div>
    <div>menu-3</div>
  </div>
</nav>


Solution

  • In such case, you can rely on implicit columns. You only define one explicit column and you create new ones only when the elements are there. You can easily swap the positions with issue too

    .navbar {
      background: pink;
      display: grid;
      grid-template-rows: auto;
      grid-template-columns: 1fr; /* only column intially */
      grid-auto-flow:dense;
      justify-items: stretch;
      align-items: stretch;
      column-gap: 20px;
    }
    
    .logo {
      background: green;
      width: 60px;
      grid-column:-3; /* create an implicit one at the beginning */
    }
    
    .menus {
      background: lightsalmon;
      display: flex;
      flex-direction: row;
      justify-content: start;
      grid-column: 1; /* take the explicit one */
    }
    
    .menus * {
      padding: 5px;
    }
    
    .toggler {
      background: lightskyblue;
      grid-column:2; /* create an implicit one at the end */
    }
    <p>navbar with complete sections:</p>
    <nav class="navbar">
      <div class="logo">
        LoGo
      </div>
      <div class="menus">
        <div>menu-1</div>
        <div>menu-2</div>
        <div>menu-3</div>
      </div>
      <div class="toggler">
        X
      </div>
    </nav>
    
    <hr>
    
    <p>navbar without logo:</p>
    <nav class="navbar">
      <div class="menus">
        <div>menu-1</div>
        <div>menu-2</div>
        <div>menu-3</div>
      </div>
      <div class="toggler">
        X
      </div>
    </nav>
    
    <hr>
    
    <p>navbar without toggler:</p>
    <nav class="navbar">
      <div class="logo">
        LoGo
      </div>
      <div class="menus">
        <div>menu-1</div>
        <div>menu-2</div>
        <div>menu-3</div>
      </div>
    </nav>
    
    <hr>
    <p>navbar without toggler and log at the end </p>
    <nav class="navbar">
      <div class="logo" style="grid-column:2">
        LoGo
      </div>
      <div class="menus">
        <div>menu-1</div>
        <div>menu-2</div>
        <div>menu-3</div>
      </div>
    </nav>
    
    <hr>
    
    <p>navbar without logo and toogler at the beginning </p>
    <nav class="navbar">
      <div class="menus">
        <div>menu-1</div>
        <div>menu-2</div>
        <div>menu-3</div>
      </div>
      <div class="toggler" style="grid-column:-3">
        X
      </div>
    </nav>