Anaïs Sparesotto
Web · FrontendDébutant≈ 2h30 · 7 chapitres

Introduction à HTML et CSS

Structurer une page avec HTML sémantique, la mettre en page avec Flexbox et Grid, la rendre responsive et accessible. Les bases solides du web moderne.

À la fin du cours, tu sais

  • Écrire une structure HTML5 sémantique propre
  • Comprendre la cascade et la spécificité CSS
  • Maîtriser Flexbox pour les layouts 1D
  • Maîtriser CSS Grid pour les layouts 2D
  • Concevoir une page responsive mobile-first
  • Intégrer l'accessibilité de base (contraste, focus, sémantique)

Prérequis

  • Savoir ouvrir un éditeur et un navigateur
  • Idéalement : avoir suivi le cours « Bien démarrer son environnement »

Chapitre 1

Anatomie d'une page HTML5

Toute page web démarre par un squelette standard qui indique au navigateur comment interpréter le document.

Le squelette obligatoire

<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Mon profil</title>
  </head>
  <body>
    <header>
      <h1>Bonjour, c'est moi</h1>
    </header>
    <main>
      <!-- Contenu principal -->
    </main>
    <footer>
      <p>© 2026</p>
    </footer>
  </body>
</html>

Les éléments clés du <code>head</code>

  • <!DOCTYPE html> active le mode HTML5 du navigateur
  • <html lang="fr"> indique la langue (essentiel pour les lecteurs d'écran et le SEO)
  • <meta charset="UTF-8"> support des accents et emojis
  • <meta name="viewport"> indispensable pour le mobile
  • <title> affiché dans l'onglet et dans Google

Les balises sémantiques HTML5

  • <header> : en-tête de page ou de section
  • <nav> : navigation principale
  • <main> : contenu principal, un seul par page
  • <section> : regroupement thématique
  • <article> : contenu indépendant (article de blog, carte produit)
  • <aside> : contenu lié mais secondaire (encart, related)
  • <footer> : pied de page ou de section

Pourquoi la sémantique

Un <div> ne dit rien. Un <nav> dit « voici la navigation » au navigateur, au lecteur d'écran, à Google. Le SEO et l'accessibilité gagnent gratuitement quand tu choisis la bonne balise.

Chapitre 2

Texte, liens et médias

Le contenu repose sur quelques balises bien choisies. Pas besoin de tout connaître.

Titres et texte

  • <h1> à <h6> : hiérarchie de titres. Un seul h1 par page.
  • <p> : paragraphe
  • <strong> : emphase forte (sémantique). Pas <b>
  • <em> : emphase légère. Pas <i>
  • <ul> / <ol> / <li> : listes

Liens

<!-- Lien interne -->
<a href="/contact">Nous contacter</a>

<!-- Lien externe : noopener noreferrer pour la sécurité -->
<a href="https://example.fr" target="_blank" rel="noopener noreferrer">
  Site externe
</a>

Pas de « Cliquez ici »

Le texte du lien doit décrire la destination, pas l'action. Un lecteur d'écran qui liste les liens hors contexte verra « Cliquez ici, Cliquez ici, Cliquez ici ». Préfère « Lire l'article complet ».

Images

<!-- Image porteuse de sens : alt descriptif -->
<img src="/avatar.jpg" alt="Photo d'Anaïs souriante" />

<!-- Image purement décorative : alt vide -->
<img src="/separateur.svg" alt="" />

<!-- Lazy loading pour les images hors écran -->
<img src="/photo.jpg" alt="..." loading="lazy" />

alt est obligatoire. alt="" (vide) signale au lecteur d'écran d'ignorer l'image décorative. Sans alt, le lecteur d'écran lit le nom du fichier, c'est catastrophique.

Chapitre 3

Formulaires accessibles

Un formulaire utilisable, c'est d'abord des labels associés aux inputs. Le reste suit.

Le pattern de base

<label for="email">Adresse e-mail</label>
<input
  id="email"
  type="email"
  name="email"
  autocomplete="email"
  required
  aria-describedby="email-help"
/>
<p id="email-help" class="help">
  On ne partagera jamais ton email.
</p>

Les attributs essentiels

  • for du label = id de l'input : obligatoire
  • type="email", tel", number", date" : clavier adapté sur mobile, validation native
  • autocomplete : aide les password managers et l'autofill
  • required : champ obligatoire
  • aria-describedby : lie un texte d'aide à l'input

Grouper plusieurs champs liés

<fieldset>
  <legend>Préférences de contact</legend>

  <label>
    <input type="radio" name="contact" value="email" />
    Email
  </label>

  <label>
    <input type="radio" name="contact" value="telephone" />
    Téléphone
  </label>
</fieldset>

Jamais outline: none sans remplacement

Ne supprime jamais l'outline du focus sans la remplacer par un autre style visible. Les personnes qui naviguent au clavier ont besoin de voir où elles en sont.

Chapitre 4

CSS : sélecteurs, cascade, spécificité

CSS applique des styles via des sélecteurs, avec une logique de priorité. Comprendre ces règles évite 90 % des problèmes « mon CSS ne s'applique pas ».

Les types de sélecteurs

/* Par tag */
p { color: blue; }

/* Par classe (le plus utilisé) */
.card { padding: 1rem; }

/* Par id (rare, trop spécifique) */
#header { background: white; }

/* Par attribut */
input[type="email"] { border-color: green; }

/* Pseudo-classes */
a:hover { text-decoration: underline; }
button:focus-visible { outline: 2px solid currentColor; }

/* Pseudo-éléments */
p::first-letter { font-size: 2em; }

La spécificité

Quand deux règles s'appliquent au même élément, la plus spécifique gagne. Ordre de priorité :

  1. !important (à éviter, dernier recours)
  2. Style inline (style="...")
  3. ID (#header)
  4. Classe / attribut / pseudo-classe (.card, :hover)
  5. Tag (p, div)

Éviter !important

Si tu as besoin d'!important pour faire passer ton style, c'est souvent qu'il y a un sélecteur trop fort ailleurs. Préfère ajouter une classe plus précise. !important en cascade dans une équipe devient vite ingérable.

Les sélecteurs modernes utiles

/* :has() : styler un parent selon ses enfants (depuis 2023) */
.card:has(img) {
  padding-block: 1rem;
}

/* :is() / :where() : grouper sans répéter */
:is(h1, h2, h3) {
  font-family: 'DM Serif Display', serif;
}

/* :focus-visible : focus visible uniquement clavier */
button:focus-visible {
  outline: 2px solid var(--accent);
}

/* :not() : exclusion */
.btn:not(.btn-primary) {
  background: transparent;
}

Chapitre 5

Box Model, Flexbox, Grid

Tout élément HTML est une boîte. Le layout moderne utilise Flexbox (1D) ou Grid (2D). On n'utilise plus les floats pour le layout en 2025.

Box Model

Une boîte CSS = content + padding + border + margin. Par défaut, la largeur d'un élément ne compte que le content, ce qui rend les calculs pénibles.

Le réflexe universel : box-sizing global
*, *::before, *::after {
  box-sizing: border-box;
}

Avec border-box, width: 200px inclut padding et border. Beaucoup plus intuitif.

Flexbox : layouts 1D

/* Une barre de navigation : items alignés horizontalement */
.nav {
  display: flex;
  gap: 1.5rem;
  align-items: center;
  justify-content: space-between;
}

/* Une grille de tags qui s'enroule */
.tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

/* Centrer parfaitement n'importe quoi */
.centre {
  display: flex;
  align-items: center;
  justify-content: center;
}

Grid : layouts 2D

/* Un layout sidebar + contenu */
.app {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 2rem;
}

/* Une grille de cartes responsive */
.cartes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 1.5rem;
}

gap remplace les margins

Avant : margin-right: 1rem sur chaque item, puis &:last-child { margin-right: 0 }. Aujourd'hui : gap: 1rem sur le parent, symétrique, simple. Marche en Flex et Grid.

Chapitre 6

Responsive moderne et variables CSS

On conçoit mobile-first (le mobile par défaut, on adapte vers le grand écran). Et on utilise des variables CSS pour éviter de répéter ses tokens.

Media queries (mobile-first)

/* Mobile par défaut */
.layout {
  padding: 1rem;
}

/* Tablette et au-dessus */
@media (min-width: 48rem) {
  .layout {
    padding: 2rem;
  }
}

/* Desktop */
@media (min-width: 80rem) {
  .layout {
    max-width: 72rem;
    margin-inline: auto;
  }
}

Container queries (depuis 2023)

Un composant s'adapte à la taille de son conteneur, pas du viewport. Indispensable quand le même composant vit dans plusieurs contextes (sidebar étroite + zone principale large).

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

@container (min-width: 30rem) {
  .card .layout {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }
}

Variables CSS (custom properties)

:root {
  --color-text: #1a1523;
  --color-accent: #e86b2c;
  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --radius: 0.75rem;
}

.btn {
  background: var(--color-accent);
  padding: var(--space-1) var(--space-2);
  border-radius: var(--radius);
  color: white;
}

Thèmes sombres en 1 ligne

Avec prefers-color-scheme + variables, tu fais un dark mode en 5 lignes : redéfinis tes --color-* dans @media (prefers-color-scheme: dark) { :root { ... } }. Tout ton site bascule.

Unités fluides

/* Tailles qui s'adaptent au viewport entre un min et un max */
h1 {
  font-size: clamp(1.5rem, 4vw, 3rem);
}

.container {
  padding-inline: clamp(1rem, 5vw, 4rem);
}

Chapitre 7

Accessibilité et bonnes pratiques

L'accessibilité fait partie de la qualité du code, pas d'une option. Quelques réflexes couvrent 80 % des besoins.

Les bases à intégrer

  • HTML sémantique d'abord : un <button> est nativement accessible, un <div onclick> non
  • Contraste minimum 4.5:1 pour le texte courant (WCAG AA)
  • Focus toujours visible : ne jamais supprimer l'outline sans remplacement
  • Navigation clavier : Tab, Enter, Échap doivent fonctionner partout
  • Hiérarchie de titres cohérente : h1h2h3, pas de saut

Quelques attributs ARIA utiles

  • aria-label="..." : nom accessible si pas de texte visible (icône-bouton)
  • aria-describedby="id" : aide complémentaire (texte d'aide d'un input)
  • aria-current="page" : lien actif dans une nav
  • aria-hidden="true" : cacher du lecteur d'écran (icône décorative)

HTML d'abord, ARIA en dernier

Les attributs ARIA sont une réparation. Si tu peux exprimer la sémantique en HTML pur, fais-le. <nav> > <div role="navigation">. <button> > <div role="button">.

Tester son accessibilité

  • Naviguer ta page uniquement au clavier (Tab, Shift+Tab, Enter, Échap)
  • Lancer un audit Lighthouse (panneau Accessibility) dans les DevTools
  • Tester avec un lecteur d'écran (VoiceOver sur Mac, NVDA sur Windows)
  • Zoomer à 200 % et vérifier que tout reste utilisable

🛠️ Exercice optionnel

Construire une page profil utilisateur

Tu vas créer une page profil simple, avec une vraie structure HTML, du CSS moderne, et une attention à l'accessibilité. Tout en un seul fichier index.html + style.css.

Ta mission

  1. Structure HTML : header (nom + rôle), main avec sections À propos, Projets, aside avec contact, footer.
  2. Image : avatar avec alt descriptif.
  3. Layout Grid : sidebar (contact) + contenu principal sur desktop, empilés sur mobile.
  4. Liste de projets en Flexbox avec gap et flex-wrap.
  5. Variables CSS : 4 couleurs et 3 espacements dans :root.
  6. Responsive : passe de 1 colonne (mobile) à 2 colonnes (≥ 48rem).
  7. Focus visible et contrastes vérifiés (4.5:1 minimum).

Tu bloques ? Des indices, à dévoiler quand tu en as besoin.

Indice 1

Indice masqué.

Indice 2

Indice masqué.

Indice 3

Indice masqué.

✅ QCM de fin de cours

Teste tes acquis

10 questions, plusieurs réponses parfois possibles. Coche tout ce qui te semble juste, puis valide pour voir ton score et les explications.

  1. 1

    Quelle balise pour le contenu principal d'une page ?

  2. 2

    À quoi sert <meta name="viewport"> ?

  3. 3

    Quelle est la spécificité la plus forte (hors !important) ?

  4. 4

    Bonne pratique pour une image purement décorative ?

  5. 5

    Pour aligner des items sur un seul axe (horizontal ou vertical), tu utilises...

  6. 6

    Le remplaçant moderne des margins entre items Flexbox / Grid ?

  7. 7

    Une container query est déclenchée par quoi ?

  8. 8

    Comment associer correctement un <label> à un <input> ?

  9. 9

    Quel sélecteur CSS permet de styler un parent selon ses enfants ?

  10. 10

    Pourquoi éviter outline: none sur :focus ?

Tu peux laisser des questions sans réponse, elles compteront comme fausses.

Tu veux ce cours pour ton équipe ?

Je peux adapter et animer ce cours pour tes formateur·ices ou tes apprenant·es, en présentiel ou en distanciel. Parlons-en pendant l'audit gratuit.

Réserver un audit gratuit →