W3docs

Ombres portées SVG

Apprenez les ombres portées, les éléments <defs> et <filter> en SVG. Exemples des éléments <feOffset>, <feGaussianBlur>, <feColorMatrix>.

Une ombre portée donne l'impression qu'une forme SVG flotte au-dessus de la page en peignant une copie floue et décalée de la forme derrière elle. En SVG, cet effet se construit à partir de primitives de filtre de bas niveau — de petits blocs de construction comme le flou et le décalage, que l'on enchaîne à l'intérieur d'un élément <filter>.

Quand utiliser les filtres SVG plutôt que CSS

Il existe trois façons d'ajouter une ombre, et elles ne sont pas interchangeables :

  • box-shadow (CSS) — agit sur la boîte rectangulaire d'un élément HTML/CSS. Elle ne suit pas la forme des tracés SVG, donc un triangle aura toujours une ombre rectangulaire. Idéale pour les boîtes, cartes et boutons.
  • filter: drop-shadow() (CSS) — suit la forme réellement peinte (y compris les tracés SVG et les PNG transparents). C'est le moyen le plus rapide d'ajouter une ombre portée à un SVG depuis une feuille de style, et elle est largement prise en charge. À utiliser quand vous avez simplement besoin d'une ombre sans contrôle fin.
  • SVG <filter> (ce chapitre) — l'option la plus puissante. Vous contrôlez chaque étape (distance de décalage, rayon de flou, couleur de l'ombre, mode de fusion) et pouvez combiner plusieurs primitives. À utiliser pour une ombre colorée, une ombre intérieure ou tout effet allant au-delà d'un simple flou.

Ce chapitre couvre l'approche SVG <filter>. Pour d'autres effets de filtre, consultez Effets de flou SVG et l'Introduction aux filtres SVG.

Description des filtres SVG

Tous les filtres SVG sont définis à l'intérieur d'un élément <defs>. L'élément <defs> est une abréviation de definitions (définitions). Il contient la définition d'éléments spécifiques comme les filtres. L'élément <filter> définit un filtre SVG. Cet élément possède un attribut id (obligatoire) qui identifie le filtre, que vous référencez ensuite depuis une forme avec filter="url(#id)".

Primitives de filtre et entrées

Chaque primitive lit une image en entrée et produit une image en sortie. Deux entrées spéciales sont intégrées :

  • SourceGraphic — la forme originale avec toutes ses couleurs.
  • SourceAlpha — la même forme, mais en utilisant uniquement son canal alpha (opacité), ce qui donne un silhouette noir uni. C'est le point de départ habituel pour une ombre, car une ombre doit être une copie sombre de la forme et non une copie recolorée.

On connecte les primitives entre elles grâce à deux attributs :

  • in — l'image que cette primitive lit en entrée (ex. SourceAlpha, ou un nom de result provenant d'une primitive antérieure).
  • result — un nom que vous donnez à la sortie de cette primitive pour qu'une primitive ultérieure puisse la lire.

Les primitives utilisées dans ce chapitre :

  • <feOffset> — décale une image de dx (horizontal) et dy (vertical). Cela positionne l'ombre en dehors de la forme.
  • <feGaussianBlur> — floute une image. Son attribut stdDeviation définit le rayon de flou : des valeurs plus élevées donnent une ombre plus douce et plus large.
  • <feColorMatrix> — transforme les valeurs RGBA de chaque pixel, ce qui permet de teinter une ombre d'une couleur personnalisée.
  • <feBlend> / <feMerge> — combinent deux images. <feBlend> superpose deux entrées (in et in2) selon un mode tel que normal ; <feMerge> superpose un nombre quelconque d'entrées dans l'ordre. Tous deux sont utilisés ici pour peindre le graphique original par-dessus l'ombre terminée.

Pour créer des ombres portées, utilisez l'élément <feOffset>. Vous prenez une copie du graphique SVG, vous la déplacez dans le plan xy, puis vous la floutez, puis vous dessinez l'original par-dessus.

Exemple de l'élément SVG <feOffset> :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <svg width="150" height="150">
      <defs>
        <filter id="filter" x="0" y="0" width="150%" height="150%">
          <feOffset result="offOut" in="SourceGraphic" dx="30" dy="30" />
          <feBlend in="SourceGraphic" in2="offOut" mode="normal" />
        </filter>
      </defs>
      <rect width="110" height="110" stroke="purple" stroke-width="5" fill="pink" 
            filter="url(#filter)" /> 
      Sorry, your browser doesn't support inline SVG.
    </svg>
  </body>
</html>

Dans l'exemple ci-dessus, l'attribut id de l'élément <filter> spécifie un nom unique pour le filtre, et l'attribut filter de l'élément <rect> relie le rectangle à ce filtre. <feOffset> copie SourceGraphic et le déplace de 30 px vers la droite et 30 px vers le bas (dx="30" dy="30"), en sauvegardant le résultat sous le nom offOut. <feBlend> dessine ensuite le SourceGraphic original par-dessus offOut, ce qui donne la forme avec une copie décalée à contours nets derrière elle.

