Guide complet des ombres CSS : box-shadow, drop-shadow et text-shadow expliqués

Maîtrisez les trois techniques d'ombre CSS — syntaxe, paramètres, différences de rendu, patterns réels et implications de performance.

~15 min de lecture Feb 2025

Les ombres sont l'un des outils les plus simples en CSS, pourtant la plupart des tutoriels n'en grattent que la surface. Ce guide couvre les trois mécanismes en profondeur — leur syntaxe, paramètres, différences de rendu, cas d'usage réels et implications de performance — pour que vous choisissiez toujours la bonne technique.

Pourquoi CSS a-t-il trois propriétés d'ombre ?

Chaque mécanisme d'ombre existe pour résoudre un problème différent. Ils sont apparus à différentes époques de l'histoire CSS et ciblent des objectifs de rendu fondamentalement différents :

  • box-shadow — ombres pour les boîtes rectangulaires (le box model CSS). Disponible depuis CSS 2.1, standardisé en CSS3.
  • filter : drop-shadow() — ombres qui suivent la forme visible réelle d'un élément, y compris la transparence. Partie de la spécification CSS Filter Effects Level 1.
  • text-shadow — ombres appliquées directement aux contours de glyphes. Techniquement la plus ancienne des trois, introduite en CSS 2, brièvement supprimée, puis re-standardisée en CSS3.

La confusion vient du fait que les trois produisent ce que l'œil humain perçoit comme « une ombre », mais le moteur de rendu les traite à des étapes complètement différentes du pipeline de peinture.

⚡ Règle pratique

Utilisez box-shadow pour les éléments UI à fond solide. Utilisez drop-shadow pour les PNG, SVG ou tout élément avec transparence. Utilisez text-shadow exclusivement sur le texte.

box-shadow : le cheval de bataille

