Niveau 13

Les Images

Maîtriser le stylisme des images en CSS : responsive design, effets visuels, clip-path, filtres, et bien plus.

1. Le concept fondamental

En une phrase : Les images en CSS se contrôlent à travers les propriétés d'affichage, d'ajustement, de masquage et de filtrage pour créer des compositions visuelles riches.

Les images sont un pilier du web moderne. En CSS, on ne se contente pas de les afficher : on les transforme, on les masque, on les filtre, et on crée des effets interactifs au survol. Ce chapitre couvre tout l'arsenal dont vous disposez.

Deux façons d'intégrer des images

Ce que le CSS peut faire avec les images

Capacité Propriétés CSS Usage
Dimensionnement max-width, width, aspect-ratio Images responsives, proportions fixes
Ajustement object-fit, object-position Recadrage intelligent dans un conteneur
Filtrage filter Flou, luminosité, grayscale, etc.
Masquage clip-path, mask-image Formes non-rectangulaires
Mélange mix-blend-mode Fusion artistique avec l'arrière-plan
Résolution image-set(), srcset Images adaptatives selon la densité d'écran

2. Syntaxe et propriétés

Les bases : inline vs block

Par défaut, <img> est un élément inline (il se comporte comme du texte dans une ligne). Pour le contrôler facilement, on le passe souvent en block.

/* Par défaut, img est inline */
img {
  display: inline;       /* comportement par défaut */
}

/* Souvent plus utile : mode bloc */
img {
  display: block;        /* prend toute la largeur disponible */
  max-width: 100%;       /* ne dépasse jamais son conteneur */
  height: auto;          /* conserve le ratio d'aspect */
}

Images responsives

img {
  max-width: 100%;       /* Jamais plus large que le conteneur */
  height: auto;          /* Ratio préservé */
}

/* Alternative moderne avec aspect-ratio */
img.portrait {
  width: 100%;
  aspect-ratio: 3 / 4;   /* Format portrait */
  object-fit: cover;      /* Recadre pour remplir */
}

object-fit

object-fit contrôle comment le contenu d'une image remplit son conteneur — c'est l'équivalent de background-size pour les <img>.

img {
  width: 300px;
  height: 200px;
  object-fit: cover;        /* Remplit en conservant le ratio, coupe le surplus */
  object-position: center;  /* Centre le point focal */
}
Valeur Comportement
fill Remplit le conteneur (défaut) — peut déformer l'image
contain Affiche l'image entière dans le conteneur — peut laisser des espaces
cover Remplit le conteneur en conservant le ratio — coupe le surplus
none Aucun ajustement — taille originale
scale-down Comme none ou contain, whichever est le plus petit

object-position

/* Point focal personnalisé */
img {
  object-fit: cover;
  object-position: 30% 70%;  /* 30% depuis la gauche, 70% depuis le haut */
}

/* Valeurs keyword */
img {
  object-position: center top;
  object-position: left center;
}

aspect-ratio

img {
  width: 100%;
  aspect-ratio: 16 / 9;    /* Format paysage */
}

img.carré {
  aspect-ratio: 1 / 1;     /* Carré parfait */
}

img.portrait {
  aspect-ratio: 3 / 4;     /* Portrait */
}

img.banniere {
  aspect-ratio: 21 / 9;    /* Ultra-large */
}

image-set() pour la résolution

/* Fournir différentes résolutions selon l'écran */
.hero {
  background-image: image-set(
    url("hero-1x.jpg") 1x,
    url("hero-2x.jpg") 2x,
    url("hero-3x.jpg") 3x
  );
}

/* Format et media query */
.hero {
  background-image: image-set(
    url("hero.webp") type("image/webp"),
    url("hero.jpg") type("image/jpeg")
  );
}
Astuce : image-set() fonctionne pour les background-image. Pour les balises <img>, utilisez l'attribut HTML srcset avec <picture>.

picture + srcset

<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.avif" type="image/avif">
  <img src="image.jpg" alt="Description">
</picture>

<!-- Switch selon la taille de l'écran -->
<picture>
  <source media="(min-width: 800px)" srcset="large.jpg">
  <source media="(min-width: 400px)" srcset="medium.jpg">
  <img src="small.jpg" alt="Responsive">
</picture>

La propriété filter

filter applique des effets visuels directement au navigateur. C'est l'un des outils les plus puissants du CSS moderne.

