Module 1 : Le Web

Exercices Pratiques

Mettez la main à la pâte avec des exercices interactifs pour consolider vos acquis.

30 min
Version Audio
Intermédiaire
📝

PHASE 1.4 : EXERCICES PRATIQUES

Évaluation Complète - Avec Corrections Détaillées

📋 PARTIE 1 : QUESTIONS DE COURS (Réponse Libre - 30 pts)

Section A : Histoire du Web (10 questions)

1.

Qui a inventé le World Wide Web et en quelle année ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Tim Berners-Lee a inventé le World Wide Web en 1989 (au CERN). La première page web a été mise en ligne en 1991.

Détail : Berners-Lee a proposé le système en mars 1989, et le premier site web (info.cern.ch) a été lancé le 6 août 1991.

2.

Quel a été le premier navigateur graphique et qui l'a créé ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Mosaic a été le premier navigateur graphique, créé par Marc Andreessen et Eric Bina en 1993 (National Center for Supercomputing Applications - NCSA).

Détail : Mosaic a été le premier navigateur à afficher des images intégrées au texte. Andreessen a ensuite fondé Netscape.

3.

Pourquoi le projet "Phoenix" a-t-il été renommé "Firefox" ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Le projet a d'abord été nommé Phoenix, puis Firebird avant de devenir Firefox en 2004. Les changements de nom étaient dus à des conflits de marques avec d'autres projets (Phoenix Technologies, Firebird Database).

Détail : Firefox signifie "panda roux" (animal). Le nom a été choisi pour son côté "rapide et agile".

4.

Quelle a été l'innovation majeure de Google Chrome lors de son lancement en 2008 ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : L'innovation majeure de Chrome était son moteur JavaScript V8, qui a révolutionné la performance du JavaScript en le compilant en code machine (JIT - Just-In-Time compilation).

Détail : Chrome a aussi introduit le sandboxing (isolation des onglets) pour la sécurité, et a popularisé l'interface minimaliste "omnibox".

5.

Quelle est la date de sortie de Firefox 1.0 ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Firefox 1.0 est sorti le 9 novembre 2004.

Détail : Il s'agissait d'une version stable et aboutie après plusieurs années de développement (précédée par Firefox 0.8, 0.9, 0.10, etc.). Il représentait une alternative crédible à Internet Explorer.

6.

Pourquoi Microsoft a-t-il abandonné son moteur Chakra pour adopter Chromium ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Microsoft a abandonné Chakra pour Chromium en 2018-2020 pour plusieurs raisons :

  • Compatibilité : Les sites étaient de plus en plus optimisés pour Chromium.
  • Coût de développement : Maintenir un moteur rival de V8 coûtait très cher.
  • Écosystème : Bénéficier des contributions open-source de Chromium.
  • Standards : Suivre plus facilement les évolutions du Web.

Détail : Edge Chromium est sorti en janvier 2020. Microsoft contribue désormais activement à Chromium.

7.

Qui a créé Deno et pourquoi ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Ryan Dahl, le créateur de Node.js, a créé Deno en 2018-2020 pour corriger les défauts de Node.js :

  • Sécurité : Deno est sécurisé par défaut (nécessite des permissions explicites).
  • TypeScript : Support natif de TypeScript.
  • ES Modules : Support moderne des import/export.
  • Package Management : Pas de package.json ni de node_modules, il utilise des URLs.

Détail : Deno signifie "anagramme de Node". Il utilise le moteur V8 et est écrit en Rust.

8.

Quelle est la différence entre Netscape Navigator et Internet Explorer dans les années 90 ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse :

  • Netscape Navigator : Le navigateur dominant au début des années 90 (1994-1997). Payant, avec des fonctionnalités avancées (cookies, JavaScript, SSL).
  • Internet Explorer : Lancé en 1995 par Microsoft, gratuit et intégré à Windows. A gagné la guerre des navigateurs grâce à son intégration système et sa gratuité.

Détail : Netscape a été racheté par AOL en 1998 et son code source a donné naissance au projet Mozilla, puis à Firefox.

9.

En quelle année Apple Safari a-t-il été lancé et quel moteur utilise-t-il ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Safari a été lancé en 2003 (pour Mac OS X Panther). Il utilise le moteur WebKit (qui a été développé à partir de KHTML).

Détail : WebKit est un moteur open-source qui a inspiré Blink (utilisé par Chrome et Edge). JavaScriptCore est le moteur JavaScript de Safari.

10.

Qu'est-ce que le projet Mozilla et pourquoi a-t-il été créé ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Le projet Mozilla a été créé en 1998 après que Netscape ait rendu public le code source de son navigateur. L'objectif était de développer un navigateur open-source pour rivaliser avec Internet Explorer.

Détail : Mozilla est une contraction de "Mosaic" et "Godzilla". La fondation Mozilla a été créée en 2003 pour gérer le projet et défendre un Web ouvert.

Section B : Architecture du Web (10 questions)

1.

Explique le modèle Client-Serveur avec une analogie concrète.

(Espace pour la réponse)
Voir la Correction ▼

Réponse : Le modèle Client-Serveur est comme un restaurant :

  • Le client = Toi (tu commandes un plat).
  • Le serveur = Le cuisinier (il prépare le plat).
  • La commande = La requête HTTP (tu demandes une page).
  • Le plat = La réponse HTTP (la page servie).

Techniquement : Le client (navigateur) envoie des requêtes au serveur (ordinateur distant) qui les traite et renvoie des réponses via des protocoles (HTTP).

