Before we can start doing anything in the world of vector graphics, there are two important concepts to understand. It might seem boring to kick off this course with some dull theory, but if I’d discussed them later, you’d problem run into quite a lot of problems you didn’t know how to fix.
The coordinate system from SVG is not like the one used in mathematics.
In math, when drawing the graph of some function, we’d use the Cartesian coordinate system. This means that the origin (the point
(0,0)) is at the lower left corner, and if we move upwards we get higher y-values, and if we move to the right we get higher x-values.
In SVG, however, and most other computer graphics systems, we use a mirrored version. Our origin is at the top left corner, and if we move downwards we get higher y-values.
Within this coordinate system, we can use regular CSS units to specify the sizes and positions of objects.
Knowing this, we can see that negative values for position, be it the x or y value, are always outside of the picture. The reason it’s done this way, is because web pages (and articles in print) extend downwards. A webpage places its first paragraph at the top, and moves the next one below it, and the next one below that. Using this inverted coordinate system for SVGs, our graphics will be part of the team, and behave like all the other HTML elements.
If we were to use the Cartesian system for SVG graphics, we’d run into all sorts of problems. We’d need to calculate the height every time and offset it by that amount to prevent interfering with the text above, and we’d need to think exactly the other way around when designing graphics for our web page layout. That’s why it’s not done this way.
What to Display?
I just stated that negative values are simply not within the picture frame, but, a vector graphic is infinitely scalable, so where does it end? How does the browser decide where to cut it off, and at what size to display it? Good questions!
By default, SVG strictly uses the axes – which mark the transition between positive and negative numbers – as the left and top borders. For the right and bottom borders, the graphic grows to whatever size is necessary to display everything. For example, if the only thing inside your SVG is a circle at position
(5px,5px) with radius
5px, then your graphic will have width and height
5+5 = 10px. Because SVG cuts off the graphic that precisely, it’s default behaviour is to scale to the full width and height of its container parent.
But, there will be times when you want full control over the width and height of the graphic, and what area to display. For this, we use something called a viewport and viewbox, respectively.
The viewport means the exact size of the SVG graphic itself. With the
attributes we can set the size of the SVG element exactly. This doesn’t scale the graphic to fit these dimensions, but it sets the element’s dimensions within the webpage to this size, and displays only those objects that fall within this area. You can look at it as being the port through which you look into the SVG graphic’s world.
If you do want the graphic to scale to fit with a fixed width and height, you can just use the CSS
height properties on the element.
<svg width="8"> <circle cx="10" cy="10" r="10"/> </svg>
If you don’t specify units for these width/height values, it defaults to pixels.
The determine what area we want to display, without saying anything about the element’s dimensions, use the
viewbox attribute. You need to specify a rectangle, which it uses to crop the graphic. Everything outside of the rectangle is discarded, and scaling the image (perhaps with CSS) simply means that everything inside the viewbox rectangle is scaled by that amount. You can look at it as putting a box underneath a specific part of the graphic, pushing everything above it in the box, and then forgetting the rest and only focussing on that box.
The syntax is:
viewbox=”origin-x origin-y width height”
Note that, using a negative origin, we can bring back negative values!
<!-- Notice how we're able to fill the whole SVG element with the circle, even though it's placed at a coordinate far away from the origin, (30,30) --> <svg viewbox="20 20 20 20"> <circle cx="30" cy="30" r="10"/> </svg>