Grow your CSS skills. Land your dream job.

Line Menu Icon… That Is A Menu

Published by Chris Coyier

I had a dumb little idea the other night so I just coded it up (as you do). You know those little icons that have come represent navigation? We've called them Three Line Menu icons around here, but otherwise known as Navicon (clever) or Hamburger (dumb). The point of that icon is that it looks like a little menu, so hopefully it's obvious you click it to reveal a real menu. But what if that icon wasn't an icon at all, but the actual menu, just shrunken?

The Concept

Yep, it's a little cheezy.

The trick is very easy though. It largely relies on CSS transform and transition, and a few more basics.

The process is essentially:

  1. Design full size view first
  2. Shrink entire thing to icon size with transform: scale(0.X);
  3. Remove unnecessary bits with opacity: 0
  4. When in icon size, only react to clicks on the whole thing.
  5. When clicked, toggle to transform: scale(1), hidden bits to opacity: 1, and restore normal clicking ability.

Here's the design bits:

Changing State

Changing the "state" (expanded or not) of menu you could do in any number of ways. Perhaps the checkbox hack or real easy-like with jQuery:

$(".main-nav").on("click", function() {
  $(this).toggleClass("open");
  return false;
});

All we're doing is changing a class here, which is the way to go for sure.

The CSS

I particularly like Sass when dealing with states because you can nest the states within the same block.

.main-nav {
  /* Animate the state change */
  transition: 0.3s ease;
  transform: 
    /* Make mini */
    scale(0.1) 
    /* Hot performance 10x hack */
    translateZ(0);
  /* The open state */
  &.open {
    transform: scale(1.0);
  }
}

Handling Clicks

The clicking thing is a little funky. We need to make sure that

  • Clicking the icon version simply opens the menu
  • Clicking menu items inside while open work
  • There is a way to close it

We already have the jQuery in place that toggles the class when you click anywhere on the entire element. That can stay just like that. We just need to make sure that if you happen to click exactly one of those those tiny little lines inside the mini icon, you don't actually go to that link.

All those links are in a <ul>, so one way to handle that is to use CSS to make that entire thing un-clickable by default (minified), but clickable when in the open state.

.main-nav {
  ul {
    pointer-events: none;
  }
  &.open {
    ul {
      pointer-events: auto;
    }
  }
}

While pointer-events is awesome, a noticeable gap in support is IE 10 (11 does support it though). You may instead want to use an additional <div> that you use to cover the entire thing when in the default (minified) state and just remove it when in the open state.

Closing It

The way we handle closing is to add a close button:

<button class="close-button">
  <b class="visually-hidden">Close</b>
  <span aria-hidden="true">
    ×
  </span>
</button>