2.

Quelle est la différence entre HTTP et HTTPS ?

(Espace pour la réponse)
Voir la Correction ▼

Réponse : HTTPS = HTTP + SSL/TLS (chiffrement).

  • HTTP : Les données sont transmises en clair (lisibles en route).
  • HTTPS : Les données sont chiffrées (confidentialité, intégrité, authentification).

Détail : HTTPS utilise un certificat numérique pour authentifier le serveur et établir une clé de session symétrique.

3.

Quels sont les codes de statut HTTP des familles 2xx, 3xx, 4xx et 5xx ? Donne un exemple pour chaque.

(Espace pour la réponse)
Voir la Correction ▼
  • 2xx (Succès) : 200 OK (requête réussie).
  • 3xx (Redirection) : 301 Moved Permanently (ressource déplacée).
  • 4xx (Erreur client) : 404 Not Found (ressource introuvable).
  • 5xx (Erreur serveur) : 500 Internal Server Error (erreur générique).

Autres exemples : 201 Created, 302 Found, 403 Forbidden, 503 Service Unavailable.

4.

Comment fonctionne la résolution DNS ? Détaille chaque étape.

(Espace pour la réponse)
Voir la Correction ▼

Étapes :

  1. Cache du navigateur : Vérifie si l'IP est déjà en cache localement.
  2. Cache du système (OS) : Vérifie le cache du système d'exploitation.
  3. Résolveur DNS : Le système interroge un résolveur DNS (ex: 8.8.8.8).
  4. Root Servers : Le résolveur interroge un serveur racine pour trouver le TLD (.com).
  5. TLD Servers : Le résolveur interroge le serveur TLD (.com) pour trouver le serveur autoritaire de "exemple.com".
  6. Autoritative Servers : Le résolveur interroge le serveur autoritaire pour obtenir l'IP (A record).
  7. Résultat : L'IP est retournée au navigateur et mise en cache.

Détail : Le DNS utilise UDP (port 53) pour la plupart des requêtes pour sa rapidité.

5.

Qu'est-ce qu'un CDN et à quoi sert-il ?

(Espace pour la réponse)
Voir la Correction ▼

Définition : Un CDN (Content Delivery Network) est un réseau de serveurs distribués géographiquement pour accélérer la livraison de contenu web.

