Is there a way to curve / arc text using CSS3 / Canvas

JavascriptHtmlCanvasCss

Javascript Problem Overview


I'm trying to make a curved text effect using CSS3, HTML Canvas, or even SVG (see image below for example)? Is this possible? If so, how can I achieve this effect?

Update: To clarify: The text that will be styled this way will be dynamic.

Arched or Curved Text Example

Javascript Solutions


Solution 1 - Javascript

SVG supports text-on-a-path directly, though it does not 'bend' the individual glyphs along the path. Here's an example of how you create it:

...
<defs>
  <path id="textPath" d="M10 50 C10 0 90 0 90 50"/>
</defs>
<text fill="red">
  <textPath xlink:href="#textPath">Text on a Path</textPath>
</text>
...

Solution 2 - Javascript

You can certainly do it with canvas, try out this code as an example:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Testing min-width and max-width</title>
    <style type="text/css">
       
    </style>
    
  </head>
  <body>
      <canvas id="cnv"></canvas>
      <script type="text/javascript" charset="utf-8">
          cnv = document.getElementById("cnv");
          cnv.width = 500;
          cnv.height = 300;
          ctx = cnv.getContext("2d");
          ctx.font = "bold 12px sans-serif";
          text = "abcdefghijklm"
          for (i = 0; i < text.length; i++) {
              ctx.fillText(text[i], 300, 100);
              ctx.rotate(0.1);
          }
      </script>
  </body>
</html>

It doesn't do it exactly right, but I'm certain you'll manage to tweak it to your likening ;)

Solution 3 - Javascript

Or you can do it using some CSS, however I'm sure you won't get it running on IE any time soon. On the other hand the cool thing is that the text is selectable :D

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>Testing min-width and max-width</title>
    <style type="text/css">
        .num1 {
            -webkit-transform: translate(0px, 30px) rotate(-35deg); 
        }
        .num2 {
            -webkit-transform: translate(0px, 25px) rotate(-25deg); 
        }
        .num3 {
            -webkit-transform: translate(0px, 23px) rotate(0deg); 
        }
        .num4 {
            -webkit-transform: translate(0px, 25px) rotate(25deg); 
        }
        .num5 {
            -webkit-transform: translate(0px, 30px) rotate(35deg); 
        }
       
       span {display: inline-block; margin: 1px;}
    </style>
    
  </head>
  <body>
    <div style="width: 300px; height: 300px; margin: 50px auto">
      <span class="num1">a</span><span class="num2">b</span><span class="num3">c</span><span class="num4">d</span><span class="num5">e</span>
    </div>
</body>
</html>

Solution 4 - Javascript

It's not a pure CSS solution but CircleType.js works great for arced text.

http://circletype.labwire.ca/

Solution 5 - Javascript

There is a jQuery Plugin to curve text using CSS3 called arctext.js. It's pretty good and has a range of configuration options. I guess it won't work on IE8 but I guess most CSS3 thing don't!

There's also a demo page with some example of it in action here.

Solution 6 - Javascript

<embed width="100" height="100" type="image/svg+xml" src="path.svg">
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <defs>
      <path id="textPath" d="M10 50 C10 0 90 0 90 50"/>
    </defs>
  </svg>
</embed>

Solution 7 - Javascript

This [tutorial][1] shows you exactly how to do it using HTML5 and canvas. One of the other answers presented a similar idea, which is to use the canvas.rotate method. This one also uses canvas.translate.

The full code from the tutorial is:

function drawTextAlongArc(context, str, centerX, centerY, radius, angle) {
  var len = str.length,
    s;
  context.save();
  context.translate(centerX, centerY);
  context.rotate(-1 * angle / 2);
  context.rotate(-1 * (angle / len) / 2);
  for (var n = 0; n < len; n++) {
    context.rotate(angle / len);
    context.save();
    context.translate(0, -1 * radius);
    s = str[n];
    context.fillText(s, 0, 0);
    context.restore();
  }
  context.restore();
}
var canvas = document.getElementById('myCanvas'),
  context = canvas.getContext('2d'),
  centerX = canvas.width / 2,
  centerY = canvas.height - 30,
  angle = Math.PI * 0.8,
  radius = 150;

context.font = '30pt Calibri';
context.textAlign = 'center';
context.fillStyle = 'blue';
context.strokeStyle = 'blue';
context.lineWidth = 4;
drawTextAlongArc(context, 'Text along arc path', centerX, centerY, radius, angle);

// draw circle underneath text
context.arc(centerX, centerY, radius - 10, 0, 2 * Math.PI, false);
context.stroke();

<!DOCTYPE HTML>
<html>

<head>
  <style>
    body {
      margin: 0px;
      padding: 0px;
    }
  </style>
</head>

<body>
  <canvas id="myCanvas" width="578" height="250"></canvas>
</body>

</html>

[1]: https://web.archive.org/web/20150325014452/http://www.html5canvastutorials.com/labs/html5-canvas-text-along-arc-path/ "tutorial"

Solution 8 - Javascript

You can use SVG with TextPath like this:

<html>

http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> THIS TEXT IS CURVED

</html>

Solution 9 - Javascript

I used the tutorial mentioned above (by Simon Tewsi) to write a better solution, regarding the kerning issue. Uses no library, pure JS.

See it at http://jsfiddle.net/fidnut/cjccg74f/

function drawTextAlongArcInside(ctx, str, font, color, radius, angle, centerX, centerY, wspace)

Note: SO is demanding that I put all the code from JSFiddle in here too. I don't think this is wise, too much code, so I am adding only the name of the function.

Solution 10 - Javascript

There is also transform: skew(x, y, z), which does not use canvas.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongabrielView Question on Stackoverflow
Solution 1 - JavascriptPhrogzView Answer on Stackoverflow
Solution 2 - JavascriptJakub HamplView Answer on Stackoverflow
Solution 3 - JavascriptJakub HamplView Answer on Stackoverflow
Solution 4 - JavascriptpeterhryView Answer on Stackoverflow
Solution 5 - JavascriptMark RhodesView Answer on Stackoverflow
Solution 6 - Javascriptsignano AnasView Answer on Stackoverflow
Solution 7 - JavascriptSimon TewsiView Answer on Stackoverflow
Solution 8 - JavascriptVerebView Answer on Stackoverflow
Solution 9 - JavascriptRookie VeeView Answer on Stackoverflow
Solution 10 - JavascriptApostolos DedeloudisView Answer on Stackoverflow