Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Responsive SVG viewBox

Tags:

html

css

svg

I made a "hamburger button" in SVG, as seen below.

body {
  margin: 0;
  text-align: center;
}

svg#ham-btn {
  margin: 2rem;
  border: 1px solid black;
  fill: #383838;
}
<svg id="ham-btn" width="107.5px" height="80px" viewBox="0 0 80 80" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
  <style>
    #ham-btn {
      cursor: pointer;
    }
    #ham-btn:hover #r1 {
      outline: 1px solid transparent;
      transition: transform 0.2s;
      transform-origin: 50% 50%;
      transform: rotate(37deg) translate(0%, 28.75%) scaleX(1.1);
    }
    #ham-btn:hover #r2 {
      transition: transform 0.2s;
      transform: translate(120%, 0);
    }
    #ham-btn:hover #r3 {
      outline: 1px solid transparent;
      transition: transform 0.2s;
      transform-origin: 50% 50%;
      transform: rotate(-37deg) translate(0%, -28.75%) scaleX(1.1);
    }
    
  </style>
  <rect id="r3" x="0" y="71.25%" width="100%" height="15%" rx="5%" />
  <rect id="r2" x="0" y="42.5%" width="100%" height="15%" rx="5%"/>
  <rect id="r1" x="0" y="13.75%" width="100%" height="15%" rx="5%" />
</svg>

Question

Right now, if I want to make the button smaller, I have to manually make the dimensions of the viewport and viewBox smaller by the same amount of px.

Is there any way to make that more responsive? For instance, by making viewBox be a percentage of the viewport?

According to the spec, it seems viewBox has to be a <number>, and thus cannot be a percentage.

Any thoughts?

Thank you.


Note 1

I have not added any accessibility or other features to the button. This question is about its responsiveness.


Note 2

I know I can make the SVG viewport a percentage of its container / the browser viewport.

That does not solve my issue unfortunately, as to make this button work my viewBox-to-viewport ratio must stay fixed (otherwise the button looses its shape).

Thus, I wanted to make the viewBox be a percentage of the viewport.

In case it is of interest, my solution takes advantage of the following:

  • viewBox is wider than viewport, but has the same height
  • Thus, preserveAspectRatio is used to horizontally center the rects
  • rect dimensions are in percentage of viewBox

The outline is to fix a Firefox issue with jagged lines after transform.


Edit:

In case helpful to future visitors, the final button, including full accessibility, can be found here: https://codepen.io/magnusriga/pen/KrrJKa

like image 742
Magnus Avatar asked Sep 07 '25 11:09

Magnus


1 Answers

Add width & height properties to your svg css. With width set and height auto.

body {
  margin: 0;
  text-align: center;
}

svg#ham-btn {
  margin: 2rem;
  border: 1px solid black;
  fill: #383838;
  /* percentage of viewport - height will autocalculate */
  width: 7vw;
  height: auto;
}
<svg id="ham-btn" width="107.5px" height="80px" viewBox="0 0 80 80" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
  <style>
    #ham-btn {
      cursor: pointer;
    }
    #ham-btn:hover #r1 {
      transition: transform 0.2s;
      transform-origin: 50% 50%;
      transform: rotate(37deg) translate(0%, 28.75%) scaleX(1.1);
    }
    #ham-btn:hover #r2 {
      transition: x 0.2s;
      x: 120%;
    }
    #ham-btn:hover #r3 {
      transition: transform 0.2s;
      transform-origin: 50% 50%;
      transform: rotate(-37deg) translate(0%, -28.75%) scaleX(1.1);
    }
    
  </style>
  <rect id="r3" x="0" y="71.25%" width="100%" height="15%" rx="5%" />
  <rect id="r2" x="0" y="42.5%" width="100%" height="15%" rx="5%"/>
  <rect id="r1" x="0" y="13.75%" width="100%" height="15%" rx="5%" />
</svg>
like image 86
Ludovit Mydla Avatar answered Sep 09 '25 08:09

Ludovit Mydla