Circular SVG text, two paths, no backwards text
Introduction
Born from a funny story my wife told me about an interaction with a young foreign student who was tired of ‘grammar’ lessons many years ago I wanted to create a memorable way of displaying it.
Text orientation & Font
The key elements for me were making sure the final word (Grammar) matched the orientation of the first two words (Too Many) above it… and using a fun bubble font for effect.
Enough jibber-jabber, here’s the result;
Following SVG paths with text
Think of the SVG as two paths running left to right. The type is locked to the path so it always reads forward. One path arcs over the circle the other dips underneath. Because both share the same orientation, neither line flips. You get top and bottom curves, with all letters upright instead of one line going upside down.
The core idea, paths, not circles
<textPath> doesn’t care about circles as shapes, it only cares about a path, a sequence of points with a direction.
In this example, I didn’t use <circle> for the text, I drew two arcs manually;
<!-- Top arc: left→right over the top -->
<path
id="tooManyTop"
d="M 40,150
A 110,110 0 0 1 260,150"
fill="none"
/>
<!-- Bottom arc: left→right under the bottom -->
<path
id="tooManyBottom"
d="M 40,150
A 110,110 0 0 0 260,150"
fill="none"
/>
M 40,150
Moves the pen to the left side of the circle.A 110,110 0 0 1 260,150
Draws an arc to the right side, curving over the top.A 110,110 0 0 0 260,150
Draws an arc to the right side again, but with the sweep flag flipped so it curves under the bottom.
Both arcs run left→right in the code. That’s the crucial bit.
Splitting the circle into two arcs
Now that there are two paths, I’ll hang some text on them with <textPath>
<text>
<textPath
href="#tooManyTop"
startOffset="50%"
text-anchor="middle"
dominant-baseline="middle"
>
Too Many
</textPath>
</text>
<text>
<textPath
href="#tooManyBottom"
startOffset="50%"
text-anchor="middle"
dominant-baseline="middle"
>
Grammar
</textPath>
</text>
Three attributes do most of the layout work;
href="#tooManyTop"/href="#tooManyBottom"
Which ‘path’ the text adheres to.startOffset="50%"
Position the text halfway along the path length.text-anchor="middle"
Align the middle of the text with that point, so the word is centred on the arc.
So, “Too Many” is centred on the top arc, which bends upwards and “Grammar” is centred on the bottom, which bends downwards. Because both arcs are left→right, the letters never rotate past 180° relative to you, so they all read upright.
Responsiveness
SVG’s viewBox is doing the heavy lifting for responsiveness;
<svg
viewBox="0 0 300 300"
role="img"
aria-labelledby="tooManyTitle tooManyDesc"
>
…
</svg>
Everything inside (circle, arcs & text) live in a 300×300 coordinate system, so when you control the sizes with CSS…
.svg-styles {
max-width: 600px; /* Remove this for full width of parent */
width: 100%;
height: auto;
}
svg text {
font-family: "Sniglet-ExtraBold";
font-size: 56px;
fill: #444;
}
…the whole coordinate space scales as a single entity.
- The circle radius (110), arc positions, and font‑size (56px) all scale proportionally as the
SVGgrows or shrinks. - Because the top and bottom paths stay in the same relative positions, “Too Many” and “Grammar” keep hugging the circle in exactly the same way at every size.
SVG vs CSS
A quick note about recreating the design using pure CSS… let’s just say that’s four hours I’ll never get back. SVG is far simpler, especially when responsive design is taken into account and requires less code making the codebase easier to maintain.
Download sample code
I’ve assembled all the parts so that you can play with them. The standard – software is provided “as is”, without warranty of any kind – applies here.
That’s all folks
I’ve subsetted the font for web performance, so only T, O, M, A, N, Y, G & R are included. In the demo, there’s an optional reference circle (commented out) you can toggle if you want to experiment. Hope you have fun playing with it.
// End of Project
More Information
Further Reading
- Sniglet Font (fonts.google.com)
- MDN Docs: SVG Paths (developer.mozilla.org)
- MDN Docs: SVG textPath (developer.mozilla.org)
- MDN Docs: SVG startOffset (developer.mozilla.org)
- MDN Docs: SVG text-anchor (developer.mozilla.org)