img {
  filter: none;  /* valeur par défaut */
}

/* Fonctions disponibles : */
img.blur       { filter: blur(4px); }
img.bright     { filter: brightness(1.5); }
img.contrast   { filter: contrast(2); }
img.gray       { filter: grayscale(100%); }
img.sepia      { filter: sepia(100%); }
img.hue        { filter: hue-rotate(90deg); }
img.saturate   { filter: saturate(2); }
img.invert     { filter: invert(100%); }
img.opacity    { filter: opacity(0.5); }
img.shadow     { filter: drop-shadow(4px 4px 8px rgba(0,0,0,0.3)); }

/* Combinaison de filtres */
img.combined {
  filter: grayscale(50%) contrast(1.2) brightness(1.1) saturate(1.3);
}
Fonction Valeurs Description
blur() px (rayon) Flou gaussien
brightness() 0% — 200%+ Luminosité (100% = normal)
contrast() 0% — 200%+ Contraste (100% = normal)
grayscale() 0% — 100% Niveaux de gris
sepia() 0% — 100% Effet sépia vintage
hue-rotate() deg (0° — 360°) Rotation des teintes
saturate() 0% — 200%+ Saturation des couleurs
invert() 0% — 100% Inversion des couleurs (négatif)
opacity() 0% — 100% Opacité (fonctionne différemment de opacity car dans le filter)
drop-shadow() offset-x offset-y blur radius color Ombre portée qui suit la forme de l'image
Erreur fréquente : filter: drop-shadow() suit la forme alpha de l'image (utile pour les PNGs transparents), tandis que box-shadow suit toujours le rectangle. Pour des ombres sur des images non-rectangulaires, utilisez drop-shadow.

mix-blend-mode

img {
  mix-blend-mode: multiply;     /* Multiplier — assombrit */
  mix-blend-mode: screen;       /* Écran — éclaircit */
  mix-blend-mode: overlay;      /* Superposition — contraste */
  mix-blend-mode: darken;       /* Assombrir — garde le plus sombre */
  mix-blend-mode: lighten;      /* Éclaircir — garde le plus clair */
  mix-blend-mode: color-dodge;  /* Éclaircir par couleur */
  mix-blend-mode: difference;   /* Différence — effet artistique */
}

clip-path

clip-path découpe un élément selon une forme géométrique.

/* Cercle */
img {
  clip-path: circle(50%);          /* Rayon = 50% de la largeur */
}

/* Ellipse */
img {
  clip-path: ellipse(40% 50%);     /* rx ry */
}

/* Losange (polygon) */
img {
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}

/* Rectangle avec coins arrondis (inset) */
img {
  clip-path: inset(10% round 16px);
}

/* Étoile */
img {
  clip-path: polygon(
    50% 0%, 61% 35%, 98% 35%,
    68% 57%, 79% 91%, 50% 70%,
    21% 91%, 32% 57%, 2% 35%, 39% 35%
  );
}

mask-image

/* Dégradé linéaire — fondu vers le bas */
img {
  mask-image: linear-gradient(to bottom, black 50%, transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, black 50%, transparent 100%);
}

/* Dégradé radial — cercle central */
img {
  mask-image: radial-gradient(circle, black 40%, transparent 70%);
  -webkit-mask-image: radial-gradient(circle, black 40%, transparent 70%);
}

/* Avec une image comme masque */
img {
  mask-image: url("masque.png");
  mask-size: cover;
  mask-repeat: no-repeat;
}
Astuce : Toujours inclure le préfixe -webkit-mask-image pour une meilleure compatibilité, notamment sur Safari.

3. Visualisation

object-fit en images

Image originale
800 × 600
original
fill
contain
cover
scale-down

Comparaison visuelle des valeurs de object-fit

clip-path en images

circle(50%)
ellipse(40% 50%)
polygon(losange)
inset(10% round 16px)

Formes de clip-path : cercle, ellipse, polygon, inset

Filters en images

none
blur(4px)
brightness(1.4)
contrast(1.8)
grayscale(100%)
sepia(100%)
hue-rotate(90deg)
saturate(2)
invert(100%)
opacity(0.4)
drop-shadow()
combined

Démonstration de toutes les fonctions filter avec un dégradé de test

4. Exemples progressifs

Exemple 1 — Image responsive de base

img {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: 8px;
  margin: 0 auto;
}

Rendu :

