JavaScript Canvas Stroke Properties
Written by Ian Elliot   
Monday, 10 February 2020
Article Index
JavaScript Canvas Stroke Properties

The stroke function simply colors the outline of the path. This all sounds easy and obvious, but in practice it is subtle and you need to understand it to get control of what exactly is happening. In this extract from a chapter in my new book on JavaScript Graphics we look at some of the fine detail of stroke.

Now available as a paperback or ebook from Amazon.

JavaScript Bitmap Graphics
With Canvas




  1. JavaScript Graphics
  2. Getting Started With Canvas
  3. Drawing Paths
      Extract: Basic Paths 
      Extract: Bezier Curves 
  4. Stroke and Fill
      Extract: Stroke Properties 
      Extract: Fill and Holes **NEW!
  5. Transformations
      Extract: Transformations 
  6. Text
      Extract: Text, Typography & SVG 
      Extract: Unicode 
  7. Clipping, Compositing and Effects
      Extract: Clipping & Basic Compositing 
  8. Generating Bitmaps
      Extract:  Introduction To Bitmaps 
  9. WebWorkers & OffscreenCanvas
      Extract: OffscreenCanvas
  10. Bit Manipulation In JavaScript
  11. Typed Arrays
  12. Files, blobs, URLs & Fetch
      Extract: Blobs & Files
      Extract: Read/Writing Local Files 
  13. Image Processing
      Extract: ImageData
      Extract: The Filter API
  14. 3D WebGL
  15. 2D WebGL
    Extract: WebGL Convolutions 






In chapter but not in this extract:

  • Color
  • Alpha
  • Stroke and Fill Color

Stroke Properties

There are a set of properties of the drawing context which change the way a path is stroked starting with the most fundamental which sets the width of the stroke:

ctx.lineWidth = value;

The value is the width in the co-ordinate system. By default this is set to 1.0 and the stroke is drawn equally each side of the path. That is, the path defines a line centered on the path with half the width to either side. Because of the way antialiasing works, this has some unexpected consequences, see the next section.

The lineCap property sets the way a line ends. The possible values are butt, round or square. The only real problem with lineCap is working out exactly what the types correspond to. The default, butt, simply ends the line where you specify, using a straight edge, round puts a small semicircle on the end, so lengthening the line by its LineWidth, and square does the same thing, but with a square.

You can see the effect of lineCap using the following program:

ctx.lineWidth = 10;
var path1 = new Path2D();
path1.moveTo(100, 300);
path1.lineTo(500, 300);
ctx.lineCap = "butt";
var path2 = new Path2D();
path2.moveTo(100, 320);
path2.lineTo(500, 320);
ctx.lineCap = "round";
var path3 = new Path2D();
path3.moveTo(100, 340);
path3.lineTo(500, 340);
ctx.lineCap = "square";

This draws three lines, each with a different lineCap:


You can see that the round and square lineCaps really do make the line longer. The round cap is useful if you want a decorative line, an underlining say, but what is the use of the square lineCap? The answer is the way two disconnected lines meet. For example, if you draw a right angle to the same point using two butt ends the result has a small square missing:


If you use square ends however the result is a sharp corner:


Notice that this only applies if the two lines are not connected, i.e. not part of a closed sub-path. If the lines are connected then what controls the way that they connect is the lineJoin property, which can be set to any of bevel, round or miter (default). The miter join is usually what you expect to happen when lines join – their outside edges are extended to where they meet:


Last Updated ( Monday, 10 February 2020 )