Change Svg Viewbox Size with CSS

Change SVG viewBox size from CSS without javascript

I can see two approaches to solve this. The first one is to have no viewBox attribute at all.

<svg>
<text x="0" y="65">test</text>
</svg>

svg {
width: calc(var(--letter-count) * 40px);
height: 80px;
}

This comes at the price of the SVG no longer being responsive.

The second solution looks a bit hacky, but works:

<svg viewBox="0 0 45 80" preserveAspectRatio="xMinYMid meet">
<text x="0" y="65">test</text>
</svg>

svg {
overflow: visible;
width: calc(var(--letter-width) * var(--letter-count));;
height: 100%;
}

The preserveAspectRatio value takes care for the text to start always at the left side. You would need to set width to a value that leaves enough space to the right for the text to run into. If the SVG is scaled, your CSS would have to adapt the --letter-width variable accordingly.

Is it possible to change svg viewBox value using CSS?

You can only change presentation attributes through CSS. viewBox is not one of these.

What you can do however is to use <symbol> elements to define "views" over the scene.

Indeed, <symbol> does have a viewBox attribute, so you can use this element to point to the whole scene, and then use one <use> element per such "view" and control via CSS when this <use> is displayed:

svg {
border: 1px solid;
border-color: yellow;
}
@media (max-width:500px) {
svg { border-color: green; }
#small-use { display: block; }
#big-use { display: none; }
}
@media (min-width:501px) {
#small-use { display: none; }
#big-use { display: block; }
}
<svg>
<!-- we wrap the whole scene in one symbol -->
<symbol id="scene">
<rect fill="blue" x="0" y="0" width="500" height="500"/>
<rect fill="red" x="0" y="0" width="50" height="50" />
</symbol>

<!-- following symbols will define our "views" -->
<symbol id="small-view" viewBox="0 0 60 60">
<use href="#scene"/>
</symbol>
<symbol id="big-view" viewBox="0 0 500 500">
<use href="#scene"/>
</symbol>

<!-- append all the views, CSS will determine which to display -->
<use href="#small-view" id="small-use"/>
<use href="#big-view" id="big-use"/>
</svg>
<p>Change the window's size to trigger the "change of viewBox"</p>

SVG viewBox=0 0 100 100 wont scale my path to 100%?

The viewBox is like a canvas size. So drawings outside of this view box will be clipped. Like css overflow: hidden. And your drawing has a size of width 123px and height 170px. So you have to change the view box to this value. Check our some docs.

If you want to keep the viewbox of 100 x 100 px, you need to change your drawing element size (path).

The view box has nothing to do with the scale. It's just the canvas size. A rect clip with width, height and offset (x y w h) for the SVG elements inside. And the SVG tag's width and height attributes are for scale the rendered image.

<div className="svgPathContainer">
<svg width="100%" height="100%" viewbox="0 0 123 170" preserveAspectRatio="none">
<path d="M82 88L0 0H123V170H0L82 88Z" fill="#F9B300" />
</svg>
</div>

Resize SVG by changes in path

No you can't. You'd have to change the SVG path to fit the box, but you can't "resize" per-se.

I manually resized your path to fit the box.

<path fill="#3E3E3E" d="M1.2 3.3H4a1 1 0 1 1 0 1.8H.6a1 1 0 0 1-.9-.9V0a1 1 0 0 1 1.9 0v1.4A11 11 0 0 1 20 8.6c0 .5-.4.9-1 .9a1 1 0 0 1-.9-1A9.2 9.2 0 0 0 12.3 1a9.2 9.2 0 0 0-10 2.3ZM17.4 16.1A11 11 0 0 1-1 8.9c0-.5.4-.9 1-.9.4 0 .8.4.9 1a9.2 9.2 0 0 0 5.8 7.5 9.2 9.2 0 0 0 10-2.3h-2.6a1 1 0 1 1 0-1.8h4.3a1 1 0 0 1 .9.9v4.2a1 1 0 0 1-1.9 0v-1.4Z"></path>

How I did it:

I used svgomg with precision: 1, to simplify the path to a point where it was small enough for me to actually manually edit.

Then I split it into two separate paths (top and bottom arrows) (using
the Z as the path separator), wrapped them in <g transform="translate(x, y)"></g> until it looked right, copied the
remainder back into svgomg where it is smart enough to convert the
transforms into a single path.

Scaling an SVG within an HTML viewbox

How the viewBox works

It is actually very simple.

In order for the browser to scale your SVG content, to fit the width and height you specify, it needs to know how big that content is.

The way you tell it how big that content is, is via the viewBox attribute. The values in a viewBox are:

<minimum X> <minimum Y> <width> <height>

So say your content was a square from (10,20) to (80,80). A viewBox definition that exactly fitted that square would be:

viewBox="10 20 70 60"

This is saying that the top left of your content is at 10,20, the width is 70, and the height is 60.