Utilité :

  • Performance : Réduction de la latence (serveur proche de l'utilisateur).
  • Scalabilité : Absorption des pics de trafic.
  • Sécurité : Protection DDoS, WAF.
  • Disponibilité : Redondance mondiale.

Exemples : Cloudflare, Akamai, Fastly, Amazon CloudFront.

6.

Quelle est la différence entre TCP et UDP ?

(Espace pour la réponse)
Voir la Correction ▼
Caractéristique TCP UDP
Fiabilité ✅ Garantie ❌ Non garanti
Ordre ✅ Garanti ❌ Non garanti
Connexion ✅ Orienté connexion ❌ Sans connexion
Vitesse Plus lent Plus rapide
Utilisation HTTP, HTTPS, FTP, SSH DNS, VoIP, Streaming, Jeux

Détail : TCP garantit la livraison des paquets (retransmission en cas de perte), UDP ne le fait pas.

7.

Qu'est-ce que le TTFB (Time To First Byte) et pourquoi est-il important ?

(Espace pour la réponse)
Voir la Correction ▼

Définition : Le TTFB est le temps entre l'envoi de la requête HTTP et la réception du premier octet de la réponse.

Importance : Il mesure la réactivité du serveur. Un TTFB élevé indique un serveur lent, un réseau congesté ou une application mal optimisée.

Objectif : Idéalement < 200ms. Il est influencé par : DNS, TCP, TLS, temps de traitement serveur.

8.

Explique le "3-way handshake" de TCP.

(Espace pour la réponse)
Voir la Correction ▼

Étapes :

  1. SYN : Le client envoie un paquet SYN (Synchronize) avec un numéro de séquence aléatoire.
  2. SYN-ACK : Le serveur répond avec SYN-ACK (accuse réception du SYN + envoie son propre SYN).
  3. ACK : Le client envoie ACK pour confirmer la réception du SYN-ACK.

Détail : La connexion est établie ! C'est comme un appel téléphonique : "Allô ?" → "Allô ?" → "Oui, je t'entends".

9.

Quelle est la différence entre HTTP/1.1 et HTTP/2 ?

(Espace pour la réponse)
Voir la Correction ▼
  • HTTP/1.1 : Requêtes séquentielles (une par connexion), en-têtes non compressés, textuel.
  • HTTP/2 : Multiplexage (plusieurs requêtes simultanées sur une connexion), compression des en-têtes (HPACK), binaire, Server Push.

Détail : HTTP/2 réduit considérablement la latence et est adopté par environ 60% des sites en 2026.

10.

Qu'est-ce que QUIC et en quoi améliore-t-il HTTP ?

(Espace pour la réponse)
Voir la Correction ▼

Définition : QUIC (Quick UDP Internet Connections) est un protocole de transport développé par Google, utilisé comme base pour HTTP/3.

Améliorations :

  • Réduction de la latence : Pas de handshake TCP (0-RTT).
  • Élimination du Head-of-Line Blocking : Les paquets perdus ne bloquent plus les autres flux.
  • Meilleure mobilité : Changement de réseau sans interrompre la connexion.
  • Chiffrement intégré : Sécurisé par défaut.

Détail : QUIC utilise UDP (au lieu de TCP) avec des mécanismes de contrôle de congestion au niveau application.

Section C : Technologies du Web (10 questions)

1.

Cite 5 balises sémantiques HTML5 et explique leur rôle.

(Espace pour la réponse)
Voir la Correction ▼
  • <header> : En-tête de page/section (logo, navigation).
  • <nav> : Navigation principale.
  • <main> : Contenu principal (unique par page).
  • <article> : Contenu indépendant (article de blog).
  • <footer> : Pied de page (copyright, liens).

Détail : Les balises sémantiques améliorent le SEO et l'accessibilité.

2.

Quelle est la différence entre localStorage et sessionStorage ?

(Espace pour la réponse)
Voir la Correction ▼
  • localStorage : Persistant (données conservées après fermeture du navigateur). Limité ~5-10 MB par domaine.
  • sessionStorage : Par onglet (données supprimées à la fermeture de l'onglet).

Détail : Les deux sont des stockages clé-valeur (string) accessibles en JavaScript.

3.

À quoi servent les Service Workers ?

(Espace pour la réponse)
Voir la Correction ▼

Définition : Un Service Worker est un proxy réseau qui s'exécute en arrière-plan.

Usages :

  • Hors-ligne : Intercepter les requêtes et servir des fichiers en cache.
  • Push notifications : Envoyer des notifications même quand la page est fermée.
  • Mises à jour en arrière-plan : Précharger des ressources.

Détail : Les Service Workers sont la base des PWA (Progressive Web Apps).

4.

Quelle est la différence entre display: flex et display: grid ?

(Espace pour la réponse)
Voir la Correction ▼
  • Flexbox : Unidimensionnel (ligne OU colonne). Idéal pour les composants (navigation, cartes).
  • CSS Grid : Bidimensionnel (lignes ET colonnes). Idéal pour la mise en page globale (structure de la page).

Détail : Flexbox est plus flexible pour le contenu dynamique, Grid est plus puissant pour les mises en page complexes.

5.

Explique le concept de "Mobile-First" avec les Media Queries.

(Espace pour la réponse)
Voir la Correction ▼

Mobile-First : Commencer par les styles mobile (par défaut), puis utiliser des Media Queries avec min-width pour ajouter des styles pour les écrans plus grands.

/* Styles par défaut (mobile) */
.container { width: 100%; padding: 10px; }

/* Tablette */
@media (min-width: 768px) {
  .container { max-width: 750px; margin: 0 auto; }
}

/* Desktop */
@media (min-width: 1025px) {
  .container { max-width: 1000px; }
}

6.

Quelle est la différence entre em et rem en CSS ?

(Espace pour la réponse)
Voir la Correction ▼
  • em : Relatif à la taille de police du parent. Ex: 1.5em = 1.5 × taille de police du parent.
  • rem : Relatif à la taille de police de l'élément racine (html). Ex: 1.5rem = 1.5 × taille de police racine (généralement 16px).

Détail : rem est plus prévisible et recommandé pour la plupart des cas. em est utile pour les composants imbriqués.

7.

Que sont les Web Workers et quand les utiliser ?

(Espace pour la réponse)
Voir la Correction ▼

Définition : Les Web Workers permettent d'exécuter du JavaScript en arrière-plan (thread séparé) sans bloquer l'interface utilisateur.

Quand les utiliser :

  • Calculs intensifs (cryptographie, algorithmes).
  • Traitement d'images (filtres, compression).
  • Parsing de gros fichiers (JSON, CSV).

Détail : Les Workers n'ont pas accès au DOM, ils communiquent via postMessage().

8.

Explique la différence entre let, const et var en JavaScript.

(Espace pour la réponse)
Voir la Correction ▼
  • let : Variable mutable, scope de bloc. Peut être réassignée.
  • const : Constante, scope de bloc. Ne peut pas être réassignée (mais les objets peuvent être modifiés).
  • var : Ancien, scope de fonction. Hoisting (déclarée en haut). À éviter.
// ✅ Préférer
let age = 30;
const name = 'Jean';

// ❌ Éviter
var oldStyle = 'obsolète';

9.

Qu'est-ce que CORS et pourquoi est-ce important ?

(Espace pour la réponse)
Voir la Correction ▼

Définition : CORS (Cross-Origin Resource Sharing) est un mécanisme de sécurité qui permet à un navigateur d'autoriser des requêtes cross-origin (domaine différent).

Pourquoi c'est important :

  • Sécurité : Empêche les sites malveillants d'accéder aux données d'un autre site (Same-Origin Policy).
  • APIs : Permet aux applications frontend d'appeler des APIs sur d'autres domaines (ex: mon-frontend.com → api.mon-backend.com).

Détail : Le serveur doit renvoyer les en-têtes CORS appropriés (Access-Control-Allow-Origin).

10.

Cite les 3 Core Web Vitals et leurs objectifs.

(Espace pour la réponse)
Voir la Correction ▼
  • LCP (Largest Contentful Paint) : Temps de chargement du contenu principal. Objectif : < 2.5s.
  • FID (First Input Delay) : Réactivité aux interactions. Objectif : < 100ms.
  • CLS (Cumulative Layout Shift) : Stabilité visuelle. Objectif : < 0.1.

Détail : Ces métriques sont utilisées par Google comme signal de ranking SEO.

🎯 PARTIE 2 : QCM (Choix Multiples - 30 pts)

Sélectionnez la bonne réponse pour chaque question. Les réponses correctes sont surlignées en vert.

Section A : Histoire du Web (10 questions)

1. En quelle année le World Wide Web a-t-il été inventé ?

Voir la Correction ▼

✅ Réponse : A) 1989

Tim Berners-Lee a proposé le WWW en 1989 au CERN. Le premier site web a été mis en ligne en 1991.

2. Qui a créé le premier navigateur graphique (Mosaic) ?

Voir la Correction ▼

✅ Réponse : B) Marc Andreessen

