Code
Animated “x” icon for the Bootstrap navbar-toggle
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:
- http://sarasoueidan.com/blog/navicon-transformicons/
- http://www.elijahmanor.com/css-animated-hamburger-icon/
- http://codepen.io/pedrocampos/details/gufrx
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
https://www.julienmelissas.comI'm a Web Developer, Foodie, and Music Lover/Maker living in Asheville, NC. I make things on the web at Craftpeak & JM Labs.