Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to scale this SVG?

Tags:

html

css

scale

svg

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.

like image 415
connexo Avatar asked Dec 08 '25 08:12

connexo


2 Answers

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>
like image 147
Danny '365CSI' Engelman Avatar answered Dec 10 '25 00:12

Danny '365CSI' Engelman


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>
like image 34
Paulie_D Avatar answered Dec 09 '25 23:12

Paulie_D