Marc Andreessen et Eric Bina ont créé Mosaic en 1993. Andreessen a ensuite fondé Netscape.

3. Quel était le nom du projet qui a précédé Firefox ?

Voir la Correction ▼

✅ Réponse : B) Phoenix (puis Firebird)

Le projet a été nommé Phoenix, puis Firebird, avant de devenir Firefox en 2004 à cause de conflits de marques.

4. En quelle année Google Chrome a-t-il été lancé ?

Voir la Correction ▼

✅ Réponse : C) 2008

Chrome a été lancé en septembre 2008 avec un moteur JavaScript V8 révolutionnaire.

5. Quel moteur JavaScript utilise Google Chrome ?

Voir la Correction ▼

✅ Réponse : C) V8

V8 est le moteur JavaScript open-source de Google, utilisé par Chrome et Node.js.

6. Qui a créé JavaScript ?

Voir la Correction ▼

✅ Réponse : C) Brendan Eich

Brendan Eich a créé JavaScript en 10 jours en 1995 pour Netscape. Le langage s'appelait à l'origine Mocha, puis LiveScript.

7. En quelle année Microsoft Edge est-il passé à Chromium ?

Voir la Correction ▼

✅ Réponse : C) 2020

Edge Chromium est sorti en janvier 2020. Microsoft utilise désormais le moteur Blink (comme Chrome).

8. Quel est le moteur JavaScript de Safari ?

Voir la Correction ▼

✅ Réponse : C) JavaScriptCore

JavaScriptCore (aussi appelé Nitro) est le moteur JavaScript de Safari, basé sur WebKit.

9. Qui a créé Node.js ?

Voir la Correction ▼

✅ Réponse : B) Ryan Dahl

Ryan Dahl a créé Node.js en 2009, permettant d'exécuter JavaScript côté serveur.

10. En quelle année Bun 1.0 est-il sorti ?

Voir la Correction ▼

✅ Réponse : C) 2023

Bun 1.0 est sorti en septembre 2023. C'est un runtime JavaScript rapide écrit en Zig, créé par Jarred Sumner.

Section B : Architecture Web (10 questions)

1. Que signifie HTTP ?

Voir la Correction ▼

✅ Réponse : A) HyperText Transfer Protocol

HTTP est le protocole de communication du Web, utilisé pour les requêtes et réponses client-serveur.

2. Quel code HTTP signifie "Not Found" ?

Voir la Correction ▼

✅ Réponse : C) 404

404 Not Found signifie que la ressource demandée n'existe pas sur le serveur.

3. Quelle est la méthode HTTP idempotente ?

Voir la Correction ▼

✅ Réponse : C) GET (et DELETE, PUT)

GET est idempotent (lecture seule). DELETE est idempotent aussi (la première supprime, les suivantes ne font rien).

4. Que fait un CDN ?

Voir la Correction ▼

✅ Réponse : B) Distribue le contenu géographiquement

Un CDN copie le contenu sur des serveurs proches des utilisateurs pour réduire la latence.

5. Quel protocole est utilisé pour la résolution DNS ?

Voir la Correction ▼

✅ Réponse : C) UDP (port 53)

DNS utilise UDP pour sa rapidité, mais peut utiliser TCP pour les réponses volumineuses.

6. Quelle est la caractéristique de TCP ?

Voir la Correction ▼

✅ Réponse : C) Orienté connexion

TCP établit une connexion avant d'échanger des données (3-way handshake) et garantit la livraison.

7. Quel code HTTP signifie "Internal Server Error" ?

Voir la Correction ▼

✅ Réponse : C) 500

500 Internal Server Error est une erreur générique du serveur.

8. Quelle est la différence entre HTTP/1.1 et HTTP/2 ?

Voir la Correction ▼

✅ Réponse : B) HTTP/2 permet le multiplexage

HTTP/2 permet plusieurs requêtes simultanées sur une même connexion, réduisant la latence.

9. Que signifie TTFB ?

Voir la Correction ▼

✅ Réponse : A) Time To First Byte

TTFB mesure la réactivité du serveur. Objectif : < 200ms.

10. QUIC est basé sur quel protocole ?

Voir la Correction ▼

✅ Réponse : B) UDP

QUIC est basé sur UDP pour éviter les latences de TCP. C'est la base de HTTP/3.

Section C : Technologies du Web (10 questions)

1. Quelle balise n'est PAS sémantique ?

Voir la Correction ▼

✅ Réponse : C) <div>

<div> est une balise générique sans valeur sémantique, contrairement à header, article et nav.

2. localStorage stocke les données jusqu'à :

Voir la Correction ▼

✅ Réponse : B) Fermeture du navigateur et C) Suppression explicite

localStorage est persistant. Les données ne sont supprimées que par l'utilisateur ou le code (clear/removeItem).

3. Service Worker permet de :

Voir la Correction ▼

