Say you already know the basic idea of Scalable Vector Graphics, it is kind of like a scene graph for 2D vector drawn shapes. You get the core concept because you have worked with similar concepts before. You don’t want to plow through a long tutorial spoon feeding you what vector graphics is, shapes, fills etc. Instead what you want to know is the non-obvious stuff and how it works.
- How do you group shapes?
- How are they reused?
- How exactly does the SVG coordinate system work?
- How should I structure my SVG graphics?
Then this the the article for you. I will assume you can lookup SVG details in various SVG references and tutorials elsewhere.
Grouping and reusing with
g tag is used to group a bunch of SVG shapes and handle them as one group which can be moved, scaled and styled as one unit. Just like you can give a HTML element an
id you can give a group an
id which can be referenced in CSS or in the SVG markup itself. If you are familiar with regular HTML and CSS, then
g serves much the same purpose as
div elements in regular HTML.
If you want to reuse a group of elements you can reuse them using the
<use x="100" y="100" xlink:href="#bird" />
<use x="100" y="100" xlink:href="path/to/animals.svg#bird" />
Above are two examples gotten from Sara Soueidan excellent blog on SVG. Which explains SVG in far more detail than me. This is the short version for lazy people.
Anyway you can see in example that we specify position of the shape as well as specify the group
id of the composite shape we want to display. The group was given as
<g id="bird"> and we refer to it by writing
xlink:href="#bird". If this definition was in another file, we would write
Something potentially confusing is when to use
symbol. If you don't want your group to display when you define it, you stuff it inside a
defs tag. It makes sure it will only show due to use of
Another important reason is:
Use coordinates are relative to position of group, unless group was placed in a defs tag. In the latter case, coordinates are relative to the users coordinate system.
symbol in contrast is an entire replacement for
symbol is a group which does not get displayed until it is used with
use. So why use
symbol instead of groups inside
defs? They sound like the same thing. The difference is in how their coordinate system is handled.
To grasp that we need to get into how the SVG coordinate system works.
In any graphics system whether 3D or 2D we have some scene or canvas where we define our objects, where they are located, how large they are etc.
But what the user sees depends on what part of this scene we let the user see. In 3D graphics this is often abstracted as a camera object. You position the camera in your scene, using scene coordinates and tell it what direction it is looking. What the user end up seeing is what is captured on the camera film. We call this the viewport.
How big something looks in the viewport depends on how close you put the camera to the objects in the scene.
With 2D graphics it is a bit simpler. You can imagine an infinite canvas, on top of this there is an infinitely large sheet of paper which somebody has cut a square hole in. This hole is your viewport.
<svg width="600" height="300" style="outline: 5px solid #630">
<rect width="200" height="100" fill="#f00" />
The code above creates a viewport which is 600 points wide and 300 points tall. You can think of this as a 600 by 300 large opening in the the sheet of paper, letting you look at the canvas below where there is a 200 by 100 large red rectangle.
This example is from Steven Bradley’s blog on SVG coordinate system.
There are several coordinate systems you need to keep track of which will easily confuse you when thinking about this.
svg width="500" height="100" says your canvas is 500 by 100 units large. However your web browser may only show an area which is 250 by 50 units large so you only see 1/4th of your viewport at any given time. You need to scroll around to see the whole thing.
To add to complexity the viewport is also a window into a scene of which you will not see everything. The size of the viewport says how much you see of the viewport at any given time in your browser.
However how much of the scene your viewport sees is determine by the size of the
viewBox. Think of the
viewBox as describing where you cut an opening into the canvas from the sheet of paper covering it.
viewBox="0 0 550 150 means start cutting in the upper left corner of the sheet (0, 0) and cut out a rectangle which is 550 by 150 units large. The size is given in canvas coordinates.
Look at the example below:
<svg width="500" height="100" viewBox="0 0 550 150" >
<circle r="25" cx="25" cy="25" fill="#f00" />
<rect x="500" y="100" width="50" height="50" fill="#393" />
You will see both the circle and the rectangle, because you have specified a
viewBox or a cutout of the canvas which is large enough to hold both.
The size of the canvas being just 500 by 100 is irrelevant. This is just how the coordinates of this cutout will be labeled in the viewport.
How altering the size of the viewport and viewBox alters what you see
Let us say we have a red circle in our canvas taking up 60x60 points. Next to it is a green square taking up 60x60 points.
Then if we specify the
viewbox as 60x60 it will only show the circle. If we offset the
viewBox like this:
viewBox="60 0 60 60
Then we will only see the green square. However if we make the
viewBox larger we can show both:
viewBox="0 0 120 60
What this tells us is that as you make the
viewBox larger you will see more of the elements on the canvas but those elements will also become smaller. Thus a smaller
viewBox makes objects larger. A larger
viewBox makes objects smaller but you see more.
The SVG canvas works in similar fashion but result will be opposite. Objects will look bigger as you make the canvas larger. Let us explain the logic of this.
If the browser window is 120x120 points, then an SVG canvas of size 60x60 will take up 1/4th of the visible window. If you increase the canvas to 120x120, then it will cover the whole visible area. Hence everything will look bigger. Keep in mind, that at this point, what objects you actually see is entirely decided by the
viewBox which defined that size of the area in the canvas (scene) you want to look at.
Now if I resized my browser window to be just 60x120 points, now I can only see the green circle, because the canvas is larger than the viewport. I can however scroll sideways to see the green rectangle instead.
We would have gotten the exact same effect if we had not resized the browser window but instead increased the canvas size to 240x120 points.
viewBoxgives smaller objects but you see more of the canvas.
- Larger SVG canvas give larger objects and you see less in your browser window.