W3docs

Canvas Gradients

HTML5 Canvas gradients are patterns of color used to fill circles, rectangles, lines, text and so on. Learn about the linear and radial gradients.

A gradient, in general, is a pattern of colors that changes smoothly from one color to another. HTML5 Canvas gradients let you fill or stroke shapes — circles, rectangles, lines, text, arbitrary paths — with this kind of multi-color blend instead of a single solid color.

This chapter covers the three gradient types you can create on a 2D canvas context, how their coordinate parameters control direction and size, how addColorStop() places colors along the gradient, and several runnable examples (vertical, diagonal, text/path fills, and a radial glow). If you are new to the canvas API, start with the HTML5 Canvas introduction, then drawing shapes and paths, and review how the canvas coordinate system works.

How canvas gradients work

Working with a gradient always follows the same four steps:

  1. Create a gradient object with one of the context's factory methods:
    • ctx.createLinearGradient(x0, y0, x1, y1) — a linear (directional) gradient.
    • ctx.createRadialGradient(x0, y0, r0, x1, y1, r1) — a radial (circular) gradient.
    • ctx.createConicGradient(startAngle, x, y) — a conic (angular sweep) gradient.
  2. Add two or more color stops with gradient.addColorStop(offset, color).
  3. Assign the gradient to ctx.fillStyle or ctx.strokeStyle.
  4. Draw a shape (fillRect, fill, stroke, fillText, …). The gradient is sampled wherever you paint.

A key thing to understand: gradient coordinates are in canvas (absolute) space, not relative to the shape you fill. A gradient created from (0, 0) to (300, 0) always spans that region of the canvas. If you draw a rectangle outside that span, it picks up the gradient's first or last color (whichever is nearest), because the colors before offset 0 and after offset 1 are clamped.

addColorStop(): placing colors

gradient.addColorStop(offset, color) adds one color stop to the gradient.

  • offset — a number between 0.0 (the start of the gradient) and 1.0 (the end). Values outside this range throw an error.
  • color — any CSS color string: a name ("green"), hex ("#14389c"), rgb()/rgba(), or hsl(). Use the alpha channel (rgba(...)) for transparent stops.

You need at least two stops for a visible blend. The offset of each stop controls where the transition happens — the smaller the gap between two offsets, the sharper the color change between them. Equal spacing gives an even blend; clustering offsets creates hard bands.

<!DOCTYPE html>
<html>
  <head>
    <title>Three color stops</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="stopsCanvas" width="300" height="120"></canvas>
    <script>
      const ctx = document.getElementById("stopsCanvas").getContext("2d");
      const grd = ctx.createLinearGradient(0, 0, 300, 0);
      grd.addColorStop(0, "red");      // start
      grd.addColorStop(0.5, "yellow"); // exact middle
      grd.addColorStop(1, "green");    // end
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 120);
    </script>
  </body>
</html>

Move the middle stop from 0.5 to 0.85 and the yellow band shifts far to the right, leaving most of the bar a red-to-yellow blend — that is the offset controlling placement.

Linear Gradient

ctx.createLinearGradient(x0, y0, x1, y1) returns a gradient whose color changes along a straight line — the gradient vector that runs from the start point (x0, y0) to the end point (x1, y1):

  • x0, y0 — the start point of the gradient. The color stop at offset 0 is painted here.
  • x1, y1 — the end point of the gradient. The color stop at offset 1 is painted here.

The direction of the line between those two points sets the gradient's direction, and the distance between them sets how far the blend stretches. Lines drawn perpendicular to the vector are a single solid color.

  • A horizontal gradient keeps y equal: createLinearGradient(0, 0, 300, 0).
  • A vertical gradient keeps x equal: createLinearGradient(0, 0, 0, 200).
  • A diagonal gradient changes both: createLinearGradient(0, 0, 300, 200).

Remember the canvas coordinate system: (0, 0) is the top-left corner, x increases to the right, and y increases downward.

Example of a horizontal linear gradient using fillStyle

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 1px solid #cccccc;
      }
    </style>
  </head>
  <body>
    <canvas id="exampleCanvas" width="300" height="150">
      Your browser doesn't support the HTML5 canvas tag.
    </canvas>
    <script>
      var c = document.getElementById("exampleCanvas");
      var ctx = c.getContext("2d");
      var grd = ctx.createLinearGradient(0, 0, 300, 0);
      grd.addColorStop(0, "green");
      grd.addColorStop(1, "whitesmoke");
      ctx.fillStyle = grd;
      ctx.fillRect(20, 20, 260, 110);
    </script>
  </body>
</html>

Because the vector runs from (0, 0) to (300, 0), the blend is purely horizontal: the left edge is green and the right edge is whitesmoke.