✅ Réponse : B) Intercepter les requêtes réseau et D) Gérer les notifications push

Les Service Workers agissent comme un proxy réseau et permettent les notifications, mais n'ont pas accès au DOM.

4. Quelle est la différence entre Flexbox et Grid ?

Voir la Correction ▼

✅ Réponse : B) Grid est bidimensionnel

Flexbox est unidimensionnel (ligne ou colonne), Grid est bidimensionnel (lignes ET colonnes).

5. em est relatif à :

Voir la Correction ▼

✅ Réponse : B) La taille de police du parent

em est relatif au parent, rem est relatif à la racine (html).

6. Web Workers permettent de :

Voir la Correction ▼

✅ Réponse : A) Exécuter du JS en arrière-plan

Les Workers s'exécutent dans un thread séparé, sans accès au DOM.

7. const en JavaScript :

Voir la Correction ▼

✅ Réponse : B) Ne peut pas être réassigné

const crée une constante. La référence ne peut pas changer, mais le contenu d'un objet peut être modifié.

8. CORS est important pour :

Voir la Correction ▼

✅ Réponse : A) La sécurité des requêtes cross-origin

CORS permet de contrôler quels domaines peuvent accéder aux ressources du serveur.

9. LCP mesure :

Voir la Correction ▼

✅ Réponse : A) Le temps de chargement du contenu principal

LCP mesure le temps d'apparition du plus grand élément visible. Objectif : < 2.5s.

10. FID mesure :

Voir la Correction ▼

✅ Réponse : B) Le délai avant la première interaction

FID mesure la réactivité. Objectif : < 100ms.

🛠️ PARTIE 3 : EXERCICES PRATIQUES (40 pts)

Exercice 1 : Structure HTML (1h - 10 pts)

Objectif

Créez une page HTML sémantique.

Consignes :

  • Créez une page HTML avec un <header> contenant le titre et une navigation.
  • Un <main> avec un <article> (titre, date, contenu).
  • Un <aside> avec des liens associés.
  • Un <footer> avec copyright.
  • Utilisez des balises sémantiques appropriées.
  • Ajoutez des images avec <figure> et <figcaption>.
  • Créez un formulaire de contact avec validation HTML5.
Voir la Correction ▼
index.html - Correction Complète

<!DOCTYPE html>

<html lang="fr">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Mon Blog - Article</title>

<link rel="stylesheet" href="style.css">

</head>

<body>

<!-- ===== HEADER ===== -->

<header>

<h1>Mon Blog</h1>

<nav aria-label="Navigation principale">

<ul>

<li><a href="#" aria-current="page">Accueil</a></li>

<li><a href="#">Articles</a></li>

<li><a href="#">À propos</a></li>

<li><a href="#">Contact</a></li>

</ul>

</nav>

</header>

<!-- ===== MAIN ===== -->

<main>

<!-- Article -->

<article>

<header>

<h2>HTML5 : La révolution du Web</h2>

<p>Publié le <time datetime="2026-07-29">29 juillet 2026</time> par <span class="author">Jean Dupont</span></p>

</header>

<!-- Section 1 -->

<section>

<h3>Les nouvelles balises sémantiques</h3>

<p>HTML5 a introduit de nombreuses balises qui donnent du sens au contenu, comme <mark><article></mark>, <mark><section></mark> et <mark><nav></mark>. Elles améliorent le SEO et l'accessibilité.</p>

<figure>

<img src="html5-structure.png" alt="Structure sémantique d'une page HTML5" loading="lazy">

<figcaption>Exemple de structure sémantique avec HTML5</figcaption>

</figure>

</section>

<!-- Section 2 -->

<section>

<h3>Les APIs avancées</h3>

<p>HTML5 propose également des APIs puissantes : Web Storage, Service Workers, WebRTC, etc.</p>

</section>

<!-- Footer article -->

<footer>

<p>Catégorie : <a href="#">Développement Web</a></p>

<p>Mots-clés : <span class="tag">HTML5</span>, <span class="tag">Sémantique</span></p>

</footer>

</article>

<!-- Aside (sidebar) -->

<aside aria-labelledby="aside-title">

<h3 id="aside-title">Articles récents</h3>

<ul>

<li><a href="#">CSS3 : Le style moderne</a></li>

<li><a href="#">JavaScript : Le langage du Web</a></li>

<li><a href="#">Node.js : JavaScript côté serveur</a></li>

<li><a href="#">Les bases de React</a></li>

</ul>

</aside>

</main>

<!-- ===== FORMULAIRE ===== -->

<section aria-labelledby="form-title">

<h2 id="form-title">Contactez-nous</h2>

<form action="/submit" method="POST" novalidate>

<div class="form-group">

<label for="nom">Nom *</label>

<input type="text" id="nom" name="nom" required minlength="2" maxlength="50" placeholder="Jean Dupont" autocomplete="family-name">

</div>

<div class="form-group">

<label for="email">Email *</label>

<input type="email" id="email" name="email" required placeholder="jean@example.com" autocomplete="email">

</div>

<div class="form-group">

<label for="message">Message *</label>

<textarea id="message" name="message" required rows="5" maxlength="500" placeholder="Votre message..."></textarea>

</div>

<div class="form-group">

<label>

<input type="checkbox" name="newsletter" value="oui"> S'inscrire à la newsletter

</label>

</div>

<button type="submit">Envoyer</button>

<button type="reset">Effacer</button>

</form>

</section>