Image responsive — max-width: 100% + height: auto

Exemple 2 — object-fit : cover vs contain

/* cover : remplit le conteneur, coupe le surplus */
.img-cover {
  width: 100%;
  height: 300px;
  object-fit: cover;
  object-position: center;
}

/* contain : affiche l'image entière, espaces restants */
.img-contain {
  width: 100%;
  height: 300px;
  object-fit: contain;
  background-color: #f1f5f9;
}

Rendu :

object-fit: cover

object-fit: contain

Exemple 3 — Effet grayscale → couleur au survol

.img-grayscale-hover img {
  filter: grayscale(100%);
  transition: filter 0.5s ease;
}

.img-grayscale-hover:hover img {
  filter: grayscale(0%);
}

Rendu :

Survolez-moi → passe en couleur

Exemple 4 — Zoom au survol

.hover-zoom {
  overflow: hidden;
  border-radius: 8px;
}

.hover-zoom img {
  width: 100%;
  height: 250px;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.hover-zoom:hover img {
  transform: scale(1.1);
}

Rendu :

Survolez-moi → zoom 1.1x

Exemple 5 — Overlay textuel au survol

.hover-overlay {
  position: relative;
  overflow: hidden;
  border-radius: 8px;
}

.hover-overlay .overlay-text {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.hover-overlay:hover .overlay-text {
  opacity: 1;
}

Rendu :

Voir le projet

Exemple 6 — Révélation progressive

Rendu :

Survolez pour révéler un dégradé et un zoom subtil

Exemple 7 — Images avatar (cercle, anneau, groupe)

/* Cercle simple */
.avatar-circle {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  object-fit: cover;
}

/* Avec anneau coloré */
.avatar-ring {
  border-radius: 50%;
  border: 4px solid #2563eb;
  padding: 2px;
  background-color: white;
}

/* Groupe d'avatars (overlapping) */
.avatar-group .avatar-circle {
  margin-left: -12px;
  border: 3px solid white;
}
.avatar-group .avatar-circle:first-child {
  margin-left: 0;
}

Rendu :

AM

Cercle

BD

Anneau

CL
DM
EF
+5

Groupe

Exemple 8 — Figure + figcaption

<figure>
  <img src="photo.jpg" alt="Description de l'image">
  <figcaption>Légende sous l'image</figcaption>
</figure>

figure {
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}

figcaption {
  padding: 1rem;
  font-size: 0.9rem;
  color: #64748b;
  font-style: italic;
  border-top: 1px solid #e2e8f0;
}

Rendu :

<img> — Photo de paysage
Vue panoramique des Alpes françaises au coucher du soleil. Photo prise en juillet 2026.

Exemple 9 — Grille galerie d'images

.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1rem;
}

.gallery-item {
  border-radius: 8px;
  overflow: hidden;
  position: relative;
  aspect-ratio: 4/3;
}

.gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.gallery-item:hover img {
  transform: scale(1.08);
}

.gallery-caption {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: linear-gradient(transparent, rgba(0,0,0,0.7));
  color: white;
  padding: 1rem 0.75rem 0.75rem;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.gallery-item:hover .gallery-caption {
  opacity: 1;
}

Rendu :

Exemple 10 — Cartes de profil avec avatar

Rendu :

AM
Alice Martin
Développeuse Full-Stack
142 Projets
3,2k Abonnés
98% Note
BD
Bob Dupont
UI/UX Designer
87 Projets
5,1k Abonnés
96% Note
CL
Claire Leroy
Chef de projet
204 Projets
1,8k Abonnés
99% Note

Exemple 11 — Hero avec image d'arrière-plan

.hero-image {
  position: relative;
  height: 400px;
  border-radius: 8px;
  overflow: hidden;
}

.hero-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-image .hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 60%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 2rem;
  color: white;
}

Rendu :

Bienvenue dans notre cours CSS
Maîtrisez les images et les effets visuels pour créer des sites web époustouflants.

Exemple 12 — Comparaison avant/après

.comparison-container {
  position: relative;
  width: 100%;
  aspect-ratio: 16/10;
  overflow: hidden;
  cursor: col-resize;
}

.comparison-after {
  position: absolute;
  inset: 0;
  clip-path: inset(0 50% 0 0);  /* Révèle la moitié gauche */
}

.comparison-slider {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 3px;
  background: white;
  z-index: 2;
}

Rendu :

AVANT — Image originale (noir & blanc)
APRÈS — Image corrigée (couleur)
Avant Après

Exemple 13 — Ratios d'aspect variés

Rendu :

1/1 (carré)
16/9 (paysage)
3/4 (portrait)
21/9 (ultra-large)

5. Erreurs fréquentes

Erreur n°1 — Ne pas définir max-width: 100% sur les images

Les images débordent de leur conteneur si elles sont plus larges. Toujours utiliser max-width: 100% pour un comportement responsive.

/* ❌ MAUVAIS — L'image déborde */
img { /* pas de max-width */ }

/* ✅ BON — L'image reste dans son conteneur */
img { max-width: 100%; height: auto; }
Erreur n°2 — Utiliser object-fit sans définir les dimensions

object-fit n'a aucun effet si l'image a sa taille naturelle. Il faut imposer width et height (ou aspect-ratio) sur l'image.

/* ❌ MAUVAIS — object-fit n'aura aucun effet */
img { object-fit: cover; }

/* ✅ BON — Dimensions imposées + object-fit */
img {
  width: 300px;
  height: 200px;
  object-fit: cover;
}
Erreur n°3 — Confondre filter: opacity() et la propriété opacity

filter: opacity() et opacity donnent le même résultat visuel, mais filter est rendu sur le GPU (meilleures performances pour les animations) tandis que opacity comme propriété de layout est moins coûteux en mode statique.

Erreur n°4 — Oublier le préfixe -webkit-mask-image

Safari nécessite -webkit-mask-image. Sans ce préfixe, les masques ne fonctionnent pas sur tous les navigateurs.

/* ❌ MAUVAIS — Ne fonctionne pas sur Safari */
img { mask-image: linear-gradient(black, transparent); }

/* ✅ BON — Compatibilité complète */
img {
  -webkit-mask-image: linear-gradient(black, transparent);
  mask-image: linear-gradient(black, transparent);
}
Erreur n°5 — Utiliser box-shadow au lieu de drop-shadow pour des images non-rectangulaires

box-shadow suit toujours le rectangle de la boîte. Si votre image est découpée avec clip-path ou border-radius: 50%, utilisez filter: drop-shadow() pour une ombre qui suit la forme.

/* ❌ MAUVAIS — Ombre rectangulaire sur un cercle */
img {
  border-radius: 50%;
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}

/* ✅ BON — Ombre qui suit le cercle */
img {
  border-radius: 50%;
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.2));
}
Erreur n°6 — Ne pas fournir d'alt text aux images