Dessine une ou plusieurs ombres derrière (ou à l'intérieur de) la border box d'un élément — la propriété d'ombre la plus polyvalente et la plus utilisée.

Syntaxe

box-shadow: [inset] offset-x offset-y [blur-radius] [spread-radius] color;

Chaque valeur fait exactement une chose :

Paramètre Défaut Ce qu'il contrôle
insetomis (extérieur)Dessine l'ombre à l'intérieur de l'élément plutôt que derrière
offset-xrequisDistance horizontale. Positif = droite, négatif = gauche
offset-yrequisDistance verticale. Positif = bas, négatif = haut
blur-radius0Quantité de flou gaussien. Plus élevé = plus doux et étalé
spread-radius0Étend (+) ou contracte (–) l'ombre avant le flou
colorcurrentColorCouleur de l'ombre — toujours utiliser rgba() ou hsla() pour le réalisme

Le spread radius : le paramètre sous-utilisé

La plupart des développeurs utilisent offset + blur et s'arrêtent là. Le spread radius débloque une classe d'effets entièrement différente. Avec spread : 0 et blur : 0, il devient une bordure CSS parfaite et empilable sans impact sur le layout :

/* Layered outline rings — no layout impact */
box-shadow:
  0 0 0 4px rgba(201,184,154,.4),
  0 0 0 8px rgba(201,184,154,.1);

Avec un spread négatif, on peut transformer une ombre floue en une ombre directionnelle qui n'apparaît que sous un élément :

/* Shadow only at the bottom — more realistic */
box-shadow: 0 12px 24px -8px rgba(0,0,0,.6);

Exemples en direct

4px 4px 8px rgba(0,0,0,.7)
0 0 0 4px accent
inset 0 4px 12px
0 2px 4px + 0 8px 24px + ring
0 0 24px + 0 0 48px
light + dark inset pair
backdrop-blur + shadow

Ombres multiples : l'ordre compte

On peut empiler un nombre illimité d'ombres avec une liste séparée par des virgules. Le rendu se fait de l'avant vers l'arrière — la première ombre de la liste est au-dessus. Cela permet de superposer des ombres ambiantes et directionnelles pour une profondeur naturelle en thème clair et sombre.

/* Three-layer system used in serious design systems */
box-shadow:
  0 1px 2px rgba(0,0,0,.3),    /* close shadow: sharp, small */
  0 4px 16px rgba(0,0,0,.25),  /* mid shadow: soft ambient */
  0 0 0 1px rgba(255,255,255,.05); /* subtle highlight ring */

Ombres inset : profondeur et états enfoncés

Le mot-clé inset déplace l'ombre à l'intérieur du bord de l'élément. La direction de l'offset s'inverse intuitivement : un offset Y positif place l'ombre le long du bord intérieur supérieur, comme si la lumière venait d'en haut. Indispensable pour les boutons enfoncés, les inputs en relief et le neumorphisme :

/* Input focus state — depth without a visible border */
input:focus {
  box-shadow:
    inset 0 2px 6px rgba(0,0,0,.5),
    0 0 0 2px rgba(201,184,154,.4);
}
Outil gratuit Générateur Box Shadow Ajustez les paramètres et copiez le CSS prêt à l'emploi

filter : drop-shadow() — ombres qui suivent la forme

filter : drop-shadow() n'est pas une propriété — c'est une fonction de filtre CSS. Les filtres sont appliqués après la peinture, opérant sur les pixels finalement rendus d'un élément et de ses descendants. Cette distinction a deux conséquences majeures :

  • L'ombre suit le contour visible réel, respectant la transparence alpha dans les PNG et la forme des tracés SVG.
  • Le filtre affecte tout le sous-arbre, y compris les enfants. Cela signifie qu'il fonctionne automatiquement sur des groupes d'éléments.

Syntaxe

filter: drop-shadow(offset-x offset-y blur-radius color);

Remarque : pas de spread-radius et pas de mot-clé inset. La spécification les a délibérément omis. Pour un spread sur une ombre suivant la forme, empiler deux appels drop-shadow() avec des rayons de flou différents.

Là où box-shadow échoue et drop-shadow brille

Imaginez un logo PNG transparent sur un fond de page coloré. Appliquez box-shadow et vous obtenez une ombre rectangulaire autour du bounding box invisible — l'ombre déborde dans les zones transparentes. Appliquez drop-shadow() et l'ombre épouse la forme visible réelle du logo.

La même logique s'applique à :

  • Éléments SVG — tracés, polygones, formes composites
  • CSS clip-path — l'ombre suit la limite du clip
  • Éléments pivotés ou transformés — l'ombre suit correctement la forme post-transformation
  • Groupes de composants — un filtre sur le parent ombre tous les enfants comme une unité
/* SVG icon with proper shadow */
.icon-wrapper {
  filter: drop-shadow(0 4px 8px rgba(0,0,0,.6));
}

/* PNG logo — shadow follows logo shape, not its bounding box */
.logo {
  filter: drop-shadow(2px 4px 12px rgba(0,0,0,.5));
}

/* Stacked for a glow effect on an irregular shape */
.neon-svg {
  filter:
    drop-shadow(0 0 6px rgba(201,184,154,.8))
    drop-shadow(0 0 20px rgba(201,184,154,.4));
}

Le compromis clé : le contexte d'empilement

Appliquer filter crée un nouveau contexte d'empilement et une nouvelle couche de composition. C'est généralement acceptable, mais cela signifie que l'élément ne peut plus se superposer correctement aux autres couches de composition — ce qui provoque parfois des problèmes de z-index. Si c'est le cas, vérifier si box-shadow peut approximer l'effet.

Outil gratuit Générateur de Filtres CSS Combinez drop-shadow avec blur, luminosité et saturation — aperçu

text-shadow : profondeur typographique

text-shadow s'applique exclusivement aux contours de glyphes du texte — pas à la boîte de l'élément. Il est peint à la même étape que le texte, derrière les glyphes, en faisant le bon choix lorsqu'on veut de la profondeur ou de la lisibilité sur des éléments typographiques.

Syntaxe

text-shadow: offset-x offset-y [blur-radius] color;

Par rapport à box-shadow, il n'y a pas de spread-radius ni d'inset. Les ombres multiples sont séparées par des virgules, avec le même ordre avant-arrière.

Exemples en direct

Heading
2px 2px 4px rgba(0,0,0,.8)
Neon
0 0 10px + 0 0 30px
Emboss
light + dark offset pair
Retro
hard double offset

Cas d'usage courants

Lisibilité sur images : Un subtil text-shadow : 0 1px 3px rgba(0,0,0,.6) rend le texte blanc lisible sur des photos lumineuses sans avoir besoin d'un overlay sombre.

Typographie néon/glow : Empiler deux ombres à offset zéro avec des rayons de flou croissants. L'ombre intérieure crée le noyau intense, l'extérieure crée le halo atmosphérique :

.neon {
  color: #c9b89a;
  text-shadow:
    0 0 8px rgba(201,184,154,.9),
    0 0 24px rgba(201,184,154,.5),
    0 0 60px rgba(201,184,154,.2);
}

Letterpress / relief : Combiner une ombre claire en haut-gauche avec une sombre en bas-droite. La direction détermine si le texte apparaît en relief ou en creux :

/* Raised (light = up-left, dark = down-right) */
text-shadow: -1px -1px 0 rgba(255,255,255,.15), 1px 1px 0 rgba(0,0,0,.6);

/* Recessed (reversed) */
text-shadow:  1px  1px 0 rgba(255,255,255,.1), -1px -1px 0 rgba(0,0,0,.5);

Ombre portée dure (style rétro/BD) : Zéro blur, offset plus grand, ombres dures empilées :

.retro {
  text-shadow: 3px 3px 0 #7a5c38, 6px 6px 0 rgba(0,0,0,.25);
}
Outil gratuit Générateur Text Shadow Créez et exportez des effets text-shadow avec aperçu en direct

Comparaison côte à côte

Fonctionnalitébox-shadowdrop-shadow()text-shadow
CibleBox model de l'élémentForme de pixels rendusContours de glyphes
Respecte la transparenceNon — ignore alphaOui — suit la formeN/A (texte seulement)
spread-radiusOuiNonNon
Mot-clé insetOuiNonNon
Couches multiplesOui, séparées par virguleOui, fonctions chaînéesOui, séparées par virgule
Contexte d'empilementAucun nouveau contexteCrée un nouveau contexteAucun nouveau contexte
S'applique aux enfantsNonOui (tout le sous-arbre)Non
Fonctionne sur SVGBounding box seulementOui, par tracéN/A
Animation CSSAnimableAnimableAnimable
Compositing GPUSouvent, sur couches promuesOui, toujoursRarement

La question qui détermine laquelle utiliser

Demandez-vous : l'élément a-t-il un fond rectangulaire et opaque ? Si oui, utilisez box-shadow — plus simple à raisonner et sans effets secondaires sur le contexte d'empilement. Sinon (PNG transparent, SVG, forme irrégulière, clip-path), utilisez drop-shadow(). Si votre cible est du texte, utilisez text-shadow.

Recettes et patterns pour la production

Système d'élévation (style Material)

Plutôt que de hardcoder les valeurs d'ombre partout dans le codebase, définir une échelle d'élévation comme propriétés CSS personnalisées. Cela rend la profondeur globale cohérente et facile à mettre à jour :

:root {
  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 2px 6px rgba(0,0,0,.35), 0 1px 2px rgba(0,0,0,.3);
  --shadow-3: 0 4px 16px rgba(0,0,0,.3), 0 2px 4px rgba(0,0,0,.3);
  --shadow-4: 0 8px 32px rgba(0,0,0,.28), 0 4px 8px rgba(0,0,0,.25);
  --shadow-5: 0 16px 48px rgba(0,0,0,.25), 0 8px 16px rgba(0,0,0,.2);
}

.card      { box-shadow: var(--shadow-2); }
.card:hover { box-shadow: var(--shadow-4); transition: box-shadow .2s ease; }
.modal     { box-shadow: var(--shadow-5); }

Ombres colorées

L'une des techniques les plus sous-utilisées : au lieu d'ombres noires, teinter l'ombre avec la couleur dominante de l'élément. Cela s'intègre mieux dans les thèmes clair et sombre et crée une qualité proche du glow sans paraître agressive :

/* Button with colored shadow matching brand color */
.btn-primary {
  background: #c9b89a;
  box-shadow: 0 4px 20px rgba(201,184,154,.4), 0 2px 6px rgba(201,184,154,.3);
}
.btn-primary:hover {
  box-shadow: 0 6px 28px rgba(201,184,154,.55), 0 3px 8px rgba(201,184,154,.4);
}

Glassmorphisme avec ombre

Le glassmorphisme nécessite une interaction soigneusement calibrée entre backdrop-filter, fond translucide, bordure semi-transparente et box-shadow pour séparer la carte du fond :

.glass-card {
  background: rgba(255, 255, 255, 0.06);
  backdrop-filter: blur(16px) saturate(1.2);
  -webkit-backdrop-filter: blur(16px) saturate(1.2);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 16px;
  box-shadow:
    0 8px 32px rgba(0,0,0,.4),    /* ambient depth */
    inset 0 1px 0 rgba(255,255,255,.08); /* top highlight */
}
🔧

PixCode Glassmorphism Generator exporte le CSS complet incluant les préfixes vendor.

Anneaux de focus avec box-shadow

Remplacer le outline par défaut du navigateur par box-shadow donne un contrôle total sur le style tout en maintenant l'accessibilité. L'astuce est d'utiliser une ombre uniquement de spread avec blur à 0 :

:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 2px var(--bg),         /* gap between element and ring */
    0 0 0 4px rgba(201,184,154,.7); /* visible ring */
}

