Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 562
Thomas Lancy Avatar asked Jun 19 '15 15:06

Thomas Lancy


2 Answers

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

like image 92
web-tiki Avatar answered Oct 15 '22 08:10

web-tiki


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>
like image 37
Persijn Avatar answered Oct 15 '22 09:10

Persijn