Développement Web

HTML et CSS modernes : les essentiels à connaître

11 دقائق للقراءة

Ce que vous saurez faire à la fin

  • Construire un site web propre avec HTML5 sémantique et CSS moderne (Grid, Flexbox, variables)
  • Produire un design responsive sans framework en écrivant 40 % de code en moins qu’avant 2020
  • Utiliser les nouvelles fonctions CSS : :has(), container queries, @layer
  • Optimiser les Core Web Vitals de base (LCP, CLS) sans outil externe
  • Livrer une landing page complète en 4 heures

Prérequis

  • VS Code ou Cursor avec extensions « Live Server » et « Prettier »
  • Chrome ou Firefox récent (pour DevTools responsive)
  • Un navigateur récent (HTML et CSS moderne nécessitent Chrome 105+, Safari 16+)

Vue d’ensemble 1 — Squelette HTML5 sémantique

Fini les <div> partout. Utilisez les balises qui ont du sens pour Google et les lecteurs d’écran.

<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Votre titre SEO | Marque</title>
  <meta name="description" content="155 caractères qui vendent">
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header> <nav>...</nav> </header>
  <main>
    <section class="hero">...</section>
    <article>...</article>
  </main>
  <footer>...</footer>
</body>
</html>

Vue d’ensemble 2 — CSS moderne avec variables et @layer

:root {
  --color-primary: #1a5490;
  --color-accent: #f39c12;
  --radius: 8px;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 2rem;
  --font-sans: 'Inter', system-ui, sans-serif;
}

@layer reset, base, components, utilities;

@layer reset {
  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
}

@layer base {
  body {
    font-family: var(--font-sans);
    line-height: 1.6;
    color: #222;
  }
}

Vue d’ensemble 3 — Grid pour layouts complexes

.grid-products {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: var(--space-md);
}
/* Le auto-fill gère automatiquement le responsive, plus besoin de media queries classiques */

Vue d’ensemble 4 — Flexbox pour les petits composants

.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
}

.card-actions {
  display: flex;
  justify-content: space-between;
  margin-top: auto;
}

Vue d’ensemble 5 — Le sélecteur :has() change tout

Sélectionner un parent selon son enfant, impossible avant 2023.

/* Si une carte contient un badge "Nouveau", surlignez-la */
.card:has(.badge-new) {
  border: 2px solid var(--color-accent);
  background: #fff8e1;
}

/* Si un formulaire a un champ en erreur, bordure rouge sur le form */
form:has(:invalid) { border-color: red; }

Vue d’ensemble 6 — Container queries

Responsive basé sur le conteneur, pas la fenêtre. Indispensable pour composants réutilisables.

.sidebar { container-type: inline-size; container-name: side; }

@container side (min-width: 400px) {
  .widget { display: grid; grid-template-columns: 1fr 2fr; }
}

Vue d’ensemble 7 — Images responsives et Core Web Vitals

<picture>
  <source srcset="hero.avif" type="image/avif">
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" alt="Description" width="1200" height="600" loading="lazy" fetchpriority="high">
</picture>

Points clés : toujours width et height (évite le CLS), loading="lazy" pour les images sous la ligne de flottaison, fetchpriority="high" pour le LCP hero.

Vue d’ensemble 8 — Typographie fluide sans media queries

h1 { font-size: clamp(1.75rem, 1rem + 3vw, 3rem); }
p { font-size: clamp(0.95rem, 0.85rem + 0.5vw, 1.125rem); }

Vue d’ensemble 9 — Animations accessibles

.button { transition: transform 0.2s ease; }
.button:hover { transform: translateY(-2px); }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

Erreurs à bannir

  • Pixel partout : utilisez rem pour la typo, em pour les marges locales
  • Oublier alt : image sans alt = inaccessible + pénalité Google
  • Font-family générique seule : toujours un fallback système
  • Trop de !important : signe d’un CSS mal structuré ; utilisez @layer

Prochaines étapes

  • Migrer vers Tailwind CSS v4 si le projet dépasse 5 000 lignes de CSS
  • Mesurer vos Core Web Vitals avec PageSpeed Insights
  • Apprendre les View Transitions API pour animations inter-pages sans framework

Étape 1 : poser une base HTML5 sémantique propre

Avant les effets visuels, structurez la page avec les bonnes balises. Un développeur qui démarre un projet à Dakar pour un client à Abidjan gagne du temps si le squelette parle de lui-même. Utilisez header, nav, main, article, section, aside et footer plutôt que des div anonymes. Ajoutez les attributs lang sur html, les meta viewport et charset, et un title clair.

<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Catalogue produits Dakar</title>
  </head>
  <body>
    <header>...</header>
    <main>...</main>
    <footer>...</footer>
  </body>
</html>

Cette base passe sans avertissement le validateur du W3C. Comment vérifier le bon fonctionnement : un audit Lighthouse renvoie 100 sur le score sémantique, et un lecteur d’écran annonce correctement les régions de la page.

Étape 2 : maîtriser les sélecteurs CSS modernes, dont :has()

Le sélecteur :has() est désormais disponible sur tous les navigateurs evergreen (Chrome 105+, Safari 15.4+, Firefox 121+). Il permet de styler un parent en fonction de ses enfants, ce qui supprime des centaines de lignes de JavaScript. Combinez-le avec :is() et :where() pour des règles concises.

/* Carte produit avec un bouton « rupture » : on grise tout */
.card:has(.btn--rupture) {
  opacity: 0.55;
  pointer-events: none;
}

/* Formulaire avec un champ invalide : on colore l'entête */
form:has(:user-invalid) header { color: #c0392b; }

Une fois ces règles en place, le DOM seul suffit à piloter l’état visuel. Le test concluant : vous supprimez le code JS qui ajoutait manuellement des classes is-error ou is-disabled.

Étape 3 : passer au layout avec Grid et Flexbox

Flexbox gère l’alignement sur un axe, Grid gère le placement en deux dimensions. Pour une page produit responsive d’une boutique aux Almadies, utilisez Grid pour la disposition globale et Flexbox pour les barres d’actions internes.

.catalogue {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1.5rem;
}
.card__actions {
  display: flex;
  gap: .5rem;
  align-items: center;
  justify-content: space-between;
}

auto-fill et minmax suppriment 90 % des media queries pour les grilles cartes. La preuve que ça tourne : la page s’adapte de 320 px (mobile Cotonou en 3G) à 1920 px (écran bureau Plateau) sans saut visuel ni scroll horizontal.

Étape 4 : adopter les Container Queries

Les media queries répondent à la taille de la fenêtre. Les container queries répondent à la taille du conteneur d’un composant. Disponibles partout depuis 2023, elles sont indispensables pour des composants réutilisables (sidebar, dashboard, embed).

.card { container-type: inline-size; container-name: card; }

@container card (min-width: 480px) {
  .card { display: grid; grid-template-columns: 160px 1fr; }
}

Une même carte produit s’adapte selon qu’elle est dans une sidebar étroite ou dans la zone principale. Le signal : zéro media query pour les composants, uniquement pour le layout global.

Étape 5 : utiliser les variables CSS et color-mix()

Les custom properties pilotent le thème du site. Combinées à color-mix(), elles génèrent des nuances sans préprocesseur. Pratique pour un thème clair-sombre ou les marques d’un client à Sandaga.

:root {
  --brand: #0d6efd;
  --brand-soft: color-mix(in srgb, var(--brand) 18%, white);
  --text: #1a1a1a;
}
[data-theme="dark"] {
  --brand-soft: color-mix(in srgb, var(--brand) 30%, black);
  --text: #f4f4f4;
}

Comment vérifier le bon fonctionnement : un seul fichier de variables suffit à basculer entre thèmes, sans recompilation.

Étape 6 : animer avec View Transitions API

L’API View Transitions (Chrome 111+, Safari 18+, Firefox derrière flag début 2026) anime de manière fluide les changements d’état d’une page, y compris en SPA et désormais en MPA via @view-transition.

// Transition sur changement d'état
if (document.startViewTransition) {
  document.startViewTransition(() => {
    document.querySelector('.panel').classList.toggle('open');
  });
}
/* Personnalisation */
::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: .35s;
  animation-timing-function: cubic-bezier(.2,.7,.2,1);
}

Le signal : le passage entre la liste produits et la fiche produit fluidifie, sans bibliothèque tierce ni framework lourd. Pour étoffer le tableau sur la stack front, voyez nos tutoriels développement web.

Étape 7 : optimiser performance et accessibilité

Une UI moderne reste inutile si elle rame ou exclut les utilisateurs. Activez loading= »lazy » sur les images sous la ligne de flottaison, fetchpriority= »high » sur le LCP, decoding= »async ». Préchargez les polices critiques avec rel= »preload » et la stratégie font-display: swap. Servez les images en AVIF ou WebP avec un fallback <picture>.

Côté accessibilité : aria-label seulement quand le texte visible manque, focus visible avec :focus-visible, contraste minimum 4.5:1 vérifié via les DevTools. Testez avec NVDA ou VoiceOver. Le signal : Lighthouse Accessibility ≥ 95 et un utilisateur de Sicap Liberté navigue au clavier sans piège visuel.

Étape 8 : structurer le projet et industrialiser

Adoptez une architecture CSS prévisible : ITCSS, BEM ou CUBE CSS au choix, mais une seule convention dans le projet. Posez Stylelint avec stylelint-config-standard et un Prettier pour la cohérence. Côté HTML, html-validate en CI bloque les régressions. Versionnez les tokens (couleurs, espacements, typographies) dans un design-tokens.json consommé par CSS et JS.

Le signal final : un nouveau développeur arrivé à Almadies clone le repo, lance npm install et obtient en 5 minutes un environnement fonctionnel avec lint, format et tests visuels (Playwright ou Storybook). Vous publiez ensuite des composants HTML/CSS modernes, accessibles et performants, sans dépendre d’un framework JS lourd. Pour mettre en pratique côté blog technique, parcourez nos tutoriels du blog.

Étape 9 : tester sur les vrais réseaux ouest-africains

Les Core Web Vitals tombent vite quand un utilisateur de Bamako charge votre site sur une 3G fluctuante. Ouvrez DevTools, onglet Network, profil « Slow 4G », puis Performance pour mesurer LCP, INP et CLS. Visez LCP < 2,5 s, INP < 200 ms, CLS < 0,1. Lancez aussi PageSpeed Insights pour obtenir les CrUX réels collectés sur Chrome.

Si le LCP est trop lent, l’image hero ou la police custom sont les coupables habituels. Convertissez l’image en AVIF, dimensionnez-la avec width et height pour bloquer le CLS, préchargez-la, et limitez les polices à deux graisses maximum. Validation pratique : un test sur un Tecno Spark à Lomé en 4G fluctuante affiche le contenu principal en moins de 3 secondes.

Étape 10 : surveiller la dette HTML et CSS

Un projet qui tourne pendant deux ans accumule des règles mortes et des id orphelins. Programmez une fois par trimestre un audit avec PurgeCSS pour repérer les sélecteurs jamais utilisés, et axe-core ou pa11y-ci en intégration continue pour traquer les régressions d’accessibilité. Tenez un journal CHANGELOG des breakages volontaires (ex : passage de px à rem) pour que les équipes à Yopougon et Cotonou suivent.

Le signal final : votre bundle CSS de production reste sous 60 ko gzip, votre HTML passe la validation W3C sur 100 % des pages échantillonnées, et chaque pull request affiche les diffs de Lighthouse en commentaire. À ce stade, la pile HTML+CSS moderne tient seule la majorité des besoins, et le JavaScript ne sert plus qu’aux interactions vraiment dynamiques.

Annexe : checklist HTML/CSS avant mise en production

Avant chaque déploiement, parcourez cette liste courte : doctype HTML5 présent, lang correct, meta viewport sans user-scalable=no, title et description renseignés, balises Open Graph remplies pour le partage WhatsApp et LinkedIn, favicon en SVG plus fallback PNG, robots.txt et sitemap référencés, CSP et HSTS configurés côté serveur. Validez ensuite avec le validateur W3C, axe DevTools et Lighthouse en mode mobile.

Côté CSS, vérifiez que prefers-reduced-motion désactive les animations longues, que prefers-color-scheme bascule le thème, et qu’aucune ressource bloquante ne s’ajoute en head sans média ni preload. Validation pratique : un déploiement en pré-production à Sandaga passe les portes qualité en moins de 10 minutes, sans alerte rouge sur Lighthouse ni axe. Vous gardez ainsi un site moderne, sobre, accessible et durable, sans dépendre des modes du moment.

Bonus : éviter les pièges classiques en 2026

Trois erreurs reviennent souvent dans les projets Dakar-Abidjan. La première : empiler vingt librairies UI quand HTML+CSS+un peu de Web Components suffit. La deuxième : ignorer prefers-reduced-data ou la 3G locale et livrer un bundle de 2 Mo. La troisième : confier le style à un framework lourd alors que les Cascade Layers (@layer base, components, utilities) règlent proprement la spécificité sans hack !important. Documentez ces choix dans le README pour que les nouveaux arrivants ne reviennent pas en arrière.

Le signal final : à la revue trimestrielle, votre dette CSS reste sous 5 % du backlog total, et chaque nouvelle feature intègre par défaut les bonnes pratiques modernes. C’est cette discipline, plus que les nouveautés du moment, qui distingue un site bien tenu d’un site qui s’effondre dès qu’on y ajoute une page.

Récapitulatif rapide à coller dans le wiki d’équipe

Sémantique d’abord, Grid pour le layout, Flexbox pour l’alignement, container queries pour les composants réutilisables, :has() pour piloter les états sans JS, custom properties + color-mix() pour le thème, View Transitions pour les changements d’écran, Lighthouse en CI pour mesurer. Cette boucle courte fait passer une équipe junior de Plateau au niveau d’une équipe expérimentée en quelques semaines. Le signal : vos prochains projets démarrent plus vite et se maintiennent plus longtemps.

مشاركة