Julien Melissas

Animated “x” icon for the Bootstrap navbar-toggle

Introduction

Julien Melissas

Julien Melissas

I'm a Web Developer, Foodie, and Music Lover/Maker living in Asheville, NC. I make things on the web at Craftpeak & JM Labs.


LATEST POSTS

fRamen: “Fancy” Instant Ramen 16th October, 2017

Nomading 2016: I suck at travel blogging – London & Berlin 20th June, 2017

Code

Animated “x” icon for the Bootstrap navbar-toggle

Posted on .

There are lots of posts online about that trendy (and awesome) transition from the hamburger icon (when the menu is collapsed) to that “x” (when the mobile menu has been expanded). This should be pulled off by CSS3 animations, of course.

You can see some awesome examples of the concept and some cool implementations here:

I’m not here to reinvent the wheel. I’m not here to blow your mind. I’m not here to tell you I figured out a better way to do it (I didn’t).

I’m actually just going to show you how it works, and how you can easily incorporate it into your next project using Bootstrap’s regular navbar-toggle element and a little bit of extra code.

How it works:

First of all, lets look at how Bootstrap’s menu already works: 3 spans inside a button, as well as a screen reader element. Keep in mind that the menu is collapsed currently. When you click it and it expands the menu, it takes away the collapsed class. This code is pulled straight from one of Bootstrap’s examples:


<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
  <span class="sr-only">Toggle navigation</span>
  <span class="icon-bar"></span>
  <span class="icon-bar"></span>
  <span class="icon-bar"></span>
</button>

It looks like this:

 See the Pen ogMbGo by Julien Melissas (@JulienMelissas) on CodePen.0

Lets add some classes so we can distinguish the bars from each other, so we can easily perform the animations:


<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
  <span class="sr-only">Toggle navigation</span>
  <span class="icon-bar top-bar"></span>
  <span class="icon-bar middle-bar"></span>
  <span class="icon-bar bottom-bar"></span>
</button>

So this is how the animation should work, play by play:

  • The right side of the top bar animates down.
  • The middle bar fades out.
  • The right side of the bottom bar animates up.

Now, we just need to add some Less (Bootstrap’s native language, mind you) to help define some of the animation rules. Remember, by default the .navbar-toggle button has the .collapsed class when the icon is in it’s “bar” state, so we’re going to have to define the animated “x” position as the default position:


.navbar-toggle {
  border: none;
  background: transparent !important;

  &:hover {
    background: transparent !important;
  }

  .icon-bar {
    width: 22px;
    transition: all 0.2s;
  }
  .top-bar {
    transform: rotate(45deg);
    transform-origin: 10% 10%;
  }
  .middle-bar {
    opacity: 0;
  }
  .bottom-bar {
    transform: rotate(-45deg);
    transform-origin: 10% 90%;
  }
}

Let me quickly explain what’s going on above:

  • Make the bootstrap toggle have no background or border (I really don’t like the look usually).
  • Give the icons a set width and CSS3 transition time.
  • The transform-origin property defines in what place the animation stems from. We’re going to set .top-bar to mostly start in the top left, and the .bottom-bar to mostly start in the bottom right. (you can read more about transform-origin here)
  • The .top-bar will animate down 45 degrees and the .bottom-bar will animate up 45 degrees.
  • The .middle-bar will “fade-out” and not show when the navbar is open, so give it an opacity of 0. Opacity is one of the cheapest/easiest things for the browser to animate.

If you’re following along at home then your bar just looks like an “x”.

Let’s add the “default” hamburger styles to fix that. These get activated and applied by default because the page usually loads with the menu collapsed and the .collapsed class already added.


.navbar-toggle.collapsed {
  .top-bar {
    transform: rotate(0);
  }
  .middle-bar {
    opacity: 1;
  }
  .bottom-bar {
    transform: rotate(0);
  }
}

All we’re doing above is reseting the rotate properties and making sure that the opacity of the .middle=bar is set to 1.

That’s it.

Seriously, pull this demo up in your phone and check it out, or just see below:

 See the Pen LEBGLj by Julien Melissas (@JulienMelissas) on CodePen.0

 

Update:

Thanks to Scott’s comment below, I wanted to mention if you don’t have anything automatically adding browser prefixes for you (like autoprefixer or the like) – and you’re wondering why it’s not working, you need to add those for the transforms:

Don’t forget to add the -ms-transform, -ms-transform-origin, -webkit-transform, and -webkit-transform-origin properties to your CSS to get this to work on iDevices and others.

Julien Melissas

Julien Melissas

http://www.julienmelissas.com

