SVG center text in circle
Add text-anchor="middle"
to the text
element.
Plunker
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd"
viewBox="0 0 500 500">
<g id="UrTavla">
<circle style="fill:url(#toning);stroke:#010101;stroke-width:1.6871;stroke-miterlimit:10;" cx="250" cy="250" r="245">
</circle>
<text x="50%" y="50%" text-anchor="middle" stroke="#51c5cf" stroke-width="2px" dy=".3em">Look, I’m centered!Look, I’m centered!</text>
</g>
</svg>
The solution proposed and accepted is INVALID when you want to draw a circle
that is not centered on container !
Using x="50%"
y="50%"
on text
tag works only when SVG element contains a circle that is centered on viewPort.
If you want to draw 3 circles, you must also change (x,y) text coordinates so that they are equal to (cx,cy) circle coordinates has done in following example
As proposed by random
, I have added alignment-baseline="middle"
for first circle in code snippet only so you can see that for Label
text is now perfectly aligned (vertically).
<svg height="350" width="350">
<circle cx="110" cy="110" r="100"
stroke="red"
stroke-width="3"
fill="none"
/>
<text x="110" y="110"
text-anchor="middle"
stroke="red"
stroke-width="1px"
alignment-baseline="middle"
> Label
</text>
<circle cx="240" cy="110" r="100"
stroke="blue"
stroke-width="3"
fill="none"
/>
<text x="240" y="110"
text-anchor="middle"
stroke="blue"
stroke-width="1px"
> Ticket
</text>
<circle cx="170" cy="240" r="100"
stroke="green"
stroke-width="3"
fill="none"
/>
<text x="170" y="240"
text-anchor="middle"
stroke="green"
stroke-width="1px"
> Vecto
</text>
</svg>
Just for the fun, I have put code with 3 circles to select each parts. Just click on it !
function setReadableCode()
{
var circLabel = document.getElementById('circLabel');
var circTicket = document.getElementById('circTicket');
var circVecto = document.getElementById('circVecto');
var interLabelTicket = document.getElementById('interLabelTicket');
var interTicketVecto = document.getElementById('interTicketVecto');
var interVectoLabel = document.getElementById('interVectoLabel');
var interLabelTicketVecto = document.getElementById('interLabelTicketVecto');
}
function clickCircle(sCircle, sInter2a, sInter2b, sInter3)
{
var circ = document.getElementById(sCircle);
var inter2a = document.getElementById(sInter2a);
var inter2b = document.getElementById(sInter2b);
var inter3 = document.getElementById(sInter3);
var sColor = '';
if (circ.style.fill == '' || circ.style.fill == 'white')
{
sColor = 'yellow';
}
else
{
sColor = 'white';
}
circ.style.fill = sColor;
inter2a.style.fill = sColor;
inter2b.style.fill = sColor;
inter3.style.fill = sColor;
setReadableCode();
}
function clickCircLabel() {
clickCircle('circLabel', 'interLabelTicket', 'interVectoLabel', 'interLabelTicketVecto');
}
function clickCircTicket() {
clickCircle('circTicket', 'interLabelTicket', 'interTicketVecto', 'interLabelTicketVecto');
}
function clickCircVecto() {
clickCircle('circVecto', 'interVectoLabel', 'interTicketVecto', 'interLabelTicketVecto');
}
function clickIntersection2(sInter2, sInter3) {
var inter2 = document.getElementById(sInter2);
var inter3 = document.getElementById(sInter3);
var sColor = '';
if (inter2.style.fill == '' || inter2.style.fill == 'white') {
sColor = 'yellow';
}
else {
sColor = 'white';
}
inter2.style.fill = sColor;
inter3.style.fill = sColor;
setReadableCode();
}
function clickInterLabelTicket() {
clickIntersection2('interLabelTicket', 'interLabelTicketVecto');
}
function clickInterTicketVecto() {
clickIntersection2('interTicketVecto', 'interLabelTicketVecto');
}
function clickInterVectoLabel() {
clickIntersection2('interVectoLabel', 'interLabelTicketVecto');
}
function clickInterLabelTicketVecto() {
var inter = document.getElementById('interLabelTicketVecto');
var sColor = '';
if (inter.style.fill == '' || inter.style.fill == 'white') {
sColor = 'yellow';
}
else {
sColor = 'white';
}
inter.style.fill = sColor;
setReadableCode();
}
text
{
font-family:Arial;
}
<svg height="350" width="350">
<circle id="circLabel" cx="110" cy="110" r="100" stroke="red" stroke-width="0" fill="white" onclick="clickCircLabel();"/>
<text x="60" y="110" text-anchor="middle" stroke="red" stroke-width="1px" onclick="clickCircLabel();">Label</text>
<circle id="circTicket" cx="210" cy="110" r="100" stroke="blue" stroke-width="0" fill="yellow" onclick="clickCircTicket();"/>
<text x="260" y="110" text-anchor="middle" stroke="blue" stroke-width="1px" onclick="clickCircTicket();">Ticket</text>
<circle id="circVecto" cx="160" cy="196.602541" r="100" stroke="green" stroke-width="0" fill="white" onclick="clickCircVecto();" />
<text x="160" y="240" text-anchor="middle" stroke="green" stroke-width="1px" onclick="clickCircVecto();">Vecto</text>
<path id="interLabelTicket"
d="M 160 23.397460 a100,100 0 0,0 0,173.205081 a100,100 0 0,0 0,-173.205081 z"
fill="white"
stroke-width="3"
onclick="clickInterLabelTicket();"
/>
<path id="interVectoLabel"
d="M 60 196.602541 a100,100 0 0,0 150,-86.602540 a100,100 0 0,0 -150,86.602540 z"
fill="white"
stroke-width="3"
onclick="clickInterVectoLabel();"
/>
<path id="interTicketVecto"
d="M 260 196.602541 a100,100 0 0,0 -150,-86.602540 a100,100 0 0,0 150,86.602540 z"
fill="white"
stroke-width="3"
onclick="clickInterTicketVecto();"
/>
<path id="interLabelTicketVecto"
d="M 110 110 a100,100 0 0,1 100,0 a100,100 0 0,1 -50,86.602540 a100,100 0 0,1 -50,-86.602540 z"
fill="none"
stroke-width="3"
onclick="clickInterLabelTicketVecto();"
/>
<circle cx="110" cy="110" r="100" stroke="red" stroke-width="3" fill="none" />
<circle cx="210" cy="110" r="100" stroke="blue" stroke-width="3" fill="none" />
<circle cx="160" cy="196.602541" r="100" stroke="green" stroke-width="3" fill="none"/>
</svg>
Maybe, could be useful also alignment-baseline="middle"
, with text-anchor="middle"
:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" viewBox="0 0 500 500">
<g id="UrTavla">
<circle style="fill:url(#toning);stroke:#010101;stroke-width:1.6871;stroke-miterlimit:10;" cx="250" cy="250" r="245" /> <!--self-closing tag-->
<text x="50%" y="50%" stroke="#51c5cf" stroke-width="2px" dy=".3em" text-anchor="middle" alignment-baseline="middle"> Look, I’m centered!Look, I’m centered! </text>
</g>
</svg>
Here a good resource: http://apike.ca/prog_svg_text_style.html
Cheers
A simpler solution that works with non-centered circles is to put circles and texts inside translated groups.
That way you don't need to repeat the coordinates on the text.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Centered texts</title>
</head>
<body ng-controller="MainCtrl">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
<g transform="translate(300, 300)" >
<circle fill="none" stroke="black" stroke-width="1px" r="120"/>
<text stroke="blue" stroke-width="1px" text-anchor="middle" alignment-baseline="central">Look, I’m centered!</text>
</g>
<g transform="translate(150, 150)" >
<circle fill="none" stroke="black" stroke-width="1px" r="120"/>
<text stroke="blue" stroke-width="1px" text-anchor="middle" alignment-baseline="central">Look, I’m also centered!</text>
</g>
</svg>
</body>
</html>
The behaviors are not consistent across browsers using alignment-baseline="central"
. Notably, Chrome will position correctly but Firefox will not. If you use dominant-baseline="central"
it will appear correctly in both.
<svg viewBox="0 0 500 500" role="img" xmlns="http://www.w3.org/2000/svg">
<g id="myid">
<circle stroke="darkgray" stroke-width="1px" fill="lightgray" cx="250" cy="250" r="245"/>
<text style="font: bold 10rem sans-serif;" text-anchor="middle" dominant-baseline="central" x="50%" y="50%">Centered</text>
</g>
</svg>