Neumorphisme

Le neumorphisme utilise des paires d'ombres inset et outer dérivées de la couleur de fond. L'élément, l'ombre et le fond doivent utiliser des tons étroitement liés — le contraste extrême brise l'illusion :

/* Element bg = slightly lighter than page bg */
.neumorphic {
  background: #1c1c1c;
  border-radius: 16px;
  box-shadow:
     8px  8px 16px #0a0a0a,   /* dark shadow: down-right */
    -8px -8px 16px #2e2e2e;   /* light shadow: up-left */
}
.neumorphic.pressed {
  box-shadow:
    inset  4px  4px 10px #0a0a0a,
    inset -4px -4px 10px #2e2e2e;
}

Considérations de performance

Les ombres sont l'une des opérations de rendu qui inquiètent le plus les développeurs, souvent sans raison. Voici ce qui se passe réellement :

✓ Chemins rapides

box-shadow sur des couches de composition GPU (position:fixed, will-change:transform). filter: drop-shadow() est toujours accéléré GPU. Animer box-shadow via des transitions CSS sur des éléments promus.

✗ Chemins lents

Animer box-shadow sur des éléments non promus déclenche layout + paint à chaque frame. Des rayons de flou importants sur filter: drop-shadow() sont coûteux. text-shadow avec un très grand flou sur de nombreux éléments.