I'm a Web Developer, Foodie, and Music Lover/Maker living in Asheville, NC. I make things on the web at Craftpeak & JM Labs.

  • Jay Deutsch

    This is great. Thanks. Only issue is if you have a border around the button, the X is off center…

    • Julien Melissas

      Hey Jay, glad you like this. Yes, there are actually 2 reasons why I excluded the border in this demo:
      1.) I don’t like the border in most cases. In fact, on most projects if I’m still using the BS toggle I make the actual button area larger so that there is more space for the user to tap
      2.) In this animation, forming the x actually moves the toggle bars to the left, as the transform-origin is set to the left side. If you wanted it to be centered, you’d have to do some more work making the transform and transform-origins work a bit more for you. This was a simple tutorial 😉

  • Chris Kanze

    Thank you brotha!

  • Chris Byrne

    Thanks for this, saved me a lot of brain power, yet so simple. Fabulous!

    • Julien Melissas

      yay!

  • Alex

    Great article! Nicely explained, saved me a lot of time.

  • Scott Glime

    Don’t forget to add the -ms-transform, -ms-transform-origin, -webkit-transform, and -webkit-transform-origin properties to your CSS to get this to work on iDevices and others. This is just what I needed. Such a cool effect and you made it so easy to implement. Thanks!

    • Julien Melissas

      Thanks for the pointer Scott. With all of my build processes I use tools like Pleeease and autoprefixer with Grunt or gulp as to keep my code clean so I don’t have to write all of those – but it’s a good thing to mention!

      • Scott Glime

        I couldn’t figure out why the effect wasn’t working on my iPhone. A quick Google search brought me to http://www.w3schools.com/cssref/css3_pr_transform.asp *gasp* and it all became clear. Thanks so much for the post!

        • Julien Melissas

          Totally! I’ll add a small update to the post – thanks for bringing it up.

          • Thanks for adding that to the end of the post – I develop in Chrome and couldn’t work out why it wasn’t working for a colleague in Safari!

          • Hi Julien,

            Is it possible for you to paste the code with the prefixes? I am just the beginner in front-end web development and I just want to make sure that I have added these prefixes to the right place. Thanks in advance.

          • Julien Melissas

            I highly recommend using this service to help you figure out the proper code, if you don’t use anything to help with this automatically: https://autoprefixer.github.io/ – it’s too long to paste here in the comments.

      • Hi Julien,

        Is it possible for you to paste this code with these prefixes? I got your animation to work on my computer but I am not too entirely sure how and where to add these prefixes so that this effect would work across all devices.

        Thank you very much in advance.

  • dopli site

    hello can you do a tutorial on the 3 minutes left/2 minutes left think you have on this webpage. Thats really cool

  • Louis Cruz

    Thanks for the great article.

    I was using a ripple effect in a project with this animation, so it became clear that the X needed to be centered. With a little bit of geometry, you can center the “X”.

    Since the transformation is at 45 degrees, you know that the resulting length will be 70.71% of the original length. Since we set the length at 22px, we know that the resulting horizontal length will be about 15.56px. That’s a difference of about 6.4 px. Divide the difference by 2, and you can translateX both bars by that amount.

    transform: translateX(3px) rotate(45deg);

    and the following for the bottom-bar:

    transform: translateX(3px) rotate(-45deg);

    If you choose a different bar length, just rework the math, and it’ll be centered. Of course, use the correct browser prefixes.

  • xavier

    Very clear tutorial!

  • Sawyer

    FYI – Not working on samsung stock browser with android 4.3. Seems like samsung browser not support pseudo css. Hopeless browser that should burn in H**l 🙂

  • Nick Courage

    If I include more than one value for the data target attribute, either as multiple IDs (separated by commas) or a class used by more than one element, the animation doesn’t work. Is there anyway around this?

    • Julien Melissas

      I’m sure there is! Can you make a codepen (you can fork mine) and give me an example?

  • Julien Melissas

    Moon, do you have an example you can link to online? I can’t help much without that.

  • Mark

    Great solution! I added a transition to the middle bar for an extra fading effect. Personal preference 😉

    opacity: 0;
    transition: opacity .25s ease-in-out;

    (collapsed)
    opacity: 1;
    transition: opacity .25s ease-in-out;

  • greggergalactic

    Great effect! Any chance of seeing this in CSS rather than Less?

  • sadegh

    hi i have one qustion! how i can use dropdown toggle

    Instead of navbar-toggle

  • Riley Jones

    Awesome! Simple solution. Thank you!

  • Zach

    Thanks for this! Saved me a bunch of time and tinkering.

  • RitterJack

    Hello, when i click button, the collapsed class is not remove automaticlly

    • Dhiroo Verma

      add javascript or jquery for removing and adding class on button click

      function toggle() {
      var toggleClasses = document.getElementById(“toggle_style”).classList;
      if (toggleClasses.contains(“toggle_style”)) {
      toggleClasses.remove(“toggle_style”);
      } else {
      toggleClasses.add(“toggle_style”);
      }
      }

  • Anurag Priyadarshi

    thanks a lot. you really made it simple.

  • Cheri Schappaugh

    it is Fabulous! Enjoy so much. Many thanks!

  • niti

    Great explanation. Thank you a lot Julien!

  • Tine Sitar

    Maestro! Thank you very much for this article. You just open my mind! Rescpet man! Do you have some donate option here in your website(blog)?

  • Andy Pohl

    Right on! Just used this tutorial, and it worked like the charm. Cheers

View Comments (40) ...
Navigation