Reputation: 1973
I'm trying to center text in a circle with SVG. The size of the text will be dynamic.
My code on 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%" stroke="#51c5cf" stroke-width="2px" dy=".3em"> Look, I’m centered!Look, I’m centered! </text>
</g>
</svg>
Upvotes: 86
Views: 133261
Reputation: 3735
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).
This image is on //github.com/schlebe/SVG-Images/blob/main/Cercles.Selection.svg
<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>
Upvotes: 59
Reputation: 1633
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's a good resource: http://apike.ca/prog_svg_text_style.html
Upvotes: 20
Reputation: 4866
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.
FireFox:
Chrome:
svg { height:140px }
<h4>alignment-baseline AND dominant-baseline settings:</h4>
<svg viewBox="0 0 48 48">
<circle stroke="darkgray" stroke-width="1px"
fill="lightgray" cx="50%" cy="50%" r="48%"/>
<line x1="0" y1="50%" x2="100%" y2="50%" stroke="blue" stroke-width="1"/>
<text text-anchor="middle" alignment-baseline="central" x="50%" y="50%">central</text>
</svg>
<svg viewBox="0 0 48 48">
<circle stroke="darkgray" stroke-width="1px"
fill="lightgray" cx="50%" cy="50%" r="48%"/>
<line x1="0" y1="50%" x2="100%" y2="50%" stroke="blue" stroke-width="1"/>
<text text-anchor="middle" alignment-baseline="middle" x="50%" y="50%">middle</text>
</svg>
<svg viewBox="0 0 48 48">
<circle stroke="darkgray" stroke-width="1px"
fill="lightgray" cx="50%" cy="50%" r="48%"/>
<line x1="0" y1="50%" x2="100%" y2="50%" stroke="blue" stroke-width="1"/>
<text text-anchor="middle" dominant-baseline="central" x="50%" y="50%">central</text>
</svg>
<svg viewBox="0 0 48 48">
<circle stroke="darkgray" stroke-width="1px"
fill="lightgray" cx="50%" cy="50%" r="48%"/>
<line x1="0" y1="50%" x2="100%" y2="50%" stroke="blue" stroke-width="1"/>
<text text-anchor="middle" dominant-baseline="middle" x="50%" y="50%">middle</text>
</svg>
Upvotes: 13
Reputation: 22998
Add text-anchor="middle"
to the text
element.
<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>
Upvotes: 104
Reputation: 1
it is super easy to make text center in SVG circle.
<svg height="300" width="300">
<circle cx="120" cy="120" r="30%" fill="#117da9" />
<text x="50" y="120" fill="white">Center Text in SVG Circle</text>
</svg>
All you need to do is change <text> tag x and y values until the given text align in the center of the circle. For example, here x and y values are x="50" y="120"
Upvotes: -2
Reputation: 1154
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>
Upvotes: 16