Thomas Lancy
Thomas Lancy

Reputation: 83

Rotate a SVG hamburger icon into an X?

I've designed a 3-bar icon using pure SVG code in HTML. I'm using CSS3 transforms to rotate the top & bottom bars into an X shape. The problem is that they rotate around their own center, but I need them rotating around the icon's center. To get around this I've adjusted their X/Y coordinates.

This causes a LOT of buggy issues with Internet Explorer, Firefox, & Safari. Chrome seems to be alright but obviously I'd like to code this the "right" way so it'll work in all browsers.

Here's my live CodePen

HTML

<svg id="burgericon" xmlns="http://www.w3.org/2000/svg" width="90" height="80">
  <g class="icon">
    <rect class="frstbar" x="10" y="10" width="70" height="12" rx="7" ry="7" fill="#414141"/>
    <rect class="scndbar" x="10" y="35" width="70" height="12" rx="7" ry="7" fill="#414141"/>
    <rect class="thrdbar" x="10" y="60" width="70" height="12" rx="7" ry="7" fill="#414141"/>
  </g>
</svg>

CSS

.hamburger { display:block; text-align:center; }
svg { cursor:pointer; }

.frstbar, .scndbar, .thrdbar {
  -webkit-transition: all 0.35s linear;
  -moz-transition: all 0.35s linear;
    -o-transition: all 0.35s linear;
    transition: all 0.35s linear;
}
#burgericon.open .frstbar {
  -webkit-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  transform: rotate(45deg);
}
#burgericon.open .thrdbar {
  -webkit-transform: rotate(-45deg);
  -ms-transform: rotate(-45deg);
  transform: rotate(-45deg);
}
#burgericon.open .scndbar { width: 0; opacity: 0; }

JS

$('#burgericon').on('click', function(e) {

  if($(this).attr('class') != "open") {
      $(this).attr('class','open');
      $('.frstbar').attr('x','25').attr('y','-5');
      $('.thrdbar').attr('x','-35').attr('y','55');
    } 
  else {
    $(this).attr('class','default');
    $('.frstbar').attr('x','10').attr('y','10');
      $('.thrdbar').attr('x','10').attr('y','60');
    }
});

I also think changing the X/Y coords is causing a blurry effect. I've added a screenshot below. First you'll see the completed X icon and then you'll see how it looks when animated back to default.

The bars aren't perfectly straight but instead they look crooked for some reason.

Screenshot here

I'm still new to SVG manipulation so I'm not sure how to properly rotate <rect> elements with CSS3/JS. Any help or tips in the right direction would be more than appreciated.

Upvotes: 8

Views: 5176

Answers (2)

web-tiki
web-tiki

Reputation: 103810

You can remove the JS positioning by using the CSS transform-origin property. You can set it on the left of the first and second bars with transform-origin: 0 50%;.

This way they will cross each other when they are rotated :

document.getElementById('burgericon').addEventListener('click', function (e) {
    this.classList.toggle('open');
});
.hamburger {
  display: block;
  text-align: center;
}
svg {
  cursor: pointer;
}
.frstbar,.scndbar,.thrdbar {
  transition: all 0.35s linear;
  transform: rotate(0deg);
  transform-origin: 0% 50%;
}
#burgericon.open .frstbar {
  transform: rotate(45deg);
}
#burgericon.open .thrdbar {
  transform: rotate(-45deg);
}
#burgericon.open .scndbar {
  width: 0;
  opacity: 0;
}
<nav class="hamburger">
  <svg id="burgericon" xmlns="http://www.w3.org/2000/svg" width="90" height="80">
    <g class="icon">
      <rect class="frstbar" x="10" y="10" width="70" height="12" rx="7" ry="7" fill="#414141" />
      <rect class="scndbar" x="10" y="35" width="70" height="12" rx="7" ry="7" fill="#414141" />
      <rect class="thrdbar" x="10" y="60" width="70" height="12" rx="7" ry="7" fill="#414141" />
    </g>
  </svg>
</nav>
<div>
</div>

Credits to David Thomas for the JS

Note that the transform-origin property needs the same vendor prefixes as the transform property. I have omited them for both in the above snippet

Upvotes: 8

Persijn
Persijn

Reputation: 15000

CSS

Using css transform: rotate() I rotated the elements so they form the X
Using css opacity and transitions; made the object gradually go transparent.

.icon {
  stroke: none;
  fill: #777;
}
.icon .frstbar {
  transform-origin: 10% 50%;
  transition: transform 1s;
}
.icon:hover .frstbar {
  transform: rotate(45deg);
}
.icon .thrdbar {
  transform-origin: 10% 50%;
  transition: transform 1s;
}
.icon:hover .thrdbar {
  transform: rotate(-45deg);
}
.scndbar {
  opacity: 1;
  transition: opacity 1s;
}
.icon:hover .scndbar {
  opacity: 0;
}
<svg id="burgericon" xmlns="http://www.w3.org/2000/svg" width="90" height="90" viewBox="0 0 100 100">
  <g class="icon">
    <rect class="frstbar" x="10" y="10" width="90" height="12" rx="7" ry="7" />
    <rect class="scndbar" x="10" y="35" width="90" height="12" rx="7" ry="7" />
    <rect class="thrdbar" x="10" y="60" width="90" height="12" rx="7" ry="7" />
  </g>
</svg>

Upvotes: 5

Related Questions