<!-- ===== FOOTER ===== -->

<footer>

<p>&copy; 2026 - Mon Blog. Tous droits réservés.</p>

<p><a href="#">Mentions légales</a> - <a href="#">Politique de confidentialité</a></p>

</footer>

</body>

</html>

Exercice 2 : CSS & Responsive (2h - 10 pts)

Objectif

Créez une page responsive avec CSS moderne.

Consignes :

  • Stylisez la page de l'exercice 1 avec une palette de couleurs (variables CSS).
  • Utilisez Flexbox pour la navigation et CSS Grid pour la mise en page.
  • Rendez la page responsive avec des Media Queries.
  • Ajoutez des animations au survol des liens.
  • Créez un mode sombre automatique.
Voir la Correction ▼
style.css - Correction Complète

/* ===== VARIABLES CSS ===== */

:root {

/* Couleurs principales */

--color-primary: #3498db;

--color-primary-dark: #2980b9;

--color-secondary: #2c3e50;

--color-text: #2c3e50;

--color-background: #f8f9fa;

--color-card: #ffffff;

--color-border: #e9ecef;

--color-link: #3498db;

--color-link-hover: #2980b9;

/* Polices */

--font-family: 'Inter', system-ui, -apple-system, sans-serif;

--font-size-base: 16px;

--font-size-large: 1.25rem;

/* Espacements */

--spacing-small: 0.5rem;

--spacing-medium: 1rem;

--spacing-large: 2rem;

/* Bordures */

--radius-small: 4px;

--radius-medium: 8px;

--radius-large: 16px;

/* Ombres */

--shadow-small: 0 1px 3px rgba(0,0,0,0.08);

--shadow-medium: 0 4px 12px rgba(0,0,0,0.1);

--shadow-large: 0 8px 24px rgba(0,0,0,0.12);

}

/* ===== MODE SOMBRE ===== */

@media (prefers-color-scheme: dark) {

:root {

--color-primary: #6c5ce7;

--color-primary-dark: #5a4bd1;

--color-secondary: #e0e0e0;

--color-text: #e0e0e0;

--color-background: #1a1a2e;

--color-card: #2a2a3e;

--color-border: #3a3a4e;

--color-link: #6c5ce7;

--color-link-hover: #5a4bd1;

--shadow-small: 0 1px 3px rgba(255,255,255,0.05);

--shadow-medium: 0 4px 12px rgba(255,255,255,0.08);

}

}

/* ===== RESET & BASE ===== */

*, *::before, *::after {

margin: 0;

padding: 0;

box-sizing: border-box;

}

body {

font-family: var(--font-family);

font-size: var(--font-size-base);

color: var(--color-text);

background: var(--color-background);

line-height: 1.6;

padding: var(--spacing-medium);

}

a {

color: var(--color-link);

text-decoration: none;

transition: color 0.3s ease;

}

a:hover {

color: var(--color-link-hover);

text-decoration: underline;

}

/* ===== HEADER ===== */

header {

background: var(--color-card);

padding: var(--spacing-medium) var(--spacing-large);

border-radius: var(--radius-medium);

box-shadow: var(--shadow-small);

margin-bottom: var(--spacing-large);

display: flex;

justify-content: space-between;

align-items: center;

flex-wrap: wrap;

gap: var(--spacing-medium);

}

header h1 {

font-size: 1.8rem;

color: var(--color-primary);

font-weight: 800;

}

nav ul {

display: flex;

gap: var(--spacing-medium);

list-style: none;

}

nav a {

padding: 0.5rem 1rem;

border-radius: var(--radius-small);

transition: background 0.3s ease, color 0.3s ease;

}

nav a:hover {

background: var(--color-primary);

color: white;

text-decoration: none;

}

/* ===== MAIN ===== */

main {

display: grid;

grid-template-columns: 2fr 1fr;

gap: var(--spacing-large);

max-width: 1200px;

margin: 0 auto;

}

article {

background: var(--color-card);

padding: var(--spacing-large);

border-radius: var(--radius-medium);

box-shadow: var(--shadow-small);

}

article h2 {

color: var(--color-secondary);

font-size: 1.8rem;

margin-bottom: var(--spacing-small);

}

article .author {

font-weight: 600;

color: var(--color-primary);

}

article section {

margin-top: var(--spacing-medium);

}

article h3 {

font-size: 1.3rem;

color: var(--color-secondary);

margin-bottom: var(--spacing-small);

}

article figure {

margin: var(--spacing-medium) 0;

text-align: center;

}

article figure img {

max-width: 100%;

border-radius: var(--radius-small);

}

article figcaption {

font-size: 0.9rem;

color: var(--color-text);

opacity: 0.7;

margin-top: var(--spacing-small);

}

article .tag {

display: inline-block;

background: var(--color-primary);

color: white;

padding: 0.2rem 0.8rem;

border-radius: var(--radius-small);

font-size: 0.8rem;

margin-right: 0.3rem;

}

aside {

background: var(--color-card);

padding: var(--spacing-large);

border-radius: var(--radius-medium);

box-shadow: var(--shadow-small);

align-self: start;

}

aside h3 {

color: var(--color-secondary);

margin-bottom: var(--spacing-medium);

}

aside ul {

list-style: none;

space-y: var(--spacing-small);

}

aside li {

padding: var(--spacing-small) 0;

border-bottom: 1px solid var(--color-border);

}

/* ===== FORMULAIRE ===== */

section form {

background: var(--color-card);

padding: var(--spacing-large);

border-radius: var(--radius-medium);

box-shadow: var(--shadow-small);

max-width: 600px;

margin: var(--spacing-large) auto;

}

.form-group {

margin-bottom: var(--spacing-medium);

}

.form-group label {

display: block;

font-weight: 600;

margin-bottom: 0.3rem;

}

.form-group input,

.form-group textarea {

width: 100%;

padding: 0.75rem;

border: 2px solid var(--color-border);

border-radius: var(--radius-small);

font-size: 1rem;

font-family: inherit;

transition: border-color 0.3s ease;

}

.form-group input:focus,

.form-group textarea:focus {

outline: none;

border-color: var(--color-primary);

}

.form-group input:valid {

border-color: #2ecc71;

}

.form-group input:invalid:not(:placeholder-shown) {

border-color: #e74c3c;

}

button[type="submit"] {

background: var(--color-primary);

color: white;

border: none;

padding: 0.75rem 2rem;

border-radius: var(--radius-small);

font-size: 1rem;

cursor: pointer;

transition: background 0.3s ease, transform 0.2s ease;

}

button[type="submit"]:hover {

background: var(--color-primary-dark);

transform: scale(1.02);

}

button[type="reset"] {

background: transparent;

color: var(--color-text);

border: 2px solid var(--color-border);

padding: 0.75rem 2rem;

border-radius: var(--radius-small);

cursor: pointer;

transition: all 0.3s ease;

}

button[type="reset"]:hover {

background: var(--color-border);

}

/* ===== FOOTER ===== */

footer {

text-align: center;

padding: var(--spacing-medium);

margin-top: var(--spacing-large);

border-top: 1px solid var(--color-border);

color: var(--color-text);

opacity: 0.7;

font-size: 0.9rem;

}

/* ===== MEDIA QUERIES (Mobile-First) ===== */

/* Tablette */

@media (max-width: 768px) {

main {

grid-template-columns: 1fr;

gap: var(--spacing-medium);

}

header {

flex-direction: column;

text-align: center;

}

nav ul {

justify-content: center;

flex-wrap: wrap;

}

}

/* Mobile */

@media (max-width: 480px) {

body { padding: var(--spacing-small); }

article, aside, section form {

padding: var(--spacing-medium);

}

article h2 { font-size: 1.4rem; }

header h1 { font-size: 1.4rem; }

nav a { padding: 0.3rem 0.7rem; }

}

Exercice 3 : JavaScript & DOM (2h - 10 pts)

Todo List

Créez une application de Todo List interactive avec JavaScript.

Consignes :

  • Créez une liste de tâches (Todo List) avec ajout, suppression et marquage "complétée".
  • Compteur de tâches restantes.
  • Utilisez localStorage pour persister les tâches.
  • Ajoutez la possibilité de filtrer les tâches (toutes, actives, terminées).
Voir la Correction ▼
todo.js - Correction Complète

// ===== MODÈLE =====

let todos = [];

let currentFilter = 'all';

// ===== DOM ELEMENTS =====

const form = document.getElementById('todo-form');

const input = document.getElementById('todo-input');

const list = document.getElementById('todo-list');

const counter = document.getElementById('todo-counter');

const filters = document.querySelectorAll('.filter-btn');

// ===== LOCALSTORAGE =====

function loadTodos() {

const stored = localStorage.getItem('todos');

if (stored) {

todos = JSON.parse(stored);

} else {

todos = [

{ id: 1, text: 'Apprendre HTML', completed: false },

{ id: 2, text: 'Apprendre CSS', completed: true },

{ id: 3, text: 'Apprendre JavaScript', completed: false }

];

}

}

function saveTodos() {

localStorage.setItem('todos', JSON.stringify(todos));

}

// ===== CRUD OPÉRATIONS =====

function addTodo(text) {

const todo = {

id: Date.now(),

text: text.trim(),

completed: false

};

todos.unshift(todo);

saveTodos();

render();

}

function deleteTodo(id) {

todos = todos.filter(todo => todo.id !== id);

saveTodos();

render();

}

function toggleTodo(id) {

const todo = todos.find(t => t.id === id);

if (todo) {

todo.completed = !todo.completed;

saveTodos();

render();

}

}

function updateTodoText(id, newText) {

const todo = todos.find(t => t.id === id);

if (todo) {

todo.text = newText.trim();

saveTodos();

render();

}

}

// ===== FILTRES =====

function getFilteredTodos() {

switch (currentFilter) {

case 'active':

return todos.filter(t => !t.completed);

case 'completed':

return todos.filter(t => t.completed);

default:

return todos;

}

}

// ===== RENDU =====

