SVG Viewbox - An Interactive Guide
What is Viewbox in SVG?
- The SVG viewBox attribute has 4 values: x, y, width, and height.
- These 4 values define the “window” through which the SVG content is viewed.
- The content inside this area is scaled to fit these values.
Playground
- You can move the red rectangle to see how the right-side SVG changes.
- Only the right-side SVG has the viewbox attribute set.
- The left-side SVG does not have the viewbox attribute. It shows a red rectangle to represent the viewbox that is applied on the right-side graphics.
This operation of moving the rectangle around is Panning. Next we will look at Zooming, but before that, it’s important to note that the viewbox numbers are not in pixels.
A Note on Viewbox Units
The <svg>
element’s width and height can be set in pixels, using CSS. But the four viewbox numbers are not measured in pixels. They are measured in the SVG user space. This is true of all elements inside the SVG. In an svg of size 10 x 10 pixels, you can define this <rect>
.
<rect x1="-1000" y1="-1000" x2="1000" y2="1000"/>
It is perfectly valid. Likewise, you can define any viewbox for this svg. It can even have negative minX and minY values.
How to use viewbox to zoom?
As you zoom in, you can imagine that the viewbox (red rectangle) would grow bigger. As you zoom out, it would grow smaller. Suppose we grow the viewbox by a factor of 1.2. If its current width is w, the new width should be w * 1.2.
We must change the width and the height, without losing the aspect ratio of the image. Also, if the center changes with each zooming action, then it will be very jittery. So the center must not be moved. To achieve this, we will grow the viewbox on the left side by dx, and on the right side by dx. So the new width will be w + 2*dx.
- Now we have two ways of calculating the new width: w * 1.2 and w + 2*dx. These two values must be equal.
- w * 1.2 = w + 2*dx
-
So, dx = w x 0.2 / 2 = w * 0.1
- To make this more general, instead of 1.2, let’s use “scale” to define our scaling factor.
- w * scale = w + 2*dx
- dx = w * (scale - 1) / 2
- Similarly, dy = h * (scale - 1) / 2
Now we are ready to calculate the new viewbox numbers.
- Suppose the current viewbox values are minX, minY, width and height.
- The new values will be minX - dx, minY - dx, width + 2dx, height + 2dy.
- Note that this works for zooming in. For zooming out, you have to use
1 / scale
in the place ofscale
.
Playground
You can see these calculations in the playground below. Click on the buttons to zoom in and out.
preserveAspectRatio
So far, we manually set the height and the width of the viewbox, so that the aspect ratio is unchanged. But what do the browsers do when the viewbox aspect ratio does not match the viewport aspect ratio? Do they squish the svg into the available space?
Here is a viewbox that’s very wide, and a viewport that’s very tall. They do not fit each other. But we can use the preserveAspectRatio
attribute to tell the browser how to draw the SVG.
This attribute has 3 values in it. First let’s look at meetOrSlice
.
- If it is
meet
, which is the default, then the viewbox is made to fit inside the space. - If it is
slice
, then the viewbox is zoomed in to fill the space, and some of it will not be shown since the space will not be sufficient to show it.
The red rectangle represents the viewbox, like before. The blue/purple box represents the part of the image that will be drawn inside the viewport (which is the right-side SVG).
Here, meetOrSlice
has been set to slice
. Go ahead and try out the 3 different values for the x
parameter.
Basically, the small blue box (viewport) is made to fit inside the red box (viewbox), either at the left-most side, or in the middle or in the right-most side.
Next, let’s set the meetOrSlice
to be meet
. Now the blue box (viewport) is made to contain the red box (viewbox), either at the top, middle or bottom. Try setting these 3 values for the y
parameter.
preserveAspectRatio
has one more value: “none”. This tells the browser that it can squish the SVG and draw it to fit the viewport. When preserveAspectRatio
is set to “none”, meetOrSlice
has no meaning and is ignored.