We wanted to use the × character there as essentially an icon. But that has no meaning when read (or if it does, it's "multiply"). So we hide that from being read and include a more readable word that is visually hidden (kicked off page with positioning). Standard procedure for using icons.

In our simple example, we don't even need to bind an event handler directly to this button, because we already have one attached to the entire parent element that toggles that open state. If you click this button, that event will bubble up and fire that event and do the job. That might be weird, so feel free to adjust and bind directly to the element.

Semantics?

While this <button> doesn't exactly make my skin crawl, we could endless debate about it. (example conversation). It's meaningless without JS enabled, so should we insert it with JS? Should we have made it an anchor link with an href back to the top of the page? Is <button> still the correct element?

Progressive Enhancement?

While we're just having fun here, we might consider tackling this via progressive enhancement. That is, start with a menu that is completely functional as markup alone. Then level up all the fancy stuff as support is available.

Fortunately, our markup already mostly in good shape. I do think <button> is the correct element for our close button, since there is no "meaningful href", but it should be inserted with JS since it only has functionality with JS. Very simply, that might look like:

$('<button class="close-button">\
    <b class="visually-hidden">Close</b>\
    <span aria-hidden="true">\
      ×\
    </span>\
  </button>').appendTo(".main-nav");

Another concern is that we approached the CSS in such a way that the default state is with the menu closed. And that "closed" state essentially relies on a CSS transform shrinking it. If CSS transforms aren't supported, the menu will appear open, overlapping content and unable to be closed (bad). If our menu didn't overlap content, we might be OK, but since it does we would be better off only applying our fancy styling should be browser support our fancy CSS needs.

There are countless ways to approach this, but a fairly easy and standard way is to detect support of the relevant technologies via Modernizr. If what we need is there, there will be a class name telling us that on the <html> element, and we can use that to apply the fancy.

.main-nav {
  /* Default, visible, accessible styling */
}
.csstransforms .main-nav {
  /* Bring the fancy */
}

IE 8 doesn't support CSS transforms, so:


None the wiser.

There I go again, turning a dumb little demo into a lesson. Here's the final deal:

See the Pen Line Menu Icon that Expands Into Actual Menu by Chris Coyier (@chriscoyier) on CodePen

Other Ideas?

Perhaps this exact idea is cheezytown, but I do like the idea of the thing you click on being a part of what is revealed. It's kind of like how animations can be used to make an action more clear, having a single point of focus during those animations can also help. For instance:

See the Pen owgLF by Chris Coyier (@chriscoyier) on CodePen

Comments

  1. You’re completely crazy…Oh my God, I love this idea!

  2. Permalink to comment#

    That is extremely cool! CSS transitions are like magic.

  3. Alan Cece
    Permalink to comment#

    I like the basic premise of the idea, but I don’t like that depending on how many items might be in your navigation it changes the overall look of the closed icon. I think the convention is the 3 lines, not that this can’t be strayed from, but it looks a bit ridiculous with 5 or 7 lines.

    • So you know how we hid a variety of elements in the minified version to make it look more icon-like. You could just hide any of the menu items above 4, like :nth-child(n+4) see recipies

  4. One more way to create collapsable nav menu for responsive design.Impressive!

  5. css geek
    Permalink to comment#

    very helpful :) thanks:)

  6. Casper Sørensen
    Permalink to comment#

    Hey Chris,

    Great concept, and a very cool execution :)

  7. Jeanette
    Permalink to comment#

    Love this.

  8. Camaron
    Permalink to comment#

    I like it, it has some transition effects that are very relevant on how to do some basic expands. Well done!!

  9. Hey Chris, I love the concept that you have going here. The idea of expanding an icon into an interactive piece of UI could extend so far beyond just menu icons! Thanks for the inspiration ( for this post and all the posts prior )!

    Happy Holidays, sir.

  10. alhoseany
    Permalink to comment#

    Brilliant.

  11. Permalink to comment#

    LOVE IT!!! I know what I’ll be doing tonight!

  12. Patrick Denny
    Permalink to comment#

    Here’s a version that uses a label as close-button and a hidden checkbox to toggle the menu on and off without using any extra script or inserted tags.

  13. Otto Perdomo
    Permalink to comment#

    Very interesting, nice post! thanks!

  14. Permalink to comment#

    Love it, kind of reminds me of a new concept like Path’s menu was when they released it. Would be pretty easy to make this work on responsive sites which is exciting.

  15. I don’t know why and know that it will sound dumb but, it looks more natural to me :)

    • Permalink to comment#

      Not dumb at all. In fact, this is kind of animation that UX engineers try to implement in their software solutions. The closer you can get to approximating real-life interactions, the more familiar it will be and the more natural it will become.

      The tabs on your browser still looks like a bunch of paper folder tabs, after all.

  16. Permalink to comment#

    Chris, I think your “dumb little demo” is actually a really nice concept.

    I do agree with Alan Cece that perhaps limiting it to a consistent three or four items is probably a good idea.

    I also found I preferred it when I changed the CSS in your pen so that the text was actually visible (although at that scale, not readable) in the icon-state. The connection between the icon and expanded menu became clearer.

  17. jamie
    Permalink to comment#

    A great idea, the transition is wonderful. I’m a big fan of this type of transition, a bit like this one:

    http://media.smashingmagazine.com/wp-content/uploads/2013/10/Stateful-toggle.gif

    from this article.

    However, I’m not sure the hamburger/navicon it’s as universally recognised yet to use as a icon on it’s own. A close symbol or a search magnifying glass have been around as long as computers have had GUIs and are a part of pretty much every OS out there.

    This is much newer, so I’d prefer to use it with a tag saying “menu” or similar.

  18. Permalink to comment#

    Very nice idea!
    Maybe I’ll stick with it in an upcoming project.
    Thanks for sharing!

  19. ikarar
    Permalink to comment#

    Very nice idea!
    really nice concept.
    Thanks for sharing!

  20. Richard
    Permalink to comment#

    It’s people like you who always inspire me to keep trying new things. That is so unique and awesome, I’ve never seen anything similar.

  21. Vimal Raj
    Permalink to comment#

    Very inspiring one. Thanks for sharing it.

  22. Jacob
    Permalink to comment#

    I like this idea a lot, Chris. It is very creative.

    It really makes me wonder what other scenarios would call for drawing something with markup and CSS and scaling it down to the size of an icon. For example, the typical speech bubble “comment” icon could be a scaled down version of a styled text area that becomes large enough to use when you click on it.

  23. Permalink to comment#

    Cool project!

  24. Joe
    Permalink to comment#

    I think “hamburger” is dumb too! Love this. Thanks Chris!

  25. sheriffderek
    Permalink to comment#

    I am excited for the day when the browser can handle this and doesn’t make all of the other text and lines on the page change weight or blink during transitions. This is no doubt awesome, but I have yet to see an animation so awesome that it trumps that darn blinking. Are there any hardware execrating-like tricks that can stop this from happening? It’s so close!

  26. sally
    Permalink to comment#

    i really this idea, and i try it by myself and keep the code the same as you showed , it doesn’t work. could you send me the whole code? Thank you so much

    • Magnus
      Permalink to comment#

      I second that. I’ve been trying to get it to work but I’m to much of a newbie to manage to succeed

  27. Permalink to comment#

    I actually really like the concept, maybe this could work better on a mobile layout. I love the way all element are contained and using just transitions.

  28. Permalink to comment#

    Idea is cool, think this will be future trend.

  29. Vimal
    Permalink to comment#

    This works only when I use with inline style. The menu box is not displayed properly when I have my css in a file and linking to my html file. Spent about an hour, but couldn’t find why?

  30. Ramesh Chowdarapally
    Permalink to comment#

    Wow. It’s magical…. Let me start R & D… :)

  31. chris lee
    Permalink to comment#

    like this idea a lot, Chris. It is very creative.

    It really makes me wonder what other scenarios would call for drawing something with markup and CSS and scaling it down to the size of an icon. For example, the typical speech bubble “comment” icon could be a scaled down version of a styled text area that becomes large enough to use when you click on it.

  32. rene van der lende
    Permalink to comment#

    Hi,

    I love the simplicity and ease, but somehow I can’t get this to work outside Codepen working with Chrome 33+ (well, I AM an NOOB). Does anyone care to elaborate on this.

    put it all in one html, won’t work
    all in separate files (css, js, html) won’t work either
    used jquery 2.1.0

    thanks, rene

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".