Topic 1.1
The SVG Coordinate System
In one line
SVG places every shape with numbers measured from the top-left corner: x grows to the right and y grows downwards. Anything outside the SVG's width and height is clipped, silently, and an SVG with no size is 300 by 150.
Think of it like this
A page in a notebook. You start writing at the top-left corner. To write a second line you go down, not up, and to write further along a line you go to the right. SVG measures every position the same way: how far across from the left edge, and how far down from the top edge.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- SVG
- Scalable Vector Graphics: a drawing made of shapes described by numbers, written as tags in the page, so it stays sharp at any size.
- coordinate
- A number that says where something is. A point needs two: x (across) and y (down).
- origin
- The point (0, 0): the top-left corner of the SVG.
- user unit
- The unit of the numbers inside an SVG. Without a viewBox it equals one CSS pixel.
- clipped
- Cut off at the edge of the drawing area. The part outside is not drawn.
- bounding box
- The smallest rectangle that contains a shape. The browser reports it with
getBBox(). - attribute
- A setting written inside a tag, like
width="300"in<svg width="300">. - DOM
- The page's tree of elements that the browser keeps in memory. Every SVG shape is one node in it, which is why you can find, measure and change it with JavaScript.
Step by step
01Draw a grid so you can see the numbers
The first example draws grey lines every 50 units, labelled with their number, in an SVG that is exactly 300 by 150. Then it adds five shapes at chosen positions. Look at where each one lands against the grid.
The teal box starts at (50, 25), so its top-left corner is 50 across and 25 down. It is 100 wide and 50 tall, so it ends at x = 150 and y = 75.
<rect x="50" y="25" width="100" height="50"></rect>02Put shapes on and over the edge
The orange circle is centred at (0, 0) with radius 30: only the quarter inside the SVG shows. The green circle is centred at x = −10, so only its right part shows. The dark circle is centred at x = 330, which is past the right edge (300) by more than its radius, so nothing of it shows.
The Console lists each shape's bounding box and whether it is fully inside, partly cut off, or not drawn. The shapes that are not fully inside are all still there in the DOM. Nothing printed an error.
03Measure the size of an SVG in nine situations
The second example creates SVGs with different width and height attributes and reads the size the browser really gave each one. No size at all gives 300 by 150. A width alone keeps the default height of 150. A height alone keeps the default width of 300.
Units work: 2in is 192 pixels because CSS defines 96 pixels per inch, and 10mm is about 37.8 pixels. A CSS width: 250px on the element beats width="200". A width of 0 is legal and makes the drawing invisible, again without an error.
04Remember which way y goes
Whenever a chart looks upside down, the cause is almost always y. Charts compute y = baseline − height, as the Phase 0 build did with y = 180 − height: height 160 gives y = 20 (high), height 40 gives y = 140 (low).
Try it yourself
- 1
Move the orange circle into view
In the first example, change
cornertocx: 30, cy: 30. The whole circle is now inside, and the Console saysfully insidefor it. The shape did not change, only its centre: the number decides where it sits. - 2
Make the SVG bigger instead
In the first example's HTML, change
width="300"towidth="400". The dark circle at x = 330 now shows. The grid does not grow, because its loops still stop at 300, so grid lines cover only the left three quarters. The Console still saysoff: ... -> not drawnbecause the script's test hard-codes 300. Change300to400in theright <= 300andb.x < 300tests and the line becomesoff: x 305 to 355, y 50 to 100 -> fully inside. - 3
Give the second example a CSS size
In the second example, add
style="height: 200px"to theheight onlySVG. The line becomes300.00 x 200.00: the CSS height beatsheight="80", and the width is still the default 300.
Code & diagrams
Nothing here prints an error: a shape outside the drawing area is clipped quietly, which is why a missing shape is hard to find.
Preview
Console
Nothing logged yet.Expected console output
box: x 50 to 150, y 25 to 75 -> fully inside
corner: x -30 to 30, y -30 to 30 -> partly cut off
left: x -35 to 15, y 85 to 135 -> partly cut off
off: x 305 to 355, y 50 to 100 -> not drawn
dot: x 235 to 265, y 95 to 125 -> fully inside
Shapes in the DOM: 5The first line is the default every SVG falls back to. The orange squares show the shape at (0, 0) in each drawing area.
Preview
Console
Nothing logged yet.Expected console output
no size at all : 300.00 x 150.00
width only : 200.00 x 150.00
height only : 300.00 x 80.00
width and height : 200.00 x 80.00
decimals : 120.50 x 60.25
2in by 1in : 192.00 x 96.00
10mm by 10mm : 37.78 x 37.78
CSS beats the attribute: 250.00 x 80.00
width 0 (invisible): 0.00 x 80.00Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Forget the size entirely
In the first example's HTML, delete width="300" height="150" from the <svg> tag.
Break #2
Swap up and down
In the first example, change the yellow dot to cy: 40 and, in your head, treat it as "40 up from the bottom".
Myth vs fact
Myth
SVG coordinates work like school maths graphs, with y going up.
Fact
In SVG, y grows downwards from the top-left corner, like text on a page. That is why chart code subtracts from a baseline.
Myth
A shape outside the SVG causes an error.
Fact
It is clipped silently. The first example shows three shapes cut or hidden, and the Console is quiet. When a shape is missing, check its position against the SVG's size first.
Myth
The numbers in an SVG are pixels.
Fact
They are user units. They equal pixels only while the SVG has no viewBox. With a viewBox, one unit can be any size on screen (Topic 1.4).
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The outer
<svg>clips because the browser's default stylesheet setsoverflow: hiddenon anysvgthat is not the root of the document. Setoverflow: visiblein CSS and the shapes outside the box are drawn. Chart authors use this on purpose for axis labels that stick out past the plot area. - ▸
getBBox()returns the shape's box in its own user units and ignores clipping.getBoundingClientRect()returns the box in screen pixels after transforms and scaling. Mixing them up is a common source of off-by-a-few-pixels bugs in tooltips (Phase 8). - ▸
The default size of 300 by 150 is the same rule the browser uses for any replaced element without an intrinsic size, such as an
<iframe>or<canvas>without attributes. A canvas, too, is 300 by 150 until you set itswidthandheight(Topic 0.5). - ▸
An SVG with
width="0"orheight="0"is not rendered at all. A chart whose container has not been laid out yet (a hidden tab,display: none) can measure 0 and silently draw nothing. Phase 10 handles measuring a container.
Remember this
- 1
The problem this solves: to draw a shape you must say where it goes. SVG gives you a number grid to say it with. If you misjudge the grid (up and down swapped, or the SVG smaller than you thought), shapes land in the wrong place or vanish, and the browser prints no error.
- 2
The origin is the top-left corner. The point (0, 0) is the top-left of the SVG. A position is written as a pair
(x, y).xis the distance to the right, andyis the distance down. This is the opposite of the graphs you drew at school, where y grows upwards. Every chart you draw has to turn that around: a bigger value gets a smaller y. Topic 3.2 builds that flip by hand, and D3 does it for you from Phase 6. - 3
User units. The numbers inside an SVG are user units. They carry no unit name (no
px, nocm). By default one user unit is one CSS pixel, sox="50"is 50 pixels from the left. Topic 1.4 shows howviewBoxchanges that rule, so the drawing's numbers and the screen's pixels no longer match one to one. - 4
The size of the SVG. The
widthandheightattributes on the<svg>tag say how big the drawing area is. Without them the browser uses 300 by 150, which is why a first drawing often looks cut off. You can use units there (2in,10mm), and a CSSwidthorheighton the same element overrides the attribute. The first example below measures all of this. - 5
Outside the SVG, shapes are clipped, with no warning. A shape beyond the edges is not drawn, or drawn only in part. It still exists: you can find it in the DOM, and its bounding box still reports the full size. A circle centred at (0, 0) shows as a quarter circle. A circle centred at x = 330 in a 300-wide SVG is not shown at all.
- 6
Negative and decimal coordinates are legal. A shape at x = −10 starts left of the edge and shows only its right part. Decimals such as
59.25are common, because scales compute them. Two or three decimal places are plenty for a screen. A bad value (the textNaN, from a failed calculation) is the real danger: the browser prints an error, and Topic 1.2 shows the exact words.
Explain it without notes
Where is the point (0, 0), and which way do x and y grow?
What size is an SVG with no width and height, and what happens to a shape outside that area?
Why does a chart that maps bigger values to bigger y look upside down?
What is a user unit, and when does it equal a pixel?
Practice
A rectangle should sit in the top-right corner of a 300 by 150 SVG, 60 wide and 30 tall, touching both edges. What are its x and y? Write the tag.
A circle of radius 20 is centred at (300, 75) in a 300 by 150 SVG. How much of it shows? What would you change to show all of it, without moving the circle?
Trade-offs
- ↔
Relying on the default 300 by 150 saves typing but hides the size from the next reader. Writing the size down costs a few characters and makes clipped shapes easy to reason about.
Done when you can
I can say where (0, 0) is and which way x and y grow.
I can say what size an SVG has when I give it none.
I can predict whether a shape at a given position is fully shown, cut off, or not drawn.
I can explain why a chart's y is computed as baseline minus height.