# Dégradé canvas HTML : createLinearGradient, radial et conique

[Canonical HTML page](https://gradiently.design/fr/guide/canvas-gradient)

Les dégradés canvas prennent des coordonnées là où le CSS prend des angles, et cette seule différence cause l’essentiel de la confusion. Voici chaque méthode de dégradé avec du code qui fonctionne, et une fonction qui convertit un angle CSS en points canvas.

## The short version

- Un dégradé canvas HTML est un objet CanvasGradient créé avec createLinearGradient, createRadialGradient ou createConicGradient, doté d’arrêts de couleur via addColorStop, puis affecté à fillStyle ou strokeStyle.
- Les dégradés canvas utilisent des coordonnées dans l’espace du canvas, pas des angles ni des pourcentages, donc un dégradé linéaire a besoin d’un point de départ et d’un point d’arrivée.
- Les positions des arrêts vont de 0 à 1, et toute chaîne de couleur CSS est acceptée, y compris hex, rgb(), hsl() et oklch() dans les navigateurs actuels.
- createConicGradient commence son balayage depuis une ligne orientée vers la droite et mesure l’angle en radians, contrairement à conic-gradient en CSS, qui part du haut en degrés.
- Sur les écrans haute densité, dimensionnez le tampon du canvas selon devicePixelRatio, sinon dégradés et texte paraissent flous.

Un **dégradé canvas HTML** se fait en trois étapes : créer un objet dégradé avec `ctx.createLinearGradient()`, `createRadialGradient()` ou `createConicGradient()`, ajouter des couleurs avec `addColorStop(offset, colour)`, puis l’affecter à `ctx.fillStyle` et dessiner. Contrairement au CSS, un dégradé canvas est défini par des points en pixels, vous lui indiquez donc exactement où la couleur commence et finit. Tout ce que vous peignez avec ce remplissage reprend la partie du dégradé située en dessous.

```js
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')

const g = ctx.createLinearGradient(0, 0, canvas.width, canvas.height)
g.addColorStop(0, '#1e1b4b')
g.addColorStop(0.55, '#7c3aed')
g.addColorStop(1, '#f472b6')

ctx.fillStyle = g
ctx.fillRect(0, 0, canvas.width, canvas.height)
```

Le plus petit dégradé canvas fonctionnel : une diagonale du coin supérieur gauche au coin inférieur droit.

## Les trois méthodes de dégradé

| Méthode | Arguments | Équivalent CSS |
| --- | --- | --- |
| `createLinearGradient` | `x0, y0, x1, y1` | `linear-gradient()` |
| `createRadialGradient` | `x0, y0, r0, x1, y1, r1` | `radial-gradient()` |
| `createConicGradient` | `startAngle, x, y` | `conic-gradient()` |
| `addColorStop` | `offset` de 0 à 1, `colour` | Un arrêt de couleur avec un pourcentage |

Chaque méthode renvoie un CanvasGradient. Vous pouvez le garder dans une variable et le réutiliser pour autant de formes que vous voulez.

Le dégradé est fixé au canvas, pas à la forme. Si vous créez un dégradé de 0 à 400 puis remplissez un petit carré à x 300, le carré ne montre que l’extrémité rose. Cela surprend quand on vient du CSS, où un dégradé s’étire toujours sur l’élément. Créez le dégradé avec les coordonnées de la forme elle-même quand vous voulez qu’il s’y ajuste.

## createLinearGradient et les angles CSS

Le CSS vous laisse écrire `135deg`. Le canvas veut deux points. Cette fonction convertit un angle CSS en points de départ et d’arrivée identiques à ceux qu’utilise le CSS, pour qu’une création écrite en [dégradé linéaire CSS](https://gradiently.design/fr/guide/css-linear-gradient) s’affiche à l’identique sur canvas.

```js
// Match CSS linear-gradient(angle) on a w by h rectangle
function cssAngleGradient(ctx, angleDeg, x, y, w, h) {
  const a = (angleDeg * Math.PI) / 180
  const len = Math.abs(w * Math.sin(a)) + Math.abs(h * Math.cos(a))
  const cx = x + w / 2
  const cy = y + h / 2
  const dx = (Math.sin(a) * len) / 2
  const dy = (-Math.cos(a) * len) / 2
  return ctx.createLinearGradient(cx - dx, cy - dy, cx + dx, cy + dy)
}

const g = cssAngleGradient(ctx, 135, 0, 0, 1200, 630)
g.addColorStop(0, '#0f172a')
g.addColorStop(1, '#0d9488')
ctx.fillStyle = g
ctx.fillRect(0, 0, 1200, 630)
```

En CSS, 0deg pointe vers le haut et les angles tournent dans le sens horaire. La formule de longueur fait tomber les coins exactement sur la première et la dernière couleur, comme en CSS.

Le même dégradé en CSS: `linear-gradient(135deg, #0f172a 0%, #0d9488 100%)`

Ce que la fonction ci-dessus dessine sur un canvas de 1200×630, la taille d’une [image Open Graph](https://gradiently.design/fr/guide/open-graph-tags). Si vos angles semblent faux, [l’angle de dégradé](https://gradiently.design/fr/guide/gradient-angle) explique comment le CSS les mesure.

## createRadialGradient

Sur canvas, un dégradé radial est défini par deux cercles : un cercle de départ et un cercle d’arrivée. L’arrêt 0 se trouve sur le premier cercle et l’arrêt 1 sur le second. La plupart du temps, vous voulez que le premier cercle soit un point, donc son rayon vaut 0.

```js
const w = canvas.width
const h = canvas.height

// A soft light in the top right corner of a dark ground
ctx.fillStyle = '#0c0a1d'
ctx.fillRect(0, 0, w, h)

const glow = ctx.createRadialGradient(w * 0.75, h * 0.2, 0, w * 0.75, h * 0.2, w * 0.6)
glow.addColorStop(0, 'rgb(124 58 237 / 0.9)')
glow.addColorStop(0.5, 'rgb(46 16 101 / 0.5)')
glow.addColorStop(1, 'rgb(12 10 29 / 0)')

ctx.fillStyle = glow
ctx.fillRect(0, 0, w, h)
```

Faire disparaître le dernier arrêt dans la transparence permet d’empiler plusieurs lumières sur un même fond, et c’est ainsi que se construisent les fonds en couches.

Éloignez le centre du premier cercle de celui du second et la lumière s’incline, comme un projecteur qui frappe un mur en biais. Le CSS n’a pas d’équivalent direct de ce décalage. Côté CSS, voir [les dégradés radiaux CSS](https://gradiently.design/fr/guide/css-radial-gradient).

## createConicGradient

`createConicGradient(startAngle, x, y)` fait tourner la couleur autour d’un point central. Deux détails diffèrent du CSS : l’angle est en radians, et 0 pointe vers la droite (trois heures), pas vers le haut. Pour reproduire un `conic-gradient(from 0deg, ...)` CSS, commencez à `-Math.PI / 2`.

```js
const cx = canvas.width / 2
const cy = canvas.height / 2

const ring = ctx.createConicGradient(-Math.PI / 2, cx, cy)
ring.addColorStop(0, '#22d3ee')
ring.addColorStop(0.33, '#7c3aed')
ring.addColorStop(0.66, '#f472b6')
ring.addColorStop(1, '#22d3ee')

ctx.fillStyle = ring
ctx.beginPath()
ctx.arc(cx, cy, 160, 0, Math.PI * 2)
ctx.fill()
```

Répéter la première couleur à la position 1 masque la jointure. createConicGradient fonctionne dans les versions actuelles de Chrome, Edge, Safari et Firefox.

- createLinearGradient: `linear-gradient(135deg, #1e1b4b 0%, #7c3aed 55%, #f472b6 100%)`
- createRadialGradient: `radial-gradient(circle at 75% 20%, #7c3aed 0%, #2e1065 30%, #0c0a1d 60%)`
- createConicGradient: `conic-gradient(from 0deg, #22d3ee, #7c3aed, #f472b6, #22d3ee)`

Les trois exemples de cet article, montrés sous forme de leurs jumeaux CSS. [Les dégradés coniques CSS](https://gradiently.design/fr/guide/css-conic-gradient) approfondissent la version conique.

## Texte en dégradé, contours et animation

`fillStyle` et `strokeStyle` acceptent tous deux un dégradé, donc le texte et les contours fonctionnent de la même façon. Placez le dégradé sur la boîte du texte lui-même, mesurée avec `measureText()`, pour que toute la gamme de couleurs apparaisse dans les lettres.

```js
ctx.font = '700 96px Inter, system-ui, sans-serif'
const text = 'Open late'
const width = ctx.measureText(text).width

const tg = ctx.createLinearGradient(80, 0, 80 + width, 0)
tg.addColorStop(0, '#fde68a')
tg.addColorStop(1, '#fb7185')
ctx.fillStyle = tg
ctx.fillText(text, 80, 200)

// Animation: rebuild the gradient each frame, it is cheap
function frame(t) {
  const shift = (Math.sin(t / 2000) + 1) / 2
  const g = ctx.createLinearGradient(0, 0, canvas.width, 0)
  g.addColorStop(0, '#1e1b4b')
  g.addColorStop(0.2 + shift * 0.6, '#7c3aed')
  g.addColorStop(1, '#0f172a')
  ctx.fillStyle = g
  ctx.fillRect(0, 0, canvas.width, canvas.height)
  requestAnimationFrame(frame)
}
requestAnimationFrame(frame)
```

Impossible de déplacer ou de supprimer un arrêt une fois ajouté : animez donc en créant un nouveau dégradé à chaque image. Mettez la boucle en pause pour les utilisateurs qui préfèrent réduire les animations.

## Enregistrer le canvas en image

Une raison courante de dessiner des dégradés sur canvas est de générer une image : une carte de partage, un certificat, une couverture. Appelez `canvas.toBlob()` avec `image/png` pour les dégradés et le texte, car le PNG garde les fondus lisses intacts, et réservez le JPEG aux images surtout photographiques. [PNG ou JPG](https://gradiently.design/fr/guide/png-vs-jpeg) explique le compromis. Dessinez à la taille de sortie réelle, comme 1200×630 pour un aperçu de lien, plutôt que d’agrandir un petit canvas.

```js
canvas.toBlob((blob) => {
  const a = document.createElement('a')
  a.href = URL.createObjectURL(blob)
  a.download = 'card.png'
  a.click()
  setTimeout(() => URL.revokeObjectURL(a.href), 1000)
}, 'image/png')
```

Téléchargez le canvas fini en PNG. Sur un serveur, le même code de dessin tourne avec une bibliothèque canvas pour Node.

## Problèmes courants des dégradés canvas

### Symptôme

- Le dégradé paraît flou sur un téléphone
- Une seule couleur apparaît dans une forme
- Des bandes visibles dans un dégradé sombre
- `IndexSizeError` venant d’addColorStop
- Le dégradé conique commence au mauvais endroit

### Correctif

- Multipliez largeur et hauteur du canvas par `devicePixelRatio`, puis revenez avec `ctx.scale()`
- Créez le dégradé avec les coordonnées de la forme, pas celles du canvas
- Ajoutez un léger bruit par-dessus, voir [l’effet de bandes des dégradés](https://gradiently.design/fr/guide/gradient-banding)
- Gardez les positions entre 0 et 1
- Commencez à `-Math.PI / 2` pour coller au CSS

> **Des couleurs plus larges sur les écrans compatibles** Chrome et Safari acceptent `canvas.getContext('2d', { colorSpace: 'display-p3' })`, qui permet aux dégradés vifs d’utiliser la gamme P3 plus large. Les navigateurs qui ne le prennent pas en charge reviennent au sRGB.

Quand il vous faut des dégradés qui bougent avec un vrai éclairage plutôt que des fondus plats, le canvas atteint ses limites et WebGL prend le relais, comme l’expliquent [les dégradés shader](https://gradiently.design/fr/guide/shader-gradients). Et quand le canvas n’est qu’un moyen d’obtenir une image, comme une carte sociale ou une affiche, Gradiently rend un Mark à n’importe quelle taille de 200 à 8 000 px avec les mots mis en page pour vous, sans code de dessin à maintenir.

## FAQ

### Comment créer un dégradé sur un canvas HTML ?

Appelez `ctx.createLinearGradient(x0, y0, x1, y1)`, ajoutez des couleurs avec `addColorStop(offset, colour)`, affectez le dégradé à `ctx.fillStyle` et dessinez une forme, par exemple avec `fillRect`.

### Quelle différence entre createLinearGradient et linear-gradient en CSS ?

Le canvas utilise un point de départ et un point d’arrivée en pixels, alors que le CSS utilise un angle et étire le dégradé sur l’élément. Une petite fonction peut convertir un angle CSS en points canvas.

### Puis-je utiliser des couleurs oklch ou hsl dans addColorStop ?

Oui. addColorStop accepte toute chaîne de couleur CSS que le navigateur comprend, y compris hex, rgb(), hsl() et, dans les navigateurs actuels, oklch().

### Pourquoi mon dégradé canvas n’affiche-t-il qu’une couleur ?

Le dégradé est positionné en coordonnées du canvas, donc une forme dessinée hors de ses points de départ et d’arrivée ne reprend que la couleur d’extrémité la plus proche. Créez le dégradé avec la position et la taille de la forme.

### Comment animer un dégradé canvas ?

Créez un nouveau dégradé à chaque image de l’animation avec des arrêts ou des coordonnées mis à jour, puis redessinez. Les arrêts d’un dégradé ne peuvent être ni déplacés ni supprimés une fois ajoutés.
