In this article I’ll try and explain the viewBox
attribute for SVGs as they’re an important thing when it comes to making SVGs responsive. Unfortunately, the viewBox is not super intuitive if you’re not too familiar with SVG, but it can be very handy once you’ve got the hang of it.
And because there are so many ways an SVG can be included on a web page, in this article I’ll only be talking about inline SVG. Just to be clear, this is the thing we’re talking about here.
But before jumping into the tricky bits, let’s first have a quick look at how sizes and coordinates work in SVG.
SVG’s coordinate system
In traditional math, when looking at a coordinate system, we’re taught that the x-axis is horizontal and increases going from left to right and that the y-axis is vertical and increases upwards. Like so:
However, in SVGs (and many other computer graphics software), the y-axis is inverted meaning the top left corner has the coordinates [0,0]
.
It’s also important to note that SVGs operate in pixel values. That doesn’t necessarily mean that everything is rendered on the screen according to those values, but we’ll get into that later on. Unless viewBox
has been defined, just think of the value 10
inside an SVG means “10 pixels”.
Imagine that we have an SVG with width of 200 pixels and height of 200 pixels.
And in that SVG we’d want to draw a 100×100 pixel square.
We’ll give it a border-radius rx
of 30 pixels so that it’ll be easier to notice when it’s scaled.
Remember, unless we specify x
and y
values for the the <rect>
element, it’ll start drawing from its top left corner at [0,0].
Resizing the SVG
The fact that values in SVG represents pixels may sometimes feel frustrating, especially when we’d want to scale a graphics either because it’s too small or too big for the screen it’s viewed on.
Trying to simply increase or decrease the width
attribute on the SVG won’t do the job, unfortunately:
Changing the width using CSS like other graphics like <img>
s won’t work either. The result is similar to when we changed the width
attribute: the SVG changes width, but the graphics inside of it remains the same size.
Applying viewBox
The viewBox
attribute lives on the <svg>
element and tells the browser which part of the canvas should be rendered into view. This is the part where numeral values stop representing actual pixels on the screen. It’s still important to think of them as pixel values though, as we’ll see in a bit.
Let’s apply a simple viewBox that matches the size our SVG:
In the viewBox syntax viewBox="<num> <num> <num> <num>"
the first pair of numbers are the x and y coordinates for its top left corner, and the last pair are the width and height values for the viewBox.
In this simple example, the viewBox is exactly the same as the SVG size, so nothing really changes.
A good way to think of the viewBox is that it’s a telescope which we can use to view the parts of the world (SVG) in greater detail. We can pan around (up, down, right, left) and zoom in or out to get the exact view of the graphics.
Let’s start by changing some of the parameters of the viewBox:
The browser will only render what’s inside the viewBox:
It’s important to remember that everything inside the SVG still respects the width
and height
values of the SVG.
Nothing prevents us from setting the viewBox to a negative value, and sometimes that’s actually a very useful trick. Let’s set the viewBox to start at [-10,-10]
and make it 120 pixels wide and tall.
So this viewBox …
… renders this view:
Scaling SVGs with CSS
The thing is that the SVG above is still rendered at the size defined in its width
attribute at 200 pixels. Sometimes we’d want the SVG to be at a certain size smaller than what is defined in its “pixel” values, for instance with icons.
In order to set the size if which it’s rendered, we can simply change the width
and height
attributes directly on the SVG, but leaving the viewBox intact:
Other times we need to fill the available space, let’s say for an illustration, diagram or chart. Luckily, there’s a way we can use CSS to do this. So in our CSS we can do something like:
and then remove the width
attribute from the SVG element all together:
Now the SVG takes up all the available width of its container. I’ve added a grey border around the SVG element here so it’s easier to see where it is.
What we really want is not just to extend the width of it, but to increase the height as well keeping the original aspect ratio. We need to get rid of the height
attribute as well. But instead of calculating what the height should be at every breakpoint we’d want the height to be dynamic.
In order to achieve this we just remove the height
attribute as well.
Yay!
Next up
I’m planning on doing a series on responsive data visualisations, please stay tuned for more SVG fun.