How they made controls at Github? Hamburger menu
Tags: javascript, html, css, github
Published: 2022-01-08 03:37:34

- Episode1: [Dropdown](https://dev.to/kiranmantha/how-they-made-controls-at-github-1h18)
- Episode2: [Modal dialog](https://dev.to/kiranmantha/how-they-made-controls-at-github-modal-dialog-2pgi)
- Episode3: **Hamburger menu**
- Episode4: [Popup](https://dev.to/kiranmantha/how-they-made-controls-at-github-popup-2omi)

## 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
```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>
```
then where is ham :laughing:. For that let's add mayonise.. i mean `svg` to add ham to above burger
```html
<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>
```
ahhh there's our ham :heavy_plus_sign: burger :smile:. But... hey that's an accordion.
i know :exclamation: i know :exclamation:
don't worry. here is the styling:
```scss
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);
      }
    }
  }
}
```

hmm still an accordian to me :neutral_face:
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 :sunglasses:

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

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:
```scss
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;
    }
  }
}
```
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.
```scss
details[role='menu'] {
  &[open] summary {
    &::before {
       background-color: rgba(0, 0, 0, 0.5);
    }
  }
}
```
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 
```scss
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;
}
```
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.

```scss
@keyframes open {
  0% {
    opacity: 0;
    width: 0;
  }
  100% {
    opacity: 1;
    width: 200px;
  }
}
```
now let's apply the transition to the list when we click on menu icon.

```scss
details[role='menu'] {
  &[open] summary + ul {
    animation: open 0.3s ease-in-out;
  }
}
```
seriously. it looks cool :sunglasses:

Now let's see the entire css
```scss
: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);
      }
    }
  }
}
```

easy peasy right?? 

Here's the working [example](https://stackblitz.com/edit/details-summary-tag-based-controls?file=style.scss)

And that's the end of this episode. 

See you in next one. Thanks..
Kiran :wave: