Niveau 14

Les Vidéos

Maîtriser l'intégration et le stylisme des vidéos en CSS : conteneurs responsives, overlays, contrôles personnalisés, arrière-plans vidéo, et composants vidéo modernes.

1. Le concept fondamental

En une phrase : Les vidéos en CSS se gèrent à travers des conteneurs intelligents, des overlays interactifs et des objets flexibles pour créer des expériences multimédia riches et responsives.

Les vidéos sont devenues un pilier incontournable du web moderne. En CSS, on ne se contente pas de les afficher : on crée des conteneurs proportionnels, des overlays interactifs, des barres de contrôle personnalisées, et même des sections hero avec vidéo d'arrière-plan. Ce chapitre couvre tout l'arsenal dont vous disposez pour maîtriser les vidéos en CSS.

Deux façons d'intégrer des vidéos

Ce que le CSS peut faire avec les vidéos

Capacité Propriétés CSS Usage
Dimensionnement aspect-ratio, width, max-width Vidéos responsives, ratios fixes
Ajustement object-fit, object-position Recadrage intelligent dans un conteneur
Overlays position: absolute, opacity Bouton play, titre superposé, gradient
Contrôles appearance: none, pseudo-éléments Barre de progression personnalisée
Plein écran :fullscreen, object-fit Mode plein écran stylé
Fond vidéo Positionnement, overlay Sections hero avec vidéo d'arrière-plan
Lazy loading loading="lazy", decoding Performance et chargement différé
Grilles CSS Grid, aspect-ratio Grilles de miniatures vidéo

2. Syntaxe et propriétés

Les bases : la balise video

La balise <video> est l'élément HTML natif pour intégrer des vidéos. En CSS, on la style comme un conteneur pour contrôler son apparence.

<!-- Vidéo avec contrôles natifs -->
<video controls width="640" height="360">
  <source src="video.mp4" type="video/mp4">
  Votre navigateur ne supporte pas la vidéo HTML5.
</video>

Attributs HTML de la balise video

Attribut Description
controls Affiche les contrôles natifs du navigateur (play, volume, barre de progression)
autoplay Lance la vidéo automatiquement (souvent bloqué sans muted)
muted Coupe le son par défaut — requis pour l'autoplay dans la plupart des navigateurs
loop Rejoue la vidéo en boucle à la fin
playsinline Empêche le plein écran automatique sur iOS
poster Image affichée avant le lancement de la vidéo
preload Contrôle le chargement : none, metadata, auto
width / height Définir les dimensions en HTML (améliore le CLS)

aspect-ratio pour les conteneurs vidéo

/* Conteneur vidéo responsive 16:9 */
.video-wrapper {
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
}

/* Ratio 4:3 pour les vidéos classiques */
.video-wrapper.classic {
  aspect-ratio: 4 / 3;
}

/* Ratio 21:9 pour le cinéma */
.video-wrapper.cinema {
  aspect-ratio: 21 / 9;
}

object-fit pour les vidéos

object-fit fonctionne exactement comme pour les images — il contrôle comment la vidéo remplit son conteneur.

video {
  width: 100%;
  height: 100%;
  object-fit: cover;        /* Remplit le conteneur, coupe le surplus */
  object-position: center;  /* Centre la vidéo */
}

/* Alternative : contain pour voir toute la vidéo */
video {
  object-fit: contain;      /* Vidéo entière, espaces restants */
  background-color: #000;  /* Fond noir pour les bandes */
}
Valeur Comportement
fill Remplit le conteneur (défaut) — peut déformer la vidéo
contain Affiche la vidéo entière — peut laisser des bandes noires
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

Overlays vidéo (bouton play, titre)

/* Conteneur avec overlay */
.video-container {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  cursor: pointer;
}

.video-container video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Overlay sombre */
.video-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.3s ease;
}

.video-container:hover .video-overlay {
  background: rgba(0, 0, 0, 0.6);
}

/* Bouton play */
.play-btn {
  width: 72px;
  height: 72px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.3s ease, background 0.3s ease;
}

.play-btn::after {
  content: "";
  display: block;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 12px 0 12px 22px;
  border-color: transparent transparent transparent #1e293b;
  margin-left: 4px;
}

.video-container:hover .play-btn {
  transform: scale(1.1);
  background: white;
}

/* Titre superposé */
.video-title-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
  color: white;
  padding: 2rem 1.5rem 1.5rem;
}

.video-title-overlay h3 {
  margin: 0;
  font-size: 1.4rem;
}

.video-title-overlay p {
  margin: 0.5rem 0 0;
  opacity: 0.8;
  font-size: 0.9rem;
}

Style des contrôles personnalisés

/* Masquer les contrôles natifs */
video::-webkit-media-controls {
  display: none !important;
}

video::-moz-media-controls {
  display: none !important;
}

/* Barre de progression personnalisée */
.video-progress {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: rgba(255, 255, 255, 0.3);
  cursor: pointer;
}

.video-progress-fill {
  height: 100%;
  background: #ef4444;
  width: 0%;
  transition: width 0.1s linear;
}

.video-progress:hover {
  height: 6px;
}

/* Contrôles custom */
.video-controls {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 0.75rem 1rem;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
  display: flex;
  align-items: center;
  gap: 1rem;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.video-container:hover .video-controls {
  opacity: 1;
}

.video-controls button {
  background: none;
  border: none;
  color: white;
  font-size: 1.2rem;
  cursor: pointer;
  padding: 0.25rem;
}

.video-controls .time {
  color: rgba(255, 255, 255, 0.8);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

Mode plein écran

/* Style en plein écran */
.video-container:fullscreen {
  background: black;
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-container:fullscreen video {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* Support Safari */
.video-container:-webkit-full-screen {
  background: black;
  display: flex;
  align-items: center;
  justify-content: center;
}

Vidéo d'arrière-plan (hero section)

/* Section hero avec vidéo de fond */
.hero-video-section {
  position: relative;
  width: 100%;
  height: 100vh;
  min-height: 400px;
  overflow: hidden;
}

.hero-video-section video {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  min-width: 100%;
  min-height: 100%;
  transform: translate(-50%, -50%);
  object-fit: cover;
}

.hero-video-section .hero-content {
  position: relative;
  z-index: 2;
  color: white;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  text-align: center;
  padding: 2rem;
  background: rgba(0, 0, 0, 0.3);
}

Lazy loading et performances

<!-- Chargement différé (performance) -->
<video
  loading="lazy"
  decoding="async"
  preload="none"
  poster="thumbnail.jpg"
>
  <source src="video.mp4" type="video/mp4">
</video>

<!-- Autoplay muted (背景 vidéo, pas besoin de son) -->
<video autoplay muted loop playsinline>
  <source src="bg-video.mp4" type="video/mp4">
</video>
Astuce : Utilisez preload="none" et poster pour les vidéos hors écran. Le navigateur ne chargera la vidéo que lorsqu'elle sera visible, ce qui améliore considérablement les performances.

Iframe YouTube responsive

/* Conteneur responsive pour iframe YouTube/Vimeo */
.iframe-wrapper {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
}

.iframe-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

/* Utilisation */
<div class="iframe-wrapper">
  <iframe
    src="https://www.youtube.com/embed/VIDEO_ID"
    title="Titre de la vidéo"
    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
    allowfullscreen
  ></iframe>
</div>
Erreur fréquente : Les iframes YouTube avec width et height fixes ne sont pas responsives. Utilisez toujours la technique aspect-ratio: 16/9 avec un position: absolute sur l'iframe.

Grille de miniatures vidéo

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

.video-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  cursor: pointer;
}

.video-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}

.video-thumb:hover img {
  transform: scale(1.05);
}

/* Badge durée */
.video-thumb .duration {
  position: absolute;
  bottom: 0.5rem;
  right: 0.5rem;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

Carte vidéo

.video-card {
  background: white;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.video-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}

.video-card .card-thumbnail {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

.video-card .card-thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-card .card-info {
  padding: 1rem;
  display: flex;
  gap: 0.75rem;
}

.video-card .card-avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  flex-shrink: 0;
}

.video-card .card-title {
  font-weight: 600;
  font-size: 0.95rem;
  margin-bottom: 0.25rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.video-card .card-meta {
  font-size: 0.8rem;
  color: #64748b;
}

3. Visualisation

object-fit en vidéos

fill (déformé)
contain (bandes noires)
cover (recadré)

Comparaison visuelle des valeurs de object-fit pour les vidéos (ratio 4:3 dans un conteneur carré)

Structure d'un overlay vidéo

video
gradient overlay
play button
titre + métadonnées
z-index: 0
z-index: 1
z-index: 2
z-index: 3

Superposition des couches dans un composant vidéo avec overlay

Grille de miniatures

12:34
Introduction au CSS
Channel Dev
8:21
Flexbox en pratique
Channel Dev
15:07
CSS Grid avancé
Channel Dev
22:45
Animations CSS
Channel Dev

Grille de miniatures vidéo avec overlay play, durée et métadonnées

4. Exemples progressifs

Exemple 1 — Vidéo responsive de base

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

Rendu :

Vidéo responsive — width: 100% + height: auto

Exemple 2 — Ratio 16:9 avec aspect-ratio

.video-16-9 {
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  background: #000;
}

.video-16-9 video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

Rendu :

16:9 — aspect-ratio: 16/9

Exemple 3 — Bouton play overlay

.video-container {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
}

.play-btn {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 72px;
  height: 72px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.3s ease;
}

.play-btn::after {
  content: "";
  border-style: solid;
  border-width: 12px 0 12px 22px;
  border-color: transparent transparent transparent #1e293b;
  margin-left: 4px;
}

.video-container:hover .play-btn {
  transform: translate(-50%, -50%) scale(1.15);
}

Rendu :

Survolez le bouton → animation de zoom

Exemple 4 — Overlay titre sur vidéo

.video-with-title {
  position: relative;
  aspect-ratio: 16 / 9;
  border-radius: 8px;
  overflow: hidden;
}

.video-title-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.8));
  color: white;
  padding: 2rem 1.5rem 1.5rem;
  transform: translateY(10px);
  opacity: 0;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.video-with-title:hover .video-title-bar {
  transform: translateY(0);
  opacity: 1;
}

Rendu :

Titre de la vidéo

1,234 vues · il y a 3 jours

Survolez pour révéler le titre

Exemple 5 — Carte vidéo style YouTube

.video-card {
  background: white;
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  transition: transform 0.3s ease;
}

.video-card:hover {
  transform: translateY(-4px);
}

.video-card .thumb {
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

.video-card .thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}

.video-card:hover .thumb img {
  transform: scale(1.05);
}

.video-card .info {
  padding: 0.75rem;
  display: flex;
  gap: 0.75rem;
}

.video-card .avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
}

.video-card .title {
  font-weight: 600;
  font-size: 0.95rem;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.video-card .meta {
  font-size: 0.8rem;
  color: #64748b;
  margin-top: 0.25rem;
}

Rendu :

12:34
Introduction complète au CSS moderne 2026
Channel Dev · 15K vues · il y a 2 jours
8:21
Flexbox : les 10 propriétés essentielles
Channel Dev · 8,2K vues · il y a 5 jours
22:45
Animations CSS : du débutant à l'expert
Channel Dev · 23K vues · il y a 1 semaine

Exemple 6 — Grille de miniatures vidéo

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

.video-thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  cursor: pointer;
}

.video-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.3s ease;
}

.video-thumb:hover img {
  transform: scale(1.05);
}

.video-thumb .duration {
  position: absolute;
  bottom: 0.5rem;
  right: 0.5rem;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 0.15rem 0.5rem;
  border-radius: 4px;
  font-size: 0.8rem;
}

.video-thumb .play-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.3);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.video-thumb:hover .play-overlay {
  opacity: 1;
}

Rendu :

12:34
8:21
15:07
22:45

Exemple 7 — Section hero avec vidéo d'arrière-plan

.hero-video {
  position: relative;
  height: 100vh;
  min-height: 400px;
  overflow: hidden;
}

.hero-video video {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  min-width: 100%;
  min-height: 100%;
  transform: translate(-50%, -50%);
  object-fit: cover;
}

.hero-video .hero-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: white;
  text-align: center;
  padding: 2rem;
}

.hero-video .hero-overlay h1 {
  font-size: 3rem;
  margin-bottom: 1rem;
}

.hero-video .hero-overlay p {
  font-size: 1.2rem;
  opacity: 0.9;
  max-width: 600px;
}

Rendu :

Bienvenue

Découvrez nos cours en vidéo

Exemple 8 — Iframe YouTube/Vimeo responsive

.iframe-wrapper {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.iframe-wrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border: none;
}

/* Centré avec max-width */
.iframe-center {
  max-width: 800px;
  margin: 0 auto;
}

Rendu :

<iframe> YouTube/Vimeo responsive

aspect-ratio: 16/9 + position: absolute

Exemple 9 — Barre de progression personnalisée

.custom-progress {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: rgba(255, 255, 255, 0.3);
  cursor: pointer;
  transition: height 0.2s ease;
}

.custom-progress:hover {
  height: 6px;
}

.custom-progress-fill {
  height: 100%;
  background: #ef4444;
  width: 35%;
  border-radius: 0 3px 3px 0;
  position: relative;
}

.custom-progress-fill::after {
  content: "";
  position: absolute;
  right: -6px;
  top: 50%;
  transform: translateY(-50%);
  width: 12px;
  height: 12px;
  background: #ef4444;
  border-radius: 50%;
  opacity: 0;
  transition: opacity 0.2s ease;
}

.custom-progress:hover .custom-progress-fill::after {
  opacity: 1;
}

Rendu :

Survolez la barre → thumb indicateur apparaît

Exemple 10 — Vidéo avec lazy loading et poster

<!-- Chargement optimisé -->
<video
  class="lazy-video"
  controls
  preload="none"
  poster="poster.jpg"
  width="800"
  height="450"
>
  <source src="video.mp4" type="video/mp4">
  <source src="video.webm" type="video/webm">
  <p>Votre navigateur ne supporte pas la vidéo HTML5.</p>
</video>

/* Style du poster avant chargement */
.lazy-video {
  width: 100%;
  height: auto;
  border-radius: 8px;
  background-color: #000;
  object-fit: contain;
}

