How they made controls at Github? Hamburger menu
Kiran Mantha
Posted on January 8, 2022
- Episode1: Dropdown
- Episode2: Modal dialog
- Episode3: Hamburger menu
- Episode4: Popup
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>
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>
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);
}
}
}
}
hmm still an accordian to me 😐
then lets see the criteria for hamburger menu
- It should close the menu when clicked outside
- It should blur the background when menu is visible
- The menu should be displayed along the height of view port
- 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;
}
}
}
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);
}
}
}
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;
}
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;
}
}
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;
}
}
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);
}
}
}
}
easy peasy right??
Here's the working example
And that's the end of this episode.
See you in next one. Thanks..
Kiran 👋
Posted on January 8, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.