Exemple de l'élément SVG <feGaussianBlur> :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <svg width="200" height="200">
      <defs>
        <filter id="filter" x="0" y="0" width="250%" height="250%">
          <feOffset result="offOut" in="SourceGraphic" dx="30" dy="30" />
          <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
          <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
        </filter>
      </defs>
      <rect width="150" height="150" stroke="coral" stroke-width="5" fill="pink" 
            filter="url(#filter)" /> 
      Sorry, your browser doesn't support inline SVG.
    </svg>
  </body>
</html>

Ici, la copie décalée est floutée avec l'élément <feGaussianBlur>. Son attribut stdDeviation spécifie l'intensité du flou — augmentez-le pour une ombre plus douce, diminuez-le pour une ombre plus nette. Comme l'entrée est encore SourceGraphic, la copie floutée conserve les couleurs de la forme, ce qui ne ressemble généralement pas à une vraie ombre. L'exemple suivant corrige cela.

Exemple d'une ombre noire (silhouette) avec SourceAlpha :

Pour rendre l'ombre en silhouette sombre plutôt qu'en clone flouté de la forme colorée, alimentez <feOffset> avec l'entrée SourceAlpha plutôt que SourceGraphic. SourceAlpha ne porte que l'opacité, donc la copie décalée et floutée ressort en noir uni — exactement ce que doit être une ombre.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <svg height="200" width="200">
      <defs>
        <filter id="filter" x="0" y="0" width="150%" height="150%">
          <feOffset result="offOut" in="SourceAlpha" dx="15" dy="15" />
          <feGaussianBlur result="blurOut" in="offOut" stdDeviation="8" />
          <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
        </filter>
      </defs>
      <rect width="120" height="120" stroke="purple" stroke-width="5" fill="pink" 
            filter="url(#filter)" /> 
       Sorry, your browser doesn't support inline SVG.
    </svg>
  </body>
</html>

Pour teinter l'ombre d'une couleur personnalisée, utilisez l'élément <feColorMatrix>. Il multiplie les valeurs rouge, vert, bleu et alpha de chaque pixel par les nombres que vous fournissez, ce qui vous permet d'assombrir ou de recolorer la copie décalée avant de la flouter.

Exemple de coloration de l'ombre avec <feColorMatrix> :

Dans la matrice ci-dessous, les canaux rouge, vert et bleu sont chacun mis à l'échelle à 0.2 (les trois premières valeurs diagonales), ce qui assombrit la copie décalée vers une couleur sombre, tandis que le canal alpha reste à 1 (la quatrième valeur diagonale) pour que l'ombre conserve l'opacité de la forme. Modifiez les trois valeurs 0.2 pour teinter l'ombre — par exemple, une valeur rouge plus élevée donne une ombre rougeâtre.

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <svg height="200" width="200">
      <defs>
        <filter id="filter" x="0" y="0" width="150%" height="150%">
          <feOffset result="offOut" in="SourceGraphic" dx="25" dy="25" />
          <feColorMatrix result="matrixOut" in="offOut" type="matrix" 
                         values="0.2 0 0 0 0 0 0.2 0 0 0 0 0 0.2 0 0 0 0 0 1 0" />
          <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="9" />
          <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
        </filter>
      </defs>
      <rect width="150" height="150" stroke="purple" stroke-width="5" fill="lightblue" 
            filter="url(#filter)" /> 
       Sorry, your browser doesn't support inline SVG.
    </svg>
  </body>
</html>

Le raccourci <feDropShadow>

Enchaîner <feOffset>, <feGaussianBlur> et <feBlend> est verbeux pour un effet aussi courant. La primitive <feDropShadow> regroupe les trois en un seul élément et est prise en charge par tous les navigateurs modernes. Vous définissez le décalage avec dx / dy, la douceur avec stdDeviation, et la couleur avec flood-color (et optionnellement flood-opacity).

Exemple de l'élément SVG <feDropShadow> :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <svg height="200" width="200">
      <defs>
        <filter id="shadow" x="-20%" y="-20%" width="150%" height="150%">
          <feDropShadow dx="15" dy="15" stdDeviation="8" flood-color="purple" flood-opacity="0.5" />
        </filter>
      </defs>
      <rect width="120" height="120" stroke="purple" stroke-width="5" fill="pink" 
            filter="url(#shadow)" /> 
      Sorry, your browser doesn't support inline SVG.
    </svg>
  </body>
</html>

Cela produit le même type de résultat que les exemples multi-primitives ci-dessus en une seule ligne.

Chapitres SVG associés

Exercice

Pratique
Quelle entrée de filtre SVG doit-on transmettre à 'feOffset' pour obtenir une ombre en silhouette noire plutôt qu'une copie recolorée de la forme ?
Quelle entrée de filtre SVG doit-on transmettre à 'feOffset' pour obtenir une ombre en silhouette noire plutôt qu'une copie recolorée de la forme ?
Was this page helpful?