Why do I have to change the `x` & `y` values of this 'rect' for it to be at the top-left of its viewport?

Viewed 189

<svg width="200" height="200" style="border: solid blue 5px;">
  <rect x="0" y="0" height="50" width="100" stroke="purple" stroke-width="30px" fill="green"/>
</svg>

What is needed to make the rect right against the top-left of its container?


SOLUTION - BUT DON'T KNOW WHY

<svg width="200" height="200" style="border: solid blue 5px; overflow: visible">
  <rect x="15" y="15" height="50" width="100" stroke="purple" stroke-width="30px" fill="green"/>
</svg>

2 Answers

Your x and y values should be half of the stroke-width. So, if your stroke-width is 50, your x and y values should be 25. The reason for this is that the stroke-width “grows” both to the inside and the outside of the rect, therefore half of that stroke will be hidden when expended. Try changing the size of the rect and the stroke and you will see that using half its value for x and y will always show the entire image as desired.

There are 3 possibilities:

  1. calculate the x-y-offset of the rectangle depending on the stroke-width to compensate the offset dislocation of the stroke-width: offset-x and offset-y values are stroke-width / 2

<svg width="200" height="200" style="border: solid blue 5px;">
  <rect x="15" y="15" height="50" width="100" stroke="purple" stroke-width="30px" fill="green"/>
</svg>

  1. instead of making the second color shape via stroke, you could use 2 rectangles with stroke-width="0px": adding 30px to height and width of the outer one, and subtracting 30px from the inner one, which gives you the same result as above

<svg width="200" height="200" style="border: solid blue 5px;">
  <rect x="0" y="0" height="80" width="130" stroke="purple" stroke-width="0px" fill="purple"/>
  <rect x="30" y="30" height="20" width="70" stroke="purple" stroke-width="0px" fill="green"/>
</svg>

  1. in case you don't need to care about the size of your svg's viewport (the outer bounding box), you could also get the same result setting the svg height and width to the inner rectangle and compensate the stroke-width with padding of stroke-width/2

<svg width="100" height="50" style="border: solid blue 5px; padding:15px; background-color:purple;">
  <rect x="0" y="0" height="50" width="100" stroke="purple" stroke-width="30px" fill="green"/>
</svg>

see also: StrokeWidthProperty:

This property specifies the width of the stroke on the current object.
A zero value causes no stroke to be painted.

Related