Example of a vertical linear gradient

Keep x the same in both points (here 0) and change only y to blend top-to-bottom:

<!DOCTYPE html>
<html>
  <head>
    <title>Vertical gradient</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="verticalCanvas" width="300" height="200"></canvas>
    <script>
      const ctx = document.getElementById("verticalCanvas").getContext("2d");
      // Same x (0), different y → top-to-bottom blend.
      const grd = ctx.createLinearGradient(0, 0, 0, 200);
      grd.addColorStop(0, "#1e3c72"); // top
      grd.addColorStop(1, "#2a5298"); // bottom
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 200);
    </script>
  </body>
</html>

Example of a diagonal linear gradient

Change both x and y so the vector runs corner-to-corner:

<!DOCTYPE html>
<html>
  <head>
    <title>Diagonal gradient</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="diagonalCanvas" width="300" height="200"></canvas>
    <script>
      const ctx = document.getElementById("diagonalCanvas").getContext("2d");
      // Vector from the top-left corner to the bottom-right corner.
      const grd = ctx.createLinearGradient(0, 0, 300, 200);
      grd.addColorStop(0, "#ff512f");
      grd.addColorStop(0.5, "#f09819");
      grd.addColorStop(1, "#ffd452");
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 200);
    </script>
  </body>
</html>

Example of a linear gradient using the fillStyle with different colors:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 2px solid #202131;
      }
    </style>
  </head>
  <body>
    <canvas id="exampleCanvas" width="500" height="200"></canvas>
    <script>
      var canvas = document.getElementById('exampleCanvas');
      var context = canvas.getContext('2d');
      context.rect(0, 0, 500, 200);
      var linear = context.createLinearGradient(0, 0, 500, 200);
      linear.addColorStop(0, '#297979');
      linear.addColorStop(1, '#2ee035');
      context.fillStyle = linear;
      context.fill();
    </script>
  </body>
</html>

Example of a linear gradient using the fillStyle and strokeStyle:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 5px solid #cccccc;
      }
    </style>
    <script>
      function drawShape() {
        var canvas = document.getElementById('canvasGradient');
        if (canvas.getContext) {
          var ctx = canvas.getContext('2d');
          var lgrad1 = ctx.createLinearGradient(0, 0, 0, 300);
          lgrad1.addColorStop(0, 'blue');
          lgrad1.addColorStop(0.4, 'lightpink');
          lgrad1.addColorStop(0.5, 'purple');
          lgrad1.addColorStop(1, 'lightsalmon');
          var lgrad2 = ctx.createLinearGradient(0, 50, 0, 150);
          lgrad2.addColorStop(0, '#7afff3');
          lgrad2.addColorStop(0.5, '#191918');
          lgrad2.addColorStop(1, '#7afff3');
          ctx.fillStyle = lgrad1;
          ctx.strokeStyle = lgrad2;
          ctx.fillRect(15, 15, 120, 120);
          ctx.strokeRect(100, 50, 100, 50);
        } else {
          alert('Your browser does not support');
        }
      }
    </script>
  </head>
  <body onload="drawShape();">
    <canvas id="canvasGradient" width="300" height="300"></canvas>
  </body>
</html>

Example of a gradient on text and a path

A gradient is not limited to rectangles — it works with any fill or stroke, including text and custom paths. Set it as fillStyle before fillText() (see drawing text on canvas), or before fill()/stroke() on a path you built (see drawing on canvas).

<!DOCTYPE html>
<html>
  <head>
    <title>Gradient text and path</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="textCanvas" width="400" height="160"></canvas>
    <script>
      const ctx = document.getElementById("textCanvas").getContext("2d");

      // A gradient spanning the canvas width.
      const grd = ctx.createLinearGradient(0, 0, 400, 0);
      grd.addColorStop(0, "#8e2de2");
      grd.addColorStop(1, "#4a00e0");

      // Fill text with the gradient.
      ctx.font = "bold 48px sans-serif";
      ctx.fillStyle = grd;
      ctx.fillText("Gradient", 30, 70);

      // Stroke a triangular path with the same gradient.
      ctx.beginPath();
      ctx.moveTo(40, 100);
      ctx.lineTo(360, 100);
      ctx.lineTo(200, 145);
      ctx.closePath();
      ctx.lineWidth = 6;
      ctx.strokeStyle = grd;
      ctx.stroke();
    </script>
  </body>
</html>

Radial Gradient

