DEV Community

Cover image for Hamburger CSS (no JS)
ljc-dev
ljc-dev

Posted on • Updated on

Hamburger CSS (no JS)

I put together this short tutorial on how to make a hamburger menu with no js in response to the feedback on my original Twitter post.

Enjoy 😁!

:target

Have you heard of the CSS pseudo-class on :target?

It styles the element with an anchor id that that has been called by a link.

For example, a p with an id of home and an a link with href=#home:

<p id="home">Home</p>
<a href="#home">Go to Home</a>
Enter fullscreen mode Exit fullscreen mode
p:target {
  color: red;
}
Enter fullscreen mode Exit fullscreen mode

target example 1

When we click on the a link, the text of the targeted p changes to red.

By clicking on another link, the :target style gets hidden.

<p id="home">Home</p>
<a href="#home">Go to Home</a>
<a href="#">Go somewhere else</a>
Enter fullscreen mode Exit fullscreen mode

target example 2

Here's the whole html code.

I'm using material icons by adding their cdn in the head of the html file.

<head>
  <!-- ... -->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
Enter fullscreen mode Exit fullscreen mode
  <ul class="menu" id="menu">
    <li><a href="#">Home</a></li>
    <li><a href="#">Profile</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contacts</a></li>
    <a class="close" href="#">
    <span class="material-icons">
      close
    </span>
    </a>
  </ul>
  <a class="hamburger" href="#menu">
    <span class="material-icons">
      menu
    </span>
  </a>
Enter fullscreen mode Exit fullscreen mode

Material icons work by defining a span with material-icons class and adding a keyword between the tags:

  <span class="material-icons">
    close
  </span>
Enter fullscreen mode Exit fullscreen mode
  • The ul has an id of menu. It holds the menu and the close icon link.

  • The a with a class of hamburger has a href #menu, clicking on it will show the on :target style for the ul menu.

  • Clicking on other links (Home, Profile, About, Contacts) and the close link will remove the on :target style of the ul.

Now we just need to add a sprinkle of CSS ✨.

The hamburger link has a position fixed to get it out of the flow of the page.

The menu has a position fixed too and a bigger z-index than the hamburger link to put the menu above the link.

For consistency, I've put the hamburger and close links on the same corner.

.hamburger {
  position: fixed;
  /* a large z-index puts the ham button above the rest of the page*/
  z-index: 99;
  background: white;
  border: none;
  cursor: pointer;
  top: 1rem;
  right: 1rem;
}

.menu {
  position: fixed;
  /* give the menu a larger z-index than the ham link
  to put the menu above it */
  z-index: 100;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100vh;
  /* basic menu styling*/
  list-style: none;
  background: black;
  display: flex;

  flex-direction: column;
  /* animate slide up/down */
  transform: translateY(-100%);
  transition: transform 0.2s ease;
}

.close {
  position: absolute;
  border: none;
  color: white;
  cursor: pointer;
  top: 1rem;
  right: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

The menu is hidden by default with transform: translateY(-100%);. Translating -100% on the Y axis moves it 100% up above the screen.

By adding a transition transition: transform 0.2s; on transform we get a small slide in and out animation when the value of transform translateY changes.

And we reset the translation Y to 0 and show the menu on :target.

.menu:target {
  /* show menu */
  transform: translateY(0);
}
Enter fullscreen mode Exit fullscreen mode

Thanks for reading 😄!

  • Thanks Martin for telling me to animate transform instead of height to get GPU support.

Latest comments (7)

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀 • Edited
.navbar {
    will-change: transform;
}
Enter fullscreen mode Exit fullscreen mode

You will see a slightly smoother transform.

Also my issue with this technique is backwards navigation will continually open and close the menu if I clicked it a few times, it's in my history 😬.

Lastly you can embed codepen here on dev, you can even share it from codepen via their sharing mechanisms.

Collapse
 
ljcdev profile image
ljc-dev

Didn't see the last part 😅, thanks for the tip!! Didn't know that was possible. Will try for sure next time 😀. Btw, are there shortcuts for emojis here? I'm copying and pasting from emojipedia 😅.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

I blog on my phone 99% of the time so I couldn't say, no markdown shortcuts but you should check the guide when you post. Lots of nice tips.

Collapse
 
akhilarjun profile image
Akhil Arjun

If you are on windows 10 just press win +.. It will open a built in emoji keyboard

Thread Thread
 
adam_cyclones profile image
Adam Crockett 🌀

If on a Mac with a touch bar you can say "so that's what this thing is good for" - "glad I didn't buy this machine" and use that.

Thread Thread
 
ljcdev profile image
ljc-dev

Lol 🤣🤣 .
Thx Akhil 😁! I'm using win.

Collapse
 
ljcdev profile image
ljc-dev

True 😅. Thanks for the precious feedback! That IS a drawback. And I don't think it can be avoided because it's using links so the url is always going to get changed 🤔.
Will try "will-change" thx, haven't heard of it before.