Command Palette

Search for a command to run...

Hectal
PHASE 1Beginner ~24 min· topic 1 of 7

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.

a shape at a positionwhole filehtml
<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.

Put shapes on and over the edgediagram
Rendering diagram…

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. 1

    Move the orange circle into view

    In the first example, change corner to cx: 30, cy: 30. The whole circle is now inside, and the Console says fully inside for it. The shape did not change, only its centre: the number decides where it sits.

  2. 2

    Make the SVG bigger instead

    In the first example's HTML, change width="300" to width="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 says off: ... -> not drawn because the script's test hard-codes 300. Change 300 to 400 in the right <= 300 and b.x < 300 tests and the line becomes off: x 305 to 355, y 50 to 100 -> fully inside.

  3. 3

    Give the second example a CSS size

    In the second example, add style="height: 200px" to the height only SVG. The line becomes 300.00 x 200.00: the CSS height beats height="80", and the width is still the default 300.

Code & diagrams

Where shapes land, and where they vanish New tab

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

Press Run to see the page.

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: 5
How big is an SVG? Nine situations New tab

The first line is the default every SVG falls back to. The orange squares show the shape at (0, 0) in each drawing area.

Preview

Press Run to see the page.

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.00

Break 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.

terminal
$ Preview and Console
── what you'll see ──
The SVG is still 300 by 150 (the default), so the picture looks the same. Now change the grid loop to x <= 400: the extra lines and labels between 300 and 400 are not drawn, and the Console prints no error.

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".

terminal
$ Preview
── what you'll see ──
The dot appears 40 units from the top, near the top of the picture. If you expected it near the bottom (a small value low on the chart), it is in the wrong place. No error is printed.

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 sets overflow: hidden on any svg that is not the root of the document. Set overflow: visible in 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 its width and height (Topic 0.5).

  • ▸

    An SVG with width="0" or height="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. 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. 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). x is the distance to the right, and y is 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. 3

    User units. The numbers inside an SVG are user units. They carry no unit name (no px, no cm). By default one user unit is one CSS pixel, so x="50" is 50 pixels from the left. Topic 1.4 shows how viewBox changes that rule, so the drawing's numbers and the screen's pixels no longer match one to one.

  4. 4

    The size of the SVG. The width and height attributes 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 CSS width or height on the same element overrides the attribute. The first example below measures all of this.

  5. 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. 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.25 are common, because scales compute them. Two or three decimal places are plenty for a screen. A bad value (the text NaN, 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

01

Where is the point (0, 0), and which way do x and y grow?

02

What size is an SVG with no width and height, and what happens to a shape outside that area?

03

Why does a chart that maps bigger values to bigger y look upside down?

04

What is a user unit, and when does it equal a pixel?

Practice

01

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.

02

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.