Les images décoratives (alt="") et les images informatives (alt="description") doivent être différenciées. Ne jamais omettre l'attribut alt.

Erreur n°7 — Ignorer le format d'image moderne

WebP et AVIF offrent une meilleure compression que JPEG/PNG. Utilisez <picture> avec <source> pour la rétrocompatibilité.

<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="Description">
</picture>

6. Bonnes pratiques

Bonne pratique n°1 — Toujours rendre les images responsives

img { max-width: 100%; height: auto; } est le point de départ de tout site moderne.

Bonne pratique n°2 — Utiliser object-fit pour les images en grille

Quand vous imposez des dimensions fixes (galeries, avatars, cartes), object-fit: cover garantit un rendu uniforme sans déformation.

Bonne pratique n°3 — Préférer filter: drop-shadow aux box-shadow pour les formes

drop-shadow suit la forme alpha de l'image, contrairement à box-shadow qui suit toujours le rectangle.

Bonne pratique n°4 — Utiliser <picture> pour le format moderne

Fournissez WebP/AVIF en priorité avec fallback JPEG/PNG. Le navigateur choisit le meilleur format supporté.

Bonne pratique n°5 — Préférer aspect-ratio aux hacks de padding

Avant aspect-ratio, on utilisait le trick padding-top: 56.25%. Désormais, aspect-ratio: 16/9 est plus lisible et maintenable.

Bonne pratique n°6 — Optimiser les transitions de filtres

Les filtres sont animables ! Utilisez transition pour des effets fluides au survol.

/* Transition fluide d'un filtre */
img {
  filter: grayscale(100%);
  transition: filter 0.4s ease;
}

img:hover {
  filter: grayscale(0%);
}
Bonne pratique n°7 — Définir width et height sur les <img>

Même avec object-fit: cover, définir les attributs HTML width et height évite les décalages de mise en page (CLS — Cumulative Layout Shift).

