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:
- 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.
- Add two or more color stops with
gradient.addColorStop(offset, color). - Assign the gradient to
ctx.fillStyleorctx.strokeStyle. - 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 between0.0(the start of the gradient) and1.0(the end). Values outside this range throw an error.color— any CSS color string: a name ("green"), hex ("#14389c"),rgb()/rgba(), orhsl(). 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 offset0is painted here.x1, y1— the end point of the gradient. The color stop at offset1is 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
yequal:createLinearGradient(0, 0, 300, 0). - A vertical gradient keeps
xequal: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 radiusr0of the start (inner) circle. The color stop at offset0fills this circle.x1, y1, r1— the center(x1, y1)and radiusr1of the end (outer) circle. The color stop at offset1is 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 offset0begins, 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.