DEV Community

Cover image for How they made controls at Github? Hamburger menu
Kiran Mantha
Kiran Mantha

Posted on • Updated on

How they made controls at Github? Hamburger menu

Recap

In last episode we gone through how to create a modal dialog using details and summary tag.

Now

In this episode let's see how to create hamburger menu using the same tags.

let's see the html

<details role="menu">
    <summary>
        I'm a burger
    </summary>
    <ul>
      <li>
        <a href="#">Item 1</a>
      </li>
      <li>
        <a href="#">Item 2</a>
      </li>
      <li>
        <a href="#">Item 3</a>
      </li>
      <li>
        <a href="#">Item 4</a>
      </li>
    </ul>
</details>
Enter fullscreen mode Exit fullscreen mode

then where is ham 😆. For that let's add mayonise.. i mean svg to add ham to above burger

<details role="menu">
    <summary>
      <svg
        aria-hidden="true"
        focusable="false"
        role="img"
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 30 30"
        height="25px"
        fill="none"
        stroke="currentColor"
        stroke-width="4"
        stroke-linecap="round"
        stroke-linejoin="round"
      >
        <line x1="3" y1="5" x2="21" y2="5"></line>
        <line x1="3" y1="15" x2="21" y2="15"></line>
        <line x1="3" y1="25" x2="21" y2="25"></line>
      </svg>
    </summary>
    <ul>
      <li>
        <a href="#">Item 1</a>
      </li>
      <li>
        <a href="#">Item 2</a>
      </li>
      <li>
        <a href="#">Item 3</a>
      </li>
      <li>
        <a href="#">Item 4</a>
      </li>
    </ul>
  </details>
Enter fullscreen mode Exit fullscreen mode

ahhh there's our ham ➕ burger 😄. But... hey that's an accordion.
i know ❗ i know ❗
don't worry. here is the styling:

details[role='menu'] {
  display: inline-block;

  summary {
    cursor: pointer;
    list-style: none;
  }

  summary + ul {
    background-color: var(--primary);
    list-style: none;
    padding: 0;
    margin: 0;
    width: 200px;

    li {
      &:hover {
        background-color: var(--option-hover-color);
      }

      a {
        color: #000;
        display: block;
        text-decoration: none;
        padding: var(--spacing);
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

hmm still an accordian to me 😐
then lets see the criteria for hamburger menu

  1. It should close the menu when clicked outside
  2. It should blur the background when menu is visible
  3. The menu should be displayed along the height of view port
  4. A subtle animation for cool looks 😎

woahh that's a huge list. no problem we can do it. let's do it. ✊

for all the above requirements we don't have to write a single line of javascript. Believe me all the above things can be done by css.

let's go one by one...

1. It should close the menu when clicked outside

we already know how to do this. here's the css:

details[role='menu'] {
  &[open] summary {
    &::before {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 1;
      display: block;
      cursor: default;
      content: ' ';
      background-color: transparent;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

awesome. when we click outside the list is disappearing. so the 1st usecase is fulfilled. but the background is not getting blurred.

2. It should blur the background when menu is visible

very simple add some background color to summary tag when opened.

details[role='menu'] {
  &[open] summary {
    &::before {
       background-color: rgba(0, 0, 0, 0.5);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

super. whenever we clicked on menu icon, the background blurs out. here comes the 3rd usecase.

3. The menu should be displayed along the height of view port

for this we can make the list as fixed and stretch along the height of view port. so let's add some css for ul tag

summary + ul {
    background-color: var(--primary);
    list-style: none;
    padding: 0;
    margin: 0;
    width: 200px;
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    z-index: 2;
}
Enter fullscreen mode Exit fullscreen mode

Good. the list is displaying along the height from left side. but if you see, the transition is sudden. my eyes are hurting. there the last usecase shows up.

4. A subtle animation

keyframes are there for our rescue. let's write a keyframe to animate opacity and width.

@keyframes open {
  0% {
    opacity: 0;
    width: 0;
  }
  100% {
    opacity: 1;
    width: 200px;
  }
}
Enter fullscreen mode Exit fullscreen mode

now let's apply the transition to the list when we click on menu icon.

details[role='menu'] {
  &[open] summary + ul {
    animation: open 0.3s ease-in-out;
  }
}
Enter fullscreen mode Exit fullscreen mode

seriously. it looks cool 😎

Now let's see the entire css

:root {
  --primary: #fff;
  --option-hover-color: #eee;
  --spacing: 1rem;
}

@keyframes open {
  0% {
    opacity: 0;
    width: 0;
  }
  100% {
    opacity: 1;
    width: 200px;
  }
}

details[role='menu'] {
  display: inline-block;

  summary {
    cursor: pointer;
  }

  &[open] summary {
    &::before {
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      z-index: 1;
      display: block;
      cursor: default;
      content: ' ';
      background-color: rgba(0, 0, 0, 0.5);
    }

    & + ul {
      animation: open 0.3s ease-in-out;
    }
  }

  summary + ul {
    background-color: var(--primary);
    list-style: none;
    padding: 0;
    margin: 0;
    width: 200px;
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    z-index: 2;

    li {
      &:hover {
        background-color: var(--option-hover-color);
      }

      a {
        color: #000;
        display: block;
        text-decoration: none;
        padding: var(--spacing);
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

easy peasy right??

Here's the working example

And that's the end of this episode.

See you in next one. Thanks..
Kiran 👋

Discussion (0)