Bonne pratique n°8 — Toujours inclure alt text

Accessibilité obligatoire. Utilisez alt="" (vide) pour les images purement décoratives, et une description concise pour les images informatives.

7. Mini-défi

Défi n°1 — Galerie d'effets de filtre

Objectif : Créer une galerie de 6 images (ou divs colorées) où chaque image a un filtre différent au repos, et passe à none au survol avec une transition fluide :

  • Grayscale, sepia, blur, invert, saturate, hue-rotate
  • Transition de 0.4s ease
  • Grille responsive avec auto-fill

Défi n°2 — Avatar interactif

Objectif : Créer un composant avatar avec :

  • Un anneau coloré animé au survol (changement de couleur de bordure)
  • Un clip-path: circle() pour le masquage
  • Un effet drop-shadow au survol
  • Une transition fluide sur toutes les propriétés

Défi n°3 — Hero section immersive

Objectif : Créer une section hero avec :

  • Une image de fond avec object-fit: cover
  • Un overlay dégradé semi-transparent
  • Du texte superposé avec un contraste suffisant
  • Un effet de parallaxe subtil au scroll (optionnel)

8. Projet — Portfolio d'images

Consigne :

Créez un mini-portfolio d'images qui combine les concepts vus dans ce chapitre :

  1. Un hero banner avec image de fond, overlay et texte
  2. Une grille galerie avec effets de zoom et captions au survol
  3. Des cartes de profil avec avatars cercle/anneau/groupe
  4. Un effet grayscale → couleur sur les images de la galerie
  5. Une section figure + figcaption avec ombre et style
  6. Le tout doit être 100% responsive

9. Révision

Récapitulatif des concepts clés

Concept Propriétés Usage principal
Responsive max-width: 100%, height: auto Images qui s'adaptent au conteneur
Ajustement object-fit, object-position Recadrage intelligent dans un conteneur fixe
Proportions aspect-ratio Rapport largeur/hauteur fixe
Résolution image-set(), <picture>, srcset Images adaptatives selon la densité d'écran
Filtres filter : blur, brightness, contrast, grayscale, sepia, hue-rotate, saturate, invert, opacity, drop-shadow Effets visuels en temps réel
Découpe clip-path : circle, ellipse, polygon, inset Formes non-rectangulaires
Masquage mask-image, -webkit-mask-image Fondu et formes avec dégradés
Fusion mix-blend-mode Mélange artistique avec l'arrière-plan
Hover effects transform, filter, opacity Zoom, overlay, révélation, grayscale→couleur
Sémantique <figure>, <figcaption>, <picture> Images sémantiques avec légendes

Quiz rapide

  1. Quelle propriété CSS contrôle la manière dont une image remplit son conteneur ?
  2. Quelle est la différence entre object-fit: cover et object-fit: contain ?
  3. Pourquoi faut-il inclure -webkit-mask-image en plus de mask-image ?
  4. Quelle fonction filter suit la forme alpha d'une image (utile pour les PNGs transparents) ?
  5. Comment fournir plusieurs formats d'image au navigateur pour qu'il choisisse le meilleur ?
Réponses :
  1. object-fit
  2. cover remplit en coupant le surplus, contain affiche l'image entière (peut laisser des espaces)
  3. Safari nécessite le préfixe -webkit- pour mask-image
  4. drop-shadow() (et mask-image en fait, mais drop-shadow est la fonction la plus pertinente pour les ombres)
  5. Avec <picture> et des <source> avec type différent

Cheat sheet

/* Image responsive */
img { max-width: 100%; height: auto; display: block; }

/* Object-fit dans un conteneur fixe */
img { width: 300px; height: 200px; object-fit: cover; }

/* Grayscale → Couleur au survol */
img { filter: grayscale(100%); transition: filter 0.4s ease; }
img:hover { filter: grayscale(0%); }

/* Clip-path cercle */
img { clip-path: circle(50%); }

/* Mask dégradé vers le bas */
img {
  -webkit-mask-image: linear-gradient(black 50%, transparent);
  mask-image: linear-gradient(black 50%, transparent);
}

/* Avatar anneau */
.avatar {
  border-radius: 50%;
  border: 4px solid #2563eb;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));
}

/* Ombre qui suit la forme */
img { filter: drop-shadow(4px 4px 8px rgba(0,0,0,0.3)); }