Lors de l'animation d'ombres

Le pattern le plus sûr pour les ombres animées (élévations au survol, états de chargement) est de promouvoir d'abord l'élément, puis de faire la transition de l'ombre :

.card {
  will-change: transform;         /* promote to compositing layer */
  transform: translateZ(0);       /* trigger layer in older browsers */
  transition: box-shadow .2s ease, transform .2s ease;
  box-shadow: var(--shadow-2);
}
.card:hover {
  transform: translateY(-2px);    /* move on GPU — free */
  box-shadow: var(--shadow-4);    /* re-composite — also fast */
}
⚠️ Attention

Ne pas appliquer will-change à l'aveugle — chaque couche promue consomme de la mémoire GPU. L'utiliser uniquement sur les éléments qui s'animeront réellement, et le supprimer une fois l'animation terminée si ajouté via JavaScript.

Performance : blur-radius vs spread-radius

Augmenter blur-radius est plus coûteux qu'augmenter spread-radius, car le blur nécessite une convolution gaussienne qui s'adapte à la surface en pixels. Une ombre avec spread : 10px, blur : 2px est moins coûteuse que spread : 0, blur : 12px pour la même empreinte visuelle.

Générateurs d'ombres interactifs sur PixCode.io

Les trois techniques d'ombre ont des générateurs interactifs dédiés sur PixCode — ajustez les paramètres avec des sliders, voyez le résultat en direct et copiez le CSS prêt pour la production en un clic.

Preguntas frecuentes

Que es CSS box-shadow? +
CSS box-shadow anade una sombra rectangular detras de un elemento con la sintaxis: offset-x offset-y blur-radius spread-radius color. Puedes apilar multiples sombras con comas y usar la palabra clave inset para renderizar la sombra dentro del elemento.
Como se diferencia filter drop-shadow de box-shadow? +
box-shadow sigue el marco rectangular ignorando los pixeles transparentes. filter drop-shadow traza la forma visible real — esencial para PNGs con transparencia, SVGs y formas irregulares.
Se pueden animar sombras CSS sin afectar el rendimiento? +
Si, pero con cuidado. Animar box-shadow dispara layout y paint en elementos no compositados. El patron mas seguro es animar la opacidad entre dos pseudo-elementos con las sombras.
Que es el parametro spread-radius en box-shadow? +
El spread-radius es el cuarto valor de box-shadow. Un valor positivo expande la sombra mas alla del area de desenfoque; uno negativo la encoge. Un spread de 0 significa que la sombra es exactamente tan grande como el elemento antes del desenfoque.
Cuando usar text-shadow en lugar de drop-shadow? +
Usa text-shadow para efectos tipograficos — legibilidad, efectos de brillo, texto en relieve y estilos retro. Usa filter drop-shadow en elementos que necesitan seguir un borde no rectangular.
Como crear una tarjeta neomorfica con box-shadow? +
El neumorfismo requiere dos sombras: una mas clara que el fondo (arriba-izquierda) y una mas oscura (abajo-derecha). Ejemplo: box-shadow: 8px 8px 16px #0a0a0a, -8px -8px 16px #2e2e2e en una tarjeta #1c1c1c sobre fondo #0e0e0e.
Que navegadores soportan box-shadow y CSS filter? +
box-shadow esta soportado en todos los navegadores desde 2011 (IE 9). filter drop-shadow esta soportado en todos los navegadores modernos desde 2013. Internet Explorer no soporta filter.