Skip to content

Instantly share code, notes, and snippets.

@naganowl
Last active August 29, 2015 13:57
Show Gist options
  • Save naganowl/9559809 to your computer and use it in GitHub Desktop.
Save naganowl/9559809 to your computer and use it in GitHub Desktop.
  • The entire hamburger element is a link with a span, where the span has a before and after pseudo-element.
  • The center bar is the actual span, whereas the top and bottom are the before and after pseudo-elements respectively.
  • The top and bottom bars are positioned to the center and rotated to create the X.
    • For some reason, the top bar rotates seamlessly while the bottom one is a bit jittery, even after specifying a bottom attribute.
    • The bars need to be rotated from the center due to the default transform-origin. The positioning may be removed if we specify a different origin at the expense of lower browser support at the time of writing.
    • The bottom bar rotation can be accomplished by adding a translateY(-10px) and top: 10px to force the transition to kick in and have it visually rotate from the bottom.
      • See this CodePen for an example of it in action.
  • The middle bar could be rotated with the bottom bar faded away, but the top bar rotation would need to be recalculated since the pseudo-elements are contained within the element and would be subsequently rotated as well.
  • Each bar could also be redone as individual spans for greater flexibility, but at the cost of being more explicit in DOM.

UPDATE: I played around with another implementation that was a bit snappier. Here are some notes on what I discovered.

  • Elijah's version is simple and uses CSS transitions which allows us to piggy back off existing CSS selectors and avoid having to add our own.
  • Strunk's version uses animations which gives us keyframes, allowing for more flexibility in what the animation does. However, this comes at the cost of needing an explicit activation class for each animation if the animation should be gated behind some action/event such as a click. You can see this in Strunk's implementation because there is a flicker when the page is loaded.
    • This post demonstrates how to do it without the animation flicker by using extra classes and toggling between them as necessary.
    • The extra example below is a modified version of Strunk's implementation to use transforms instead of positioning. I felt that would degrade more gracefully in case a given browser didn't support animations. Also, it keeps it consistent with the transition implementation.
.navbar-toggle .icon-bar
transition all 300ms
&:nth-child(2)
animation topbar-x 500ms
animation-fill-mode both
&:nth-child(3)
background-color transparent
&:last-child
animation bottombar-x 500ms
animation-fill-mode both
.collapsed .icon-bar
&:nth-child(2)
animation topbar-back 500ms
animation-fill-mode both
&:nth-child(3)
background-color #fff
&:last-child
animation bottombar-back 500ms
animation-fill-mode both
@keyframes topbar-x
0%
transform rotate(0deg)
45%
transform translateY(7px) rotate(145deg)
75%
transform translateY(7px) rotate(130deg)
100%
transform translateY(7px) rotate(135deg)
@keyframes topbar-back
0%
transform rotate(135deg)
45%
transform rotate(-10deg)
75%
transform rotate(5deg)
100%
transform rotate(0)
@keyframes bottombar-x
0%
transform rotate(0deg)
45%
transform translateY(-5px) rotate(-145deg)
75%
transform translateY(-5px) rotate(-130deg)
100%
transform translateY(-5px) rotate(-135deg)
@keyframes bottombar-back
0%
transform rotate(-135deg)
45%
transform rotate(10deg)
75%
transform rotate(-5deg)
100%
transform rotate(0)
.navbar-toggle .icon-bar
transition all 500ms ease-in-out;
&:nth-child(2)
transform translateY(7px) rotate(45deg)
&:nth-child(3)
background-color transparent
&:last-child
transform translateY(-5px) rotate(-45deg)
.collapsed .icon-bar
&:nth-child(2)
transform rotate(0deg)
&:nth-child(3)
background-color #fff
&:last-child
transform rotate(0deg)
%button.navbar-toggle.collapsed{:type=> 'button', :'data-toggle' => 'collapse', :'data-target' => '.navbar-collapse'}
%span.sr-only Toggle navigation
%span.icon-bar
%span.icon-bar
%span.icon-bar
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment