skip to Main Content

I have e.g. this SVG:

<svg><rect width="6" height="14" x="1" y="4" fill="currentColor"><animate id="svgSpinnersBarsFade0" fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsFade1.end-0.25s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4"><animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.15s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3"><animate id="svgSpinnersBarsFade1" fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.3s" dur="0.75s" values="1;.2"></animate></rect></svg>

How can I scale it? I have tried using width and height attributes on the <svg>, tried setting font-size in hopes of it reacting to that, tried setting a viewbox (which I still don’t get how it works). I’ve also tried putting it in a container element and style it via width: 100%; height: 100%;. None of these attempts had any effect whatsoever.

Example:

svg { width: 100%; height: 100% }
<div style="width: 64px; height: 64px; background-color: #f8f8f8;">
  <svg height="64" width="64" viewBox="0 0 64 64" style="font-size: 64px;"><rect width="6" height="14" x="1" y="4" fill="currentColor"><animate id="svgSpinnersBarsFade0" fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsFade1.end-0.25s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4"><animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.15s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3"><animate id="svgSpinnersBarsFade1" fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.3s" dur="0.75s" values="1;.2"></animate></rect></svg>
</div>

I’d love someone to not only provide a solution, but also explain the basics behind this, and why none of my approaches is valid.

2

Answers


  1. Just remove the width/height etc. from the SVG and it will scale to the bounding container depending on the viewbox.

    The viewbox defines the canvas dimensions for placement of the elements within. It has no relevance to the actual size of the SVG in the HTML.

    The viewBox attribute defines the position and dimension, in user space, of an SVG viewport.

    When an SVG contains a viewBox attribute (often in combination with a preserveAspectRatio attribute), a transform stretches or resizes the SVG viewport to fit a particular container element.

    However, setting a width/height in the SVG will set the size until removed or overridden.

    div {
      width: 200px;
      height: 200px;
    }
    <div>
      <svg viewBox="0 0 64 64"><rect width="6" height="14" x="1" y="4" fill="currentColor"><animate id="svgSpinnersBarsFade0" fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsFade1.end-0.25s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4"><animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.15s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3"><animate id="svgSpinnersBarsFade1" fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.3s" dur="0.75s" values="1;.2"></animate></rect></svg>
    </div>

    In your specific SVG, you aren’t actually using the whole canvas as the objects you place on it are essentially only using the top left corner. If you change the viewbox so they fill the SVG it looks quite different.

    div {
      width: 100px;
    }
    
    svg {
      border: 1px solid red;
    }
    <div>
      <svg viewBox="0 0 64 64"><rect width="6" height="14" x="1" y="4" fill="currentColor"><animate id="svgSpinnersBarsFade0" fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsFade1.end-0.25s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4"><animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.15s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3"><animate id="svgSpinnersBarsFade1" fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.3s" dur="0.75s" values="1;.2"></animate></rect></svg>
    </div>
    
    <div>
      <svg viewBox="0 0 24 24"><rect width="6" height="14" x="1" y="4" fill="currentColor"><animate id="svgSpinnersBarsFade0" fill="freeze" attributeName="opacity" begin="0;svgSpinnersBarsFade1.end-0.25s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="9" y="4" fill="currentColor" opacity=".4"><animate fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.15s" dur="0.75s" values="1;.2"></animate></rect><rect width="6" height="14" x="17" y="4" fill="currentColor" opacity=".3"><animate id="svgSpinnersBarsFade1" fill="freeze" attributeName="opacity" begin="svgSpinnersBarsFade0.begin+0.3s" dur="0.75s" values="1;.2"></animate></rect></svg>
    </div>
    Login or Signup to reply.
  2. FYI, the "default" viewBox is viewBox="0 0 300 150"

    without a viewBox, the SVG gets a 300 x 150 pixel size in the HTML document

    with a viewBox the SVG sizes to its container

    For sanity, always use a viewBox

    Libraries that set width and heigth attributes on a SVG should be burnt,
    its like using !important in CSS (IMHO)

    <svg style="background:pink">
      <circle r="75" cx="50%" cy="50%" fill="peru"/>
    </svg>
    
    <svg viewBox="0 0 300 150" style="background:pink;width:300;height:150">
      <circle r="75" cx="50%" cy="50%" fill="silver"/>
    </svg>
    
    <svg viewBox="0 0 300 150" style="background:pink">
      <circle r="75" cx="50%" cy="50%" fill="gold"/>
    </svg>

    Those id values in your SVG animation will get you in trouble when more SVGs use the same id

    And since I know you love Web Components as much as I do;
    this one makes it easier to play with values

    Note the viewBox y value. the viewBox "shifts" upward so the rect does NOT need an y=2 value since the default is y=0

    customElements.define("svg-bars", class extends HTMLElement{
      connectedCallback() {
        this.style.display = "inline-block";
        this.style.verticalAlign = "top";
        let fill = this.getAttribute("fill") || "currentColor";
        this.innerHTML = `<svg viewBox="0 -2 12 12" style="background:pink">` +
        [2,5,8].map((x,i)=>`<rect width=2 height=8 x=${x} fill=${fill}>`+
          `<animate repeatCount=indefinite attributeName=opacity begin=${i*.15} dur=.75s values=1;.;1 />`+
          `</rect>`).join("") +
        `</svg>`
      }
    })
    <svg-bars></svg-bars>
    <svg-bars fill=red></svg-bars>
     
    <style>
      svg-bars { width:150px } 
    </style>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search