function render() {

const filtered = getFilteredTodos();

const activeCount = todos.filter(t => !t.completed).length;

// Mise à jour du compteur

counter.textContent = `${activeCount} tâche${activeCount > 1 ? 's' : ''} restante${activeCount > 1 ? 's' : ''}`;

// Rendu de la liste

if (filtered.length === 0) {

list.innerHTML = `

<li class="empty-message">

${todos.length === 0 ? 'Aucune tâche. Ajoutez-en une !' : 'Aucune tâche dans ce filtre.'}

</li>

`;

return;

}

list.innerHTML = filtered.map(todo => `

<li class="todo-item ${todo.completed ? 'completed' : ''}">

<input type="checkbox" class="todo-checkbox" data-id="${todo.id}" ${todo.completed ? 'checked' : ''}>

<span class="todo-text" data-id="${todo.id}">${todo.text}</span>

<div class="todo-actions">

<button class="edit-btn" data-id="${todo.id}">✏️</button>

<button class="delete-btn" data-id="${todo.id}">🗑️</button>

</div>

</li>

`).join('');

// Attacher les événements aux boutons

document.querySelectorAll('.delete-btn').forEach(btn => {

btn.addEventListener('click', () => deleteTodo(Number(btn.dataset.id)));

});

document.querySelectorAll('.todo-checkbox').forEach(cb => {

cb.addEventListener('change', () => toggleTodo(Number(cb.dataset.id)));

});

document.querySelectorAll('.edit-btn').forEach(btn => {

btn.addEventListener('click', () => {

const id = Number(btn.dataset.id);

const textSpan = document.querySelector(`.todo-text[data-id="${id}"]`);

const currentText = textSpan.textContent;

const newText = prompt('Modifier la tâche :', currentText);

if (newText && newText.trim()) {

updateTodoText(id, newText);

}

});

});

}

// ===== FILTRES UI =====

function setFilter(filter) {

currentFilter = filter;

filters.forEach(btn => {

btn.classList.toggle('active', btn.dataset.filter === filter);

});

render();

}

// ===== ÉVÉNEMENTS =====

form.addEventListener('submit', (e) => {

e.preventDefault();

const text = input.value.trim();

if (text) {

addTodo(text);

input.value = '';

input.focus();

}

});

filters.forEach(btn => {

btn.addEventListener('click', () => {

setFilter(btn.dataset.filter);

});

});

// ===== INITIALISATION =====

loadTodos();

setFilter('all');

Exercice 4 : API & Fetch (2h - 10 pts)

API REST

Interagissez avec une API REST publique (JSONPlaceholder).

Consignes :

  • Utilisez l'API publique JSONPlaceholder (https://jsonplaceholder.typicode.com/users).
  • Récupérez et affichez la liste des utilisateurs (nom, email, site web).
  • Ajoutez un formulaire pour créer un nouvel utilisateur (POST).
  • Gérez les erreurs et affichez un message de chargement.
Voir la Correction ▼
api.js - Correction Complète

// ===== CONSTANTES =====

const API_URL = 'https://jsonplaceholder.typicode.com/users';

const userList = document.getElementById('user-list');

const form = document.getElementById('user-form');

const loading = document.getElementById('loading');

const errorDiv = document.getElementById('error');

// ===== AFFICHAGE =====

function showLoading(show) {

loading.style.display = show ? 'block' : 'none';

}

function showError(message) {

errorDiv.textContent = message;

errorDiv.style.display = 'block';

setTimeout(() => {

errorDiv.style.display = 'none';

}, 5000);

}

function renderUsers(users) {

if (users.length === 0) {

userList.innerHTML = '<p class="empty">Aucun utilisateur trouvé.</p>';

return;

}

userList.innerHTML = users.map(user => `

<div class="user-card">

<h3>${user.name}</h3>

<p><strong>Email :</strong> ${user.email}</p>

<p><strong>Site web :</strong> ${user.website ? `<a href="https://${user.website}" target="_blank">${user.website}</a>` : 'N/A'}</p>

</div>

`).join('');

}

// ===== REQUÊTES API =====

async function fetchUsers() {

try {

showLoading(true);

const response = await fetch(API_URL);

if (!response.ok) {

throw new Error(`HTTP error! status: ${response.status}`);

}

const users = await response.json();

renderUsers(users);

} catch (error) {

showError('Erreur de chargement : ' + error.message);

userList.innerHTML = '<p class="error">Impossible de charger les utilisateurs.</p>';

} finally {

showLoading(false);

}

}

async function createUser(userData) {

try {

showLoading(true);

const response = await fetch(API_URL, {

method: 'POST',

headers: {

'Content-Type': 'application/json'

},

body: JSON.stringify(userData)

});

if (!response.ok) {

throw new Error(`HTTP error! status: ${response.status}`);

}

const newUser = await response.json();

showError('✅ Utilisateur créé avec succès ! (ID: ' + newUser.id + ')');

await fetchUsers(); // Rafraîchir la liste

} catch (error) {

showError('Erreur de création : ' + error.message);

} finally {

showLoading(false);

}

}

// ===== FORMULAIRE =====

form.addEventListener('submit', async (e) => {

e.preventDefault();

const formData = new FormData(form);

const userData = {

name: formData.get('name'),

email: formData.get('email'),

website: formData.get('website') || '',

username: formData.get('name').toLowerCase().replace(/\s/g, ''),

company: { name: 'Mon entreprise' }

};

await createUser(userData);

form.reset();

});

// ===== INITIALISATION =====

fetchUsers();

📊 BARÈME D'ÉVALUATION

Répartition des points

  • Questions de Cours (30 × 1)30 pts
  • QCM (30 × 1)30 pts
  • Exercice 1 (Structure HTML)10 pts
  • Exercice 2 (CSS & Responsive)10 pts
  • Exercice 3 (JS & DOM)10 pts
  • Exercice 4 (API & Fetch)10 pts
  • Total100 pts

Niveaux de compétence

🏆 ExpertMaîtrise parfaite
90-100
🚀 AvancéTrès solide
75-89
📈 IntermédiaireEn bonne voie
60-74
📚 DébutantÀ renforcer
40-59
🎯 FondamentauxReprendre les bases
< 40