DEV Community

Cover image for Hamburger CSS (no JS)

Hamburger CSS (no JS)

ljcdev profile image ljc-dev ・4 min read



I've made a hamburger menu with no js on codepen and from the feedback, thought it would be useful to explain how.

So here's my 3 steps tutorial on how to code a simple hamburger menu with no js 🙃!


Step 1: Getting familiar with :target


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

The MDN definition says that:

The :target CSS pseudo-class represents a unique element (the target element) with an id matching the URL's fragment.


To put it simply, for target to work there needs to be an anchor id and a link that calls it.

For example a <p> element with an id of home and an <a> link with href=#home like the following:

<p id="home">Home</p>
<a href="#home">Go to Home</a>
  • p:target is active when we click on the <a> link and the page jumps to <p>.

  • we can add a style to it just like we would to :hover or :focus.

Here's a simple CSS to change the color to red when :target is active:

p:target {
  color: red;

We would get the following:

target example 1

  • To make :target inactive we only need to go to another link for example by adding another <a> link that has href="#"
<p id="home">Home</p>
<a href="#home">Go to Home</a>
<a href="#">Go somewhere else</a>

We would get the following:

target example 2

We can see that by clicking on another link :target becomes inactive and the color red is removed.


Step2: Making the html of our hamburger menu


Here's the whole html code:

  <ul class="navbar" id="navbar">
    <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="#">
      <img src="" alt="close">
  <a class="hamburger" href="#navbar">
      <img src="" alt="menu">
  • The ul <ul class="navbar" id="navbar"> holds the hamburger menu and the close image link.

  • It's important to place the close image link inside the hamburger menu because the hamburger menu <ul> will cover the hamburger link button <a class="hamburger" href="#navbar">.

  • Clicking on <a class="hamburger" href="#navbar"> will activate the :target style for <ul class="navbar" id="navbar">

  • Clicking on Home, Profile, About, Contacts and the close image link will deactivate it because they jump to somewhere else.


Step 3: Adding the CSS


I've placed the hamburger and close image links at the top right at the exact same position and added some basic styling:

.hamburger, .close {
  border: none;
  cursor: pointer;
  /* position absolute position the icons relative to the body because they have no position relative parents*/
  position: absolute;
  top: 20px;
  right: 20px;
  width: 36px;
  height: 36px;

.hamburger {
  background: white;

.close {
  background: black;

.hamburger img, .close img {
  width: 100%;
  height: 100%;

Then I added some styling to the hamburger menu <ul class="navbar" id="navbar">

.navbar {
  position: absolute;
  /* a higher z-index put navbar above hamburger */
  z-index: 1000;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  overflow: hidden;
  /* basic menu styling*/
  list-style: none;
  background: black;
  display: flex;
  flex-flow: column nowrap;
  justify-content: space-evenly;
  align-items: center;
  /* animate slide up/down */
  transform: translateY(-100%);
  transition: transform 0.2s ease;
  • position: absolute; get the hamburger menu out of the page context. We make it cover the whole screen with
    top: 0; left: 0; width: 100%; height: 100vh;

  • z-index: 1000; put the hamburger menu aboves everything else including the hamburger image link. So the close image link inside the hamburger menu is right above the hamburger image link.

  • transform: translateY(-100%); hides the hamburger menu above the screen by default.

  • transition: transform 0.2s ease; will animate changes in the transform property.

Finally we show the menu by adding transform: translateY(0); to the :target which will put the menu back at its original position.

.navbar:target {
  /* show navbar */
  transform: translateY(0);

After adding some more styling to the menu links we get:




... is what I want to shout but I think this tutorial is a bit rushed and could be better. You can ask me if you don't get anything here or on twitter 😄.

Thanks for reading!

  • Shout out to Belev Martin who told me to animate transform instead of height because it has GPU support so less likely to be laggy.

  • And many thanks for all of the feedback to this codepen on Twitter 🥰.


Editor guide
adam_cyclones profile image
Adam Crockett
.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.

ljcdev profile image
ljc-dev Author

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.

ljcdev profile image
ljc-dev Author

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 😅.

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 Author

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

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.