/* Placeholder animé pendant le chargement */
.lazy-video:not([src]) {
  background: linear-gradient(90deg, #1e293b 25%, #334155 50%, #1e293b 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

Rendu :

preload="none" + poster = chargement différé optimal

5. Erreurs fréquentes

Erreur n°1 — Ne pas utiliser aspect-ratio pour les iframes vidéo

Les iframes YouTube/Vimeo avec width et height fixes cassent le responsive design. Utilisez aspect-ratio: 16/9 avec position: absolute sur l'iframe.

/* ❌ MAUVAIS — Dimensions fixes, pas responsive */
<iframe width="560" height="315" src="..."></iframe>

/* ✅ BON — Responsive avec aspect-ratio */
.video-wrapper {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
}
.video-wrapper iframe {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  border: none;
}
Erreur n°2 — Oublier autoplay + muted pour les vidéos d'arrière-plan

Les navigateurs modernes bloquent l'autoplay avec son. Pour une vidéo d'arrière-plan, combinez toujours autoplay, muted, loop et playsinline.

/* ❌ MAUVAIS — Bloqué par le navigateur */
<video autoplay><source src="bg.mp4"></video>

/* ✅ BON — autoplay autorisé */
<video autoplay muted loop playsinline>
  <source src="bg.mp4" type="video/mp4">
</video>
Erreur n°3 — Utiliser object-fit sans dimensions imposées

object-fit n'a aucun effet si la vidéo a sa taille naturelle. Il faut imposer width et height (ou aspect-ratio).

/* ❌ MAUVAIS — object-fit sans effet */
video { object-fit: cover; }

/* ✅ BON — Dimensions imposées */
video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
Erreur n°4 — Ne pas définir le poster

Sans poster, l'utilisateur voit un écran noir avant le lancement. Ajoutez toujours une image de prévisualisation.

Erreur n°5 — Ignorer preload pour les performances

Par défaut, preload="auto" charge toute la vidéo. Pour les vidéos hors écran, utilisez preload="none" ou preload="metadata".

Erreur n°6 — Oublier l'attribut title sur les iframes

L'attribut title sur les iframes est essentiel pour l'accessibilité. Les lecteurs d'écran en ont besoin pour décrire le contenu.

/* ❌ MAUVAIS — Pas d'accessibilité */
<iframe src="..."></iframe>

/* ✅ BON — Titre descriptif */
<iframe src="..." title="Vidéo: Introduction au CSS"></iframe>
Erreur n°7 — Ne pas inclure les dimensions width/height en HTML

Même avec CSS, définir width et height en HTML sur <video> évite les décalages de mise en page (CLS) pendant le chargement.

6. Bonnes pratiques

Bonne pratique n°1 — Toujours utiliser aspect-ratio pour les conteneurs vidéo

aspect-ratio: 16/9 remplace le hack padding-top: 56.25%. C'est plus lisible et maintenable.

Bonne pratique n°2 — Utiliser object-fit: cover pour les thumbnails

Quand les vidéos ont des ratios différents, object-fit: cover garantit un rendu uniforme dans la grille.

Bonne pratique n°3 — Toujours inclure muted pour les vidéos d'arrière-plan

Les navigateurs bloquent l'autoplay avec son. muted est obligatoire pour les vidéos décoratives.

Bonne pratique n°4 — Fournir un poster pour toutes les vidéos

L'image poster améliore l'UX et le CLS. Choisissez une image représentative et optimisée.

Bonne pratique n°5 — Utiliser preload="none" pour les vidéos hors écran

Économisez la bande passante des utilisateurs en ne chargeant les vidéos que lorsqu'elles sont proches du viewport.

Bonne pratique n°6 — Ajouter loading="lazy" sur les iframes

Les iframes YouTube ne se chargent qu'au scroll avec loading="lazy", ce qui améliore significativement le temps de chargement initial.

Bonne pratique n°7 — Inclure les dimensions en HTML

Définissez width et height sur <video> et les iframes pour éviter les décalages CLS.

Bonne pratique n°8 — Toujours mettre un title sur les iframes

Accessibilité obligatoire. Décrivez le contenu de la vidéo pour les lecteurs d'écran.

/* Checklist d'une vidéo optimisée */
<video
  controls
  width="800"
  height="450"
  preload="none"
  poster="poster.jpg"
  playsinline
>
  <source src="video.mp4" type="video/mp4">
  <source src="video.webm" type="video/webm">
  <p>Alternative textuelle</p>
</video>

/* Styles de base */
video {
  width: 100%;
  height: auto;
  border-radius: 8px;
  background-color: #000;
}

7. Mini-défi

Défi n°1 — Lecteur vidéo custom

Objectif : Créer un conteneur vidéo avec :

  • Ratio 16:9 responsive avec aspect-ratio
  • Un overlay sombre qui apparaît au survol
  • Un bouton play centré avec animation de zoom
  • Un titre superposé qui glisse vers le bas au survol
  • Une barre de progression custom en bas

Défi n°2 — Grille de miniatures

Objectif : Créer une grille responsive de miniatures vidéo :

  • Grille avec auto-fill et minmax(280px, 1fr)
  • Chaque miniature a aspect-ratio: 16/9
  • Bouton play overlay qui apparaît au survol
  • Badge durée en bas à droite
  • Effet zoom subtil au survol

Défi n°3 — Section hero vidéo

Objectif : Créer une section hero avec vidéo d'arrière-plan :

  • Vidéo en fond avec object-fit: cover
  • Overlay semi-transparent
  • Titre et sous-titre centrés
  • Bouton CTA avec effet hover
  • Le tout doit être responsive

8. Projet — Plateforme vidéo

Consigne :

Créez une mini-plateforme vidéo qui combine les concepts vus dans ce chapitre :

  1. Une section hero avec vidéo d'arrière-plan, overlay et CTA
  2. Une grille de miniatures avec effets hover, badges durée et play overlay
  3. Un lecteur vidéo avec contrôles custom (bouton play, barre de progression)
  4. Des cartes vidéo style YouTube avec avatar, titre, métadonnées
  5. Un embed YouTube responsive avec la technique aspect-ratio
  6. Le tout doit être 100% responsive et accessible

9. Révision

Récapitulatif des concepts clés

Concept Propriétés Usage principal
Responsive aspect-ratio, width: 100% Vidéos qui s'adaptent au conteneur
Ajustement object-fit, object-position Recadrage intelligent dans un conteneur fixe
Overlays position: absolute, opacity, transition Bouton play, titre, gradient
Contrôles appearance: none, pseudo-éléments Barre de progression personnalisée
Plein écran :fullscreen, object-fit Mode plein écran stylé
Fond vidéo Positionnement central, overlay Sections hero avec vidéo d'arrière-plan
Performances loading="lazy", preload, poster Chargement différé et optimisé
Iframe aspect-ratio, position: absolute YouTube, Vimeo responsive
Grilles CSS Grid, auto-fill Grilles de miniatures vidéo

Quiz rapide

  1. Pourquoi faut-il combiner autoplay et muted pour les vidéos d'arrière-plan ?
  2. Quelle propriété CSS permet de garder le ratio 16:9 d'une vidéo ?
  3. Comment rendre un iframe YouTube responsive ?
  4. Quel attribut HTML empêche le chargement complet d'une vidéo hors écran ?
  5. Pourquoi object-fit ne fonctionne-t-il pas sans dimensions imposées ?
Réponses :
  1. Les navigateurs modernes bloquent l'autoplay avec son. muted débloque l'autoplay.
  2. aspect-ratio: 16 / 9 (remplace le hack padding-top: 56.25%)
  3. Conteneur avec aspect-ratio: 16/9 + iframe en position: absolute fill
  4. preload="none" (ou loading="lazy" pour les iframes)
  5. object-fit n'a d'effet que lorsque l'élément a des dimensions différentes de sa taille naturelle

Cheat sheet

/* Conteneur vidéo responsive */
.video-wrapper {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: 8px;
}

.video-wrapper video,
.video-wrapper iframe {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  border: none;
  object-fit: cover;
}

/* Overlay au survol */
.video-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.4);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.video-wrapper:hover .video-overlay {
  opacity: 1;
}

/* Vidéo d'arrière-plan */
.hero-video video {
  position: absolute;
  top: 50%; left: 50%;
  width: 100%; min-width: 100%;
  min-height: 100%;
  transform: translate(-50%, -50%);
  object-fit: cover;
}

/* Chargement optimisé */
<video controls preload="none" poster="poster.jpg"
  width="800" height="450">

/* Iframe YouTube responsive */
<div style="aspect-ratio:16/9; position:relative">
  <iframe style="position:absolute; inset:0; width:100%; height:100%">
</div>