I have the following code:
.container{
width: 100px;
height: 200px;
background-color: red;
resize: both; /* Just to make it... */
overflow: hidden; /* ...resizable for testing. */
}
<div class="container">
<svg width="100%" height="100%">
<circle cx="50%" cy="50%" r="25%" fill="black"></circle>
</svg>
</div>
As I resize .container
, I can easily see that:
cx
is percentage of the widthcy
is percentage of the heightBut I cannot understand what r
is percentage of. What is r
percentage of?
As commented by Roko C. Buljan when using % units the relative value refers to the normalized diagonal length.
See the W3C SVG 2 specs (working draft) "8.9. Units"
For any other length value expressed as a percentage of the SVG viewport, the percentage must be calculated as a percentage of the normalized diagonal of the ‘viewBox’ applied to that viewport. If no ‘viewBox’ is specified, then the normalized diagonal of the SVG viewport must be used. The normalized diagonal length must be calculated with
sqrt((width)**2 + (height)**2)/sqrt(2)
.
here's an example
let w = 100;
let h = 200;
let c = Math.sqrt(w ** 2 + h ** 2) / Math.sqrt(2)
let rAbsolute = c * 0.25
// get absolute radius via baseVal
let r = c1.r.baseVal.value
console.log(rAbsolute, r)
.container {
width: 100px;
height: 200px;
background-color: red;
}
<div class="container">
<svg width="100%" height="200px">
<circle id="c1" cx="50%" cy="50%" r="25%" fill="#ccc"></circle>
<circle cx="50%" cy="50%" r="39.52847075210474" fill="none" stroke="blue" />
</svg>
</div>
You can also check your calculations using the baseVal
property from the SVGAnimatedLength
interface.
If you actually need the circle scale more predictably you may also add a square-shaped viewBox
. In this case the preserveAspectRatio
(in the example below the default "xMidYMid meet") attribute will affect the alignment and scaling.
.container {
width: 100px;
height: 200px;
background-color: red;
resize: both;
overflow: hidden;
}
<div class="container">
<svg width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet">
<rect width="100%" height="100%" fill="none" stroke="#ccc"/>
<circle cx="50%" cy="50%" r="25%" fill="black" />
</svg>
</div>
As you can see the radius of the circle stays at 25% relative to the 100x100 viewBox
(so the circle stays 50% wide).