Here's a diagram to show what I mean.

<svg width="300" height="300">  <g transform="translate(50 50) scale(2)">     >!-- axes -->     <line x1="0.25" y1="-100" y1="0.25" y2="300" stroke="grey" stroke-width="0.5"/>     <line x1="-100" y1="0.25" x2="300" y2="0.25" stroke="grey" stroke-width="0.5"/>
<!-- bounds --> <line x1="10.25" y1="-100" x2="10.25" y2="300" stroke="grey" stroke-width="0.5" stroke-dasharray="3 3"/> <line x1="-100" y1="20.25" x2="300" y2="20.25" stroke="grey" stroke-width="0.5" stroke-dasharray="3 3"/> <line x1="80.25" y1="-100" x2="80.25" y2="300" stroke="grey" stroke-width="0.5" stroke-dasharray="3 3"/> <line x1="-100" y1="80.25" x2="300" y2="80.25" stroke="grey" stroke-width="0.5" stroke-dasharray="3 3"/>
<!-- rectangle --> <rect x="10" y="20" width="70" height="60" fill="rebeccapurple"/> <!-- labels --> <g fill="grey" font-size="6px" font-family="sans-serif"> <text x="-2" y="-2" text-anchor="end">0,0</text> <text x="12" y="-2">10</text> <text x="82" y="-2">80</text> <text x="-2" y="27" text-anchor="end">20</text> <text x="-2" y="87" text-anchor="end">80</text> <text x="45" y="87" text-anchor="middle">width = 70</text> <text x="82" y="50">height = 60</text> </g> </g></svg>

How can I make an svg scale with its parent container?

To specify the coordinates within the SVG image independently of the scaled size of the image, use the viewBox attribute on the SVG element to define what the bounding box of the image is in the coordinate system of the image, and use the width and height attributes to define what the width or height are with respect to the containing page.

For instance, if you have the following:

<svg>
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>

It will render as a 10px by 20px triangle:

10x20 triangle

Now, if you set only the width and height, that will change the size of the SVG element, but not scale the triangle:

<svg width=100 height=50>
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>

10x20 triangle

If you set the view box, that causes it to transform the image such that the given box (in the coordinate system of the image) is scaled up to fit within the given width and height (in the coordinate system of the page). For instance, to scale up the triangle to be 100px by 50px:

<svg width=100 height=50 viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>

100x50 triangle

If you want to scale it up to the width of the HTML viewport:

<svg width="100%" viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>

300x150 triangle

Note that by default, the aspect ratio is preserved. So if you specify that the element should have a width of 100%, but a height of 50px, it will actually only scale up to the height of 50px (unless you have a very narrow window):

<svg width="100%" height="50px" viewBox="0 0 20 10">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>

100x50 triangle

If you actually want it to stretch horizontally, disable aspect ratio preservation with preserveAspectRatio=none:

<svg width="100%" height="50px" viewBox="0 0 20 10" preserveAspectRatio="none">
<polygon fill=red stroke-width=0
points="0,10 20,10 10,0" />
</svg>

300x50 triangle

(note that while in my examples I use syntax that works for HTML embedding, to include the examples as an image in StackOverflow I am instead embedding within another SVG, so I need to use valid XML syntax)

SVG height not behaving as expected

First of all you can use the attribute preserveAspectRatio="none" on <svg>. This will stretch the SVG if you specify a height and a width.
Second you path was placed around 200 down the y axis. So, when it stretched, the transparent area above the path would also take up more space. I moved the path so that it almost hits y=0 on the top. Now the path only takes up 113 in the height and when stretched it will fill up the entire box.

I used SvgPathEditor to edit the path.

.wrap {
height: 300px;
width: 300px;
background: #eee;
}

svg, img {
height: 100%;
width: 100%;
}
Just the SVG file

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 113">
<path fill="#0369a1" fill-opacity="1" d="M 0 17 L 80 33 C 160 49 320 81 480 70.3 C 640 60 800 6 960 1 C 1120 -4 1280 38 1360 59.7 L 1440 81 L 1440 113 L 1360 113 C 1280 113 1120 113 960 113 C 800 113 640 113 480 113 C 320 113 160 113 80 113 L 0 113 Z"></path>
</svg>

SVG in a box - Does not work

<div class="wrap">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 113" preserveAspectRatio="none">
<path fill="#0369a1" fill-opacity="1" d="M 0 17 L 80 33 C 160 49 320 81 480 70.3 C 640 60 800 6 960 1 C 1120 -4 1280 38 1360 59.7 L 1440 81 L 1440 113 L 1360 113 C 1280 113 1120 113 960 113 C 800 113 640 113 480 113 C 320 113 160 113 80 113 L 0 113 Z"></path>
</svg>
</div>

JPG in a box - Do work

<div class="wrap">
<img src="https://placekitten.com/96/139">
</div>


Related Topics



Leave a reply



Submit