ctx.createRadialGradient(x0, y0, r0, x1, y1, r1) defines a gradient between two circles. The color blends outward from the start circle to the end circle:

  • x0, y0, r0 — the center (x0, y0) and radius r0 of the start (inner) circle. The color stop at offset 0 fills this circle.
  • x1, y1, r1 — the center (x1, y1) and radius r1 of the end (outer) circle. The color stop at offset 1 is reached at the edge of this circle.

When both circles share the same center, you get a perfectly concentric glow. When the inner circle's center is offset from the outer one, the bright point shifts to one side — this is exactly how you fake a light source or a glossy highlight (the example below uses offset centers). Making r0 greater than 0 produces a solid core of the first color before the blend begins.

Example of a radial gradient with offset centers

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      canvas {
        border: 2px solid #cccccc;
      }
    </style>
  </head>
  <body>
    <canvas id="exampleCanvas" width="300" height="150">
      Your browser doesn't support the HTML5 canvas tag.
    </canvas>
    <script>
      var c = document.getElementById("exampleCanvas");
      var ctx = c.getContext("2d");
      var grd = ctx.createRadialGradient(155, 80, 20, 130, 40, 190);
      grd.addColorStop(0, "#14389c");
      grd.addColorStop(1, "white");
      ctx.fillStyle = grd;
      ctx.fillRect(15, 15, 270, 120);
    </script>
  </body>
</html>

Here the inner circle is centered at (155, 80) with radius 20, while the outer circle is centered at (130, 40) with radius 190. Because the centers differ, the dark-blue core sits toward the lower right and fades to white off-center, giving the fill a three-dimensional, lit-from-one-side look.

Example of a radial glow

A small, fully transparent outer stop over a transparent canvas region creates a soft glow you can layer over other drawings. Note the use of rgba() so the edge fades to nothing instead of to white:

<!DOCTYPE html>
<html>
  <head>
    <title>Radial glow</title>
    <style>
      canvas { border: 1px solid #cccccc; background: #11131f; }
    </style>
  </head>
  <body>
    <canvas id="glowCanvas" width="300" height="200"></canvas>
    <script>
      const ctx = document.getElementById("glowCanvas").getContext("2d");
      // Concentric circles: solid core at (150,100), fading out to radius 110.
      const grd = ctx.createRadialGradient(150, 100, 5, 150, 100, 110);
      grd.addColorStop(0, "rgba(255, 214, 102, 1)");   // bright core
      grd.addColorStop(0.4, "rgba(255, 154, 0, 0.6)"); // warm mid
      grd.addColorStop(1, "rgba(255, 154, 0, 0)");     // transparent edge
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 300, 200);
    </script>
  </body>
</html>

Conic Gradient

ctx.createConicGradient(startAngle, x, y) creates a gradient that sweeps the colors around a center point, like a color wheel or a pie chart, rather than along a line or between circles:

  • startAngle — the angle in radians at which offset 0 begins, measured clockwise from the positive x-axis.
  • x, y — the center point of the rotation.

Color stops are placed around the full turn, so offset 0 and offset 1 meet back at startAngle. To avoid a visible seam, give the first and last stops the same color.

<!DOCTYPE html>
<html>
  <head>
    <title>Conic gradient</title>
    <style>
      canvas { border: 1px solid #cccccc; }
    </style>
  </head>
  <body>
    <canvas id="conicCanvas" width="200" height="200"></canvas>
    <script>
      const ctx = document.getElementById("conicCanvas").getContext("2d");
      // Sweep starting at the top (-90° = -Math.PI/2), centered at (100,100).
      const grd = ctx.createConicGradient(-Math.PI / 2, 100, 100);
      grd.addColorStop(0, "red");
      grd.addColorStop(0.25, "yellow");
      grd.addColorStop(0.5, "lime");
      grd.addColorStop(0.75, "blue");
      grd.addColorStop(1, "red"); // matches stop 0 → seamless wheel
      ctx.fillStyle = grd;
      ctx.fillRect(0, 0, 200, 200);
    </script>
  </body>
</html>

createConicGradient() is supported in current versions of all major browsers (Chrome, Edge, Firefox, and Safari). Provide a fallback solid color for very old browsers if you must support them.

Practice

Practice
Which of these methods are used to apply colors, patterns, and gradients to the draw shapes on the HTML5 canvas?
Which of these methods are used to apply colors, patterns, and gradients to the draw shapes on the HTML5 canvas?
Practice
What does the offset argument of addColorStop(offset, color) represent?
What does the offset argument of addColorStop(offset, color) represent?
Practice
To make a linear gradient blend straight down (top to bottom), how should the points in createLinearGradient(x0, y0, x1, y1) be set?
To make a linear gradient blend straight down (top to bottom), how should the points in createLinearGradient(x0, y0, x1, y1) be set?
Was this page helpful?