Durée : entre 3h et 7h
La maquette desktop

La maquette Mobile

La maquette Mobile avec Navigation dépliée

Ce que l’on va construire
Ce chapitre est l’exercice de synthèse de tout ce que vous avez appris depuis le début du cours. Il n’y a plus d’étapes détaillées cette fois : c’est à vous de construire la page en autonomie, en mobilisant les briques déjà vues (structure sémantique, Flexbox, variables CSS, formulaire, tableau, iframe, bibliothèque externe, menu burger, etc.).
En vous référant aux 3 maquettes fournies en en-tête du présent chapitre (desktop, mobile, et mobile avec navigation dépliée), veuillez intégrer cette maquette.
La page est un catalogue vivant : chaque section se nomme et se définit elle-même avant de démontrer concrètement la technique qu’elle illustre (Hero Section, Cards, Slider, vidéo intégrée, carte intégrée, tableau, formulaire…).
Besoin d’un coup de pouce ?
Si vous ne savez pas comment commencer, voici un squelette HTML de départ, avec uniquement la structure des sections dans l’ordre attendu — à vous de le compléter avec les classes, le contenu et le CSS nécessaires.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<!-- favicon -->
<!-- meta description -->
<style>
</style>
</head>
<body>
<!-- header : logo + nav (ancres vers chaque section) + bouton menu -->
<header>
<nav>
</nav>
</header>
<!-- section 1 : hero plein écran -->
<section>
</section>
<!-- section 2 : hero secondaire (texte + image) -->
<section>
</section>
<!-- section 3 : cards -->
<section>
</section>
<!-- section 4 : bandeau image en arrière-plan -->
<section>
</section>
<!-- section 5 : slider -->
<section>
</section>
<!-- section 6 : vidéo -->
<section>
</section>
<!-- section 7 : carte -->
<section>
</section>
<!-- section 8 : tableau -->
<section>
</section>
<!-- section 9 : formulaire -->
<section>
</section>
<!-- footer -->
<footer>
</footer>
<!-- bouton retour en haut -->
</body>
</html>
La correction, section par section
Plutôt qu’un seul gros bloc de correction, chaque section a la sienne : si vous êtes bloqué sur un seul point précis, inutile de tout regarder — ouvrez uniquement la correction qui vous concerne.
Attention : pour fonctionner, chaque section a besoin, en plus de son propre code, du CSS commun ci-dessous (variables, reset, styles génériques) — à copier une seule fois dans votre fichier, quelle que soit la section sur laquelle vous travaillez. Certaines sections (menu burger, slider) ont aussi besoin du JS commun, plus bas.
CSS commun (nécessaire pour toutes les sections)
/* ===== CSS COMMUN — à copier une seule fois dans votre fichier ===== */
/* Variables CSS (chapitre 580) */
:root {
--color-primary: #fb6400;
--color-dark: #1e1e1e;
--color-light: #ffffff;
--color-bg: #f5f5f5;
--color-text: #333333;
--color-border: #e0e0e0;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
color: var(--color-text);
background-color: var(--color-bg);
scroll-behavior: smooth;
}
h1, h2, h3 {
color: var(--color-dark);
}
/* Style générique appliqué à toutes les balises section */
section {
padding: 60px 20px;
max-width: 1000px;
margin: 0 auto;
}
section > p.definition {
max-width: 700px;
color: #555;
font-size: 1.05rem;
}
/* Bouton générique, avec radius */
.btn {
display: inline-block;
background-color: var(--color-primary);
color: var(--color-light);
border: none;
border-radius: 10px;
padding: 12px 24px;
font-size: 1rem;
cursor: pointer;
text-decoration: none;
transition: background-color 0.3s ease;
}
.btn:hover {
background-color: #d95700;
}
JS commun (nécessaire pour le menu burger et le slider)
<!-- Bibliothèque Splide, nécessaire pour la section Slider (chapitre 810) -->
<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/js/splide.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Activation du slider Splide
new Splide('.splide', {
type: 'loop',
perPage: 1,
}).mount();
// Menu burger (chapitre 850)
const burger = document.querySelector(".burger");
const navLinks = document.querySelector(".nav-links");
burger.addEventListener("click", function () {
navLinks.classList.toggle("active");
});
// Fermer le menu mobile après un clic sur un lien
document.querySelectorAll(".nav-links a").forEach(function (link) {
link.addEventListener("click", function () {
navLinks.classList.remove("active");
});
});
});
</script>
Les 11 corrections, section par section
Header (logo, nav par ancres, menu burger)
<!-- HTML -->
<header>
<nav>
<div class="logo">Intégration Web</div>
<ul class="nav-links">
<li><a href="#hero">Hero</a></li>
<li><a href="#cards">Cards</a></li>
<li><a href="#slider">Slider</a></li>
<li><a href="#video">Vidéo</a></li>
<li><a href="#map">Carte</a></li>
<li><a href="#tableau">Tableau</a></li>
<li><a href="#formulaire">Formulaire</a></li>
</ul>
<button class="burger" aria-label="Menu">☰</button>
</nav>
</header>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
header {
background-color: var(--color-dark);
padding: 15px 20px;
position: sticky;
top: 0;
z-index: 100;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
color: var(--color-light);
font-weight: bold;
font-size: 1.2rem;
}
.nav-links {
display: flex;
gap: 20px;
list-style: none;
margin: 0;
padding: 0;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.nav-links a {
color: var(--color-light);
text-decoration: none;
transition: color 0.3s ease;
}
.nav-links a:hover {
color: var(--color-primary);
}
.burger {
display: none;
background: none;
border: none;
padding: 0;
appearance: none;
-webkit-appearance: none;
line-height: 1;
color: var(--color-light);
font-size: 1.8rem;
cursor: pointer;
}
@media (max-width: 768px) {
.nav-links {
display: none;
flex-direction: column;
position: absolute;
top: 60px;
left: 0;
transform: none;
width: 100%;
background-color: var(--color-dark);
margin: 0;
padding: 20px;
gap: 15px;
}
.nav-links.active {
display: flex;
}
.burger {
display: block;
}
}
/* Le menu burger a aussi besoin du JS commun (voir plus haut) */
Hero Section (full viewport, chapitre 650)
<!-- HTML -->
<section id="hero">
<div class="overlay"></div>
<div class="hero-full-content">
<h1>Ceci est une Hero Section</h1>
<p class="definition">Une Hero Section est le premier bloc visible d'une page web. Cette version occupe toute la hauteur de l'écran, avec une image en arrière-plan.</p>
<a href="#hero-secondaire" class="btn">Découvrir la suite</a>
</div>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
#hero {
position: relative;
width: 100%;
height: 100vh;
/* on neutralise le max-width/padding/margin hérité de la règle générique "section" */
max-width: none;
margin: 0;
padding: 0;
background-image: url('https://placehold.co/1600x900?text=hero-full-viewport');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
#hero .overlay {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
#hero .hero-full-content {
position: relative;
z-index: 1;
color: var(--color-light);
padding: 0 20px;
max-width: 700px;
}
#hero .hero-full-content h1 {
color: var(--color-light);
}
Hero Section secondaire (texte + image)
<!-- HTML -->
<section id="hero-secondaire">
<div class="hero-text">
<h1>Ceci est une Hero Section secondaire</h1>
<p class="definition">Une variante de Hero Section en deux colonnes : texte d'un côté, image de l'autre, plutôt qu'en plein écran.</p>
<a href="#cards" class="btn">Découvrir la suite</a>
</div>
<img src="https://placehold.co/600x400?text=hero" alt="Illustration de la hero section secondaire">
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
#hero-secondaire {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 40px;
padding-top: 80px;
}
#hero-secondaire .hero-text {
flex: 1;
min-width: 280px;
}
#hero-secondaire img {
flex: 1;
min-width: 280px;
max-width: 500px;
width: 100%;
height: auto;
border-radius: 10px;
}
Cards (3 cards en Flexbox)
<!-- HTML -->
<section id="cards">
<h2>Ceci sont des Cards, construites en Flexbox</h2>
<p class="definition">Une card est un bloc autonome regroupant une image et un texte, souvent utilisé pour présenter des services ou des articles. Ici, trois cards sont alignées côte à côte grâce à Flexbox.</p>
<div class="cards-container">
<div class="card">
<img src="https://placehold.co/300x200?text=card1" alt="Card 1">
<div class="card-content">
<h3>HTML</h3>
<p>Structure le contenu de la page à l'aide de balises.</p>
</div>
</div>
<div class="card">
<img src="https://placehold.co/300x200?text=card2" alt="Card 2">
<div class="card-content">
<h3>CSS</h3>
<p>Habille visuellement la structure : couleurs, espacements, mise en page.</p>
</div>
</div>
<div class="card">
<img src="https://placehold.co/300x200?text=card3" alt="Card 3">
<div class="card-content">
<h3>JavaScript</h3>
<p>Ajoute du comportement et de l'interactivité à la page.</p>
</div>
</div>
</div>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
.cards-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 30px;
}
.card {
flex: 1;
min-width: 250px;
background-color: var(--color-light);
border: 1px solid var(--color-border);
border-radius: 10px;
overflow: hidden;
}
.card img {
width: 100%;
height: auto;
display: block;
}
.card-content {
padding: 20px;
}
Bandeau image en arrière-plan (chapitre 150)
<!-- HTML -->
<section class="section-background">
<div class="overlay"></div>
<div class="contenu-background">
<h2>Ceci est une image en arrière-plan</h2>
<p>Une background-image habille visuellement un bloc, sans passer par une balise img.</p>
</div>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
.section-background {
width: 100%;
height: 300px;
/* on neutralise le max-width/padding/margin hérité de la règle générique "section" */
max-width: none;
margin: 0;
padding: 0;
background-image: url('https://placehold.co/1600x600?text=background-image');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
position: relative;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.section-background .overlay {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.section-background .contenu-background {
position: relative;
z-index: 1;
color: var(--color-light);
padding: 0 20px;
}
.section-background h2 {
color: var(--color-light);
margin-bottom: 10px;
}
Slider (bibliothèque externe Splide, chapitre 810)
<!-- HTML -->
<!-- Nécessite aussi, dans le head, le CSS de Splide chargé depuis le CDN : -->
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css"> -->
<section id="slider">
<h2>Ceci est un Slider, une bibliothèque externe intégrée</h2>
<p class="definition">Plutôt que de coder un slider entièrement à la main, on peut intégrer une bibliothèque externe déjà construite — ici Splide, chargée depuis un CDN.</p>
<section class="splide" aria-label="Galerie d'images">
<div class="splide__track">
<div class="splide__list">
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image1" alt="Image 1">
</div>
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image2" alt="Image 2">
</div>
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image3" alt="Image 3">
</div>
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image4" alt="Image 4">
</div>
</div>
</div>
</section>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
.splide {
max-width: 600px;
margin: 30px auto 0 auto;
}
.splide__slide img {
width: 100%;
height: auto;
display: block;
}
/* Le slider a aussi besoin du JS commun, qui l'active (voir plus haut) */
Vidéo intégrée (iframe responsive, chapitre 90)
<!-- HTML -->
<section id="video">
<h2>Ceci est une vidéo intégrée, via un iframe</h2>
<p class="definition">Un iframe permet d'intégrer un contenu externe à une page web, comme cette vidéo YouTube. Un conteneur avec un padding-bottom en pourcentage la rend responsive.</p>
<div class="video-conteneur">
<div class="responsive-video">
<iframe src="https://www.youtube.com/embed/UCRi8niBIbA" title="Vidéo exemple" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
</div>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
.video-conteneur {
max-width: 700px;
margin: 30px auto 0 auto;
}
.responsive-video {
position: relative;
width: 100%;
padding-bottom: 56.25%;
height: 0;
}
.responsive-video iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 10px;
}
Carte intégrée (iframe Google Maps, chapitre 95)
<!-- HTML -->
<section id="map">
<h2>Ceci est une carte intégrée, elle aussi via un iframe</h2>
<p class="definition">Même principe que la vidéo : Google Maps fournit un code iframe, dont on retire les dimensions fixes pour les gérer nous-mêmes en CSS.</p>
<div class="map-container">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d21529.419930070188!2d-2.8673990264643896!3d47.58378965310169!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x48101ac23d1f14c9%3A0x71d07ab5d81f9c34!2s%C3%8Ele-aux-Moines!5e0!3m2!1sfr!2sfr!4v1734186267933!5m2!1sfr!2sfr"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade">
</iframe>
</div>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
.map-container {
width: 100%;
max-width: 700px;
height: 400px;
margin: 30px auto 0 auto;
border-radius: 10px;
overflow: hidden;
}
.map-container iframe {
width: 100%;
height: 100%;
border: none;
}
Tableau (chapitre 600)
<!-- HTML -->
<section id="tableau">
<h2>Ceci est un tableau</h2>
<p class="definition">Un tableau organise des données en lignes et colonnes, à l'aide des balises table, thead, tbody, tr, th et td.</p>
<table>
<thead>
<tr>
<th>Jour</th>
<th>Horaires</th>
</tr>
</thead>
<tbody>
<tr><td>Lundi</td><td>9h - 18h</td></tr>
<tr><td>Mardi</td><td>9h - 18h</td></tr>
<tr><td>Mercredi</td><td>9h - 18h</td></tr>
<tr><td>Jeudi</td><td>9h - 18h</td></tr>
<tr><td>Vendredi</td><td>9h - 17h</td></tr>
</tbody>
</table>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
table {
width: 100%;
max-width: 600px;
margin: 30px auto 0 auto;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
border: 1px solid var(--color-border);
}
thead {
background-color: var(--color-dark);
color: var(--color-light);
}
tbody tr:nth-child(even) {
background-color: #f0f0f0;
}
Formulaire (chapitre 595)
<!-- HTML -->
<section id="formulaire">
<h2>Ceci est un formulaire</h2>
<p class="definition">Un formulaire permet de recueillir des informations saisies par l'utilisateur, à l'aide de champs input, select, textarea, regroupés dans des fieldset.</p>
<form>
<fieldset>
<legend>Vos coordonnées</legend>
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom" placeholder="Votre nom" required>
<label for="email">Email :</label>
<input type="email" id="email" name="email" placeholder="Votre email" required>
</fieldset>
<label for="sujet">Sujet :</label>
<select id="sujet" name="sujet">
<option value="">-- Choisissez --</option>
<option value="devis">Demande de devis</option>
<option value="info">Demande d'information</option>
</select>
<label for="message">Message :</label>
<textarea id="message" name="message" rows="4" placeholder="Votre message"></textarea>
<br><br>
<button type="submit" class="btn">Envoyer</button>
</form>
</section>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
form {
max-width: 500px;
margin: 30px auto 0 auto;
background-color: var(--color-light);
padding: 20px;
border-radius: 10px;
border: 1px solid var(--color-border);
}
fieldset {
border: 1px solid var(--color-border);
border-radius: 6px;
margin-bottom: 20px;
padding: 15px;
}
label {
display: block;
margin-top: 10px;
margin-bottom: 5px;
font-weight: bold;
}
input, select, textarea {
width: 100%;
padding: 8px;
border: 1px solid var(--color-border);
border-radius: 6px;
font-family: inherit;
}
Footer + bouton retour en haut (chapitre 135)
<!-- HTML -->
<footer>
<p>Ceci est un footer</p>
<p>© 2026 Intégration réalisée par [prénom] [nom] — <a href="#top">retour en haut</a></p>
</footer>
<a href="#top" id="retour-haut" aria-label="Retour en haut">↑</a>
/* ===== CSS spécifique (le CSS commun est nécessaire en plus, voir plus haut) ===== */
footer {
background-color: var(--color-dark);
color: var(--color-light);
text-align: center;
padding: 30px 20px;
margin-top: 40px;
}
footer a {
color: var(--color-primary);
}
#retour-haut {
position: fixed;
bottom: 20px;
right: 20px;
background-color: var(--color-primary);
color: var(--color-light);
border: none;
border-radius: 10px;
padding: 10px 16px;
font-size: 1.5rem;
cursor: pointer;
text-decoration: none;
z-index: 100;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
/* Rappel : le body doit avoir id="top" pour que ce lien fonctionne : <body id="top"> */
A n’utilisez qu’en extrême recours :
Chapitre 1000 annexe | La correction complète assemblée
Le chapitre 1000 propose une correction découpée en 11 parties, section par section. Si vous préférez comparer votre travail avec la page complète assemblée (HTML, CSS et JavaScript réunis dans un seul fichier), la voici ci-dessous.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Catalogue de l'intégration web</title>
<!-- Meta description (chapitre 710) -->
<meta name="description" content="Une page qui se décrit elle-même : chaque section nomme et démontre une brique HTML/CSS/JS apprise durant le cours d'intégration web pour UI Designers.">
<!-- Favicon (chapitre 710) -->
<link rel="icon" type="image/png" href="https://placehold.co/32x32/1e1e1e/ffffff?text=W">
<!-- Splide CSS (chapitre 810) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/css/splide.min.css">
<style>
/* ===== Variables CSS (chapitre 580) ===== */
:root {
--color-primary: #fb6400;
--color-dark: #1e1e1e;
--color-light: #ffffff;
--color-bg: #f5f5f5;
--color-text: #333333;
--color-border: #e0e0e0;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
color: var(--color-text);
background-color: var(--color-bg);
scroll-behavior: smooth;
}
h1, h2, h3 {
color: var(--color-dark);
}
section {
padding: 60px 20px;
max-width: 1000px;
margin: 0 auto;
}
section > p.definition {
max-width: 700px;
color: #555;
font-size: 1.05rem;
}
/* Boutons génériques avec radius */
.btn {
display: inline-block;
background-color: var(--color-primary);
color: var(--color-light);
border: none;
border-radius: 10px;
padding: 12px 24px;
font-size: 1rem;
cursor: pointer;
text-decoration: none;
transition: background-color 0.3s ease;
}
.btn:hover {
background-color: #d95700;
}
/* ===== Header (chapitre 850) ===== */
header {
background-color: var(--color-dark);
padding: 15px 20px;
position: relative;
position: sticky;
top: 0;
z-index: 100;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
.logo {
color: var(--color-light);
font-weight: bold;
font-size: 1.2rem;
}
.nav-links {
display: flex;
gap: 20px;
list-style: none;
margin: 0;
padding: 0;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.nav-links a {
color: var(--color-light);
text-decoration: none;
transition: color 0.3s ease;
}
.nav-links a:hover {
color: var(--color-primary);
}
.burger {
display: none;
background: none;
border: none;
padding: 0;
appearance: none;
-webkit-appearance: none;
line-height: 1;
color: var(--color-light);
font-size: 1.8rem;
cursor: pointer;
}
@media (max-width: 768px) {
.nav-links {
display: none;
flex-direction: column;
position: absolute;
top: 60px;
left: 0;
transform: none;
width: 100%;
background-color: var(--color-dark);
margin: 0;
padding: 20px;
gap: 15px;
}
.nav-links.active {
display: flex;
}
.burger {
display: block;
}
}
/* ===== Hero Section (full viewport, chapitre 650) ===== */
#hero {
position: relative;
width: 100%;
height: 100vh;
/* on neutralise le max-width/padding/margin hérité de la règle générique "section" */
max-width: none;
margin: 0;
padding: 0;
background-image: url('https://placehold.co/1600x900?text=hero-full-viewport');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
#hero .overlay {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.4);
}
#hero .hero-full-content {
position: relative;
z-index: 1;
color: var(--color-light);
padding: 0 20px;
max-width: 700px;
}
#hero .hero-full-content h1 {
color: var(--color-light);
}
/* ===== Hero secondaire ===== */
#hero-secondaire {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 40px;
padding-top: 80px;
}
#hero-secondaire .hero-text {
flex: 1;
min-width: 280px;
}
#hero-secondaire img {
flex: 1;
min-width: 280px;
max-width: 500px;
width: 100%;
height: auto;
border-radius: 10px;
}
/* ===== Cards ===== */
.cards-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
margin-top: 30px;
}
.card {
flex: 1;
min-width: 250px;
background-color: var(--color-light);
border: 1px solid var(--color-border);
border-radius: 10px;
overflow: hidden;
}
.card img {
width: 100%;
height: auto;
display: block;
}
.card-content {
padding: 20px;
}
/* ===== Section background-image (chapitre 150) ===== */
.section-background {
width: 100%;
height: 300px;
/* on neutralise le max-width/padding/margin hérité de la règle générique "section" */
max-width: none;
margin: 0;
padding: 0;
background-image: url('https://placehold.co/1600x600?text=background-image');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
position: relative;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.section-background .overlay {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.5);
}
.section-background .contenu-background {
position: relative;
z-index: 1;
color: var(--color-light);
padding: 0 20px;
}
.section-background h2 {
color: var(--color-light);
margin-bottom: 10px;
}
/* ===== Slider ===== */
.splide {
max-width: 600px;
margin: 30px auto 0 auto;
}
.splide__slide img {
width: 100%;
height: auto;
display: block;
}
/* ===== Vidéo responsive (chapitre 90) ===== */
.video-conteneur {
max-width: 700px;
margin: 30px auto 0 auto;
}
.responsive-video {
position: relative;
width: 100%;
padding-bottom: 56.25%;
height: 0;
}
.responsive-video iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 10px;
}
/* ===== Map (chapitre 95) ===== */
.map-container {
width: 100%;
max-width: 700px;
height: 400px;
margin: 30px auto 0 auto;
border-radius: 10px;
overflow: hidden;
}
.map-container iframe {
width: 100%;
height: 100%;
border: none;
}
/* ===== Tableau (chapitre 600) ===== */
table {
width: 100%;
max-width: 600px;
margin: 30px auto 0 auto;
border-collapse: collapse;
}
th, td {
padding: 12px;
text-align: left;
border: 1px solid var(--color-border);
}
thead {
background-color: var(--color-dark);
color: var(--color-light);
}
tbody tr:nth-child(even) {
background-color: #f0f0f0;
}
/* ===== Formulaire (chapitre 595) ===== */
form {
max-width: 500px;
margin: 30px auto 0 auto;
background-color: var(--color-light);
padding: 20px;
border-radius: 10px;
border: 1px solid var(--color-border);
}
fieldset {
border: 1px solid var(--color-border);
border-radius: 6px;
margin-bottom: 20px;
padding: 15px;
}
label {
display: block;
margin-top: 10px;
margin-bottom: 5px;
font-weight: bold;
}
input, select, textarea {
width: 100%;
padding: 8px;
border: 1px solid var(--color-border);
border-radius: 6px;
font-family: inherit;
}
/* ===== Footer ===== */
footer {
background-color: var(--color-dark);
color: var(--color-light);
text-align: center;
padding: 30px 20px;
margin-top: 40px;
}
footer a {
color: var(--color-primary);
}
/* ===== Bouton retour en haut (chapitre 135) ===== */
#retour-haut {
position: fixed;
bottom: 20px;
right: 20px;
background-color: var(--color-primary);
color: var(--color-light);
border: none;
border-radius: 10px;
padding: 10px 16px;
font-size: 1.5rem;
cursor: pointer;
text-decoration: none;
z-index: 100;
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
</style>
</head>
<body id="top">
<!-- ===== Header ===== -->
<header>
<nav>
<div class="logo">Intégration Web</div>
<ul class="nav-links">
<li><a href="#hero">Hero</a></li>
<li><a href="#cards">Cards</a></li>
<li><a href="#slider">Slider</a></li>
<li><a href="#video">Vidéo</a></li>
<li><a href="#map">Carte</a></li>
<li><a href="#tableau">Tableau</a></li>
<li><a href="#formulaire">Formulaire</a></li>
</ul>
<button class="burger" aria-label="Menu">☰</button>
</nav>
</header>
<!-- ===== Hero Section (full viewport) ===== -->
<section id="hero">
<div class="overlay"></div>
<div class="hero-full-content">
<h1>Ceci est une Hero Section</h1>
<p class="definition">Une Hero Section est le premier bloc visible d'une page web. Cette version occupe toute la hauteur de l'écran, avec une image en arrière-plan.</p>
<a href="#hero-secondaire" class="btn">Découvrir la suite</a>
</div>
</section>
<!-- ===== Hero Section secondaire ===== -->
<section id="hero-secondaire">
<div class="hero-text">
<h1>Ceci est une Hero Section secondaire</h1>
<p class="definition">Une variante de Hero Section en deux colonnes : texte d'un côté, image de l'autre, plutôt qu'en plein écran.</p>
<a href="#cards" class="btn">Découvrir la suite</a>
</div>
<img src="https://placehold.co/600x400?text=hero" alt="Illustration de la hero section secondaire">
</section>
<!-- ===== Section Cards ===== -->
<section id="cards">
<h2>Ceci sont des Cards, construites en Flexbox</h2>
<p class="definition">Une card est un bloc autonome regroupant une image et un texte, souvent utilisé pour présenter des services ou des articles. Ici, trois cards sont alignées côte à côte grâce à Flexbox.</p>
<div class="cards-container">
<div class="card">
<img src="https://placehold.co/300x200?text=card1" alt="Card 1">
<div class="card-content">
<h3>HTML</h3>
<p>Structure le contenu de la page à l'aide de balises.</p>
</div>
</div>
<div class="card">
<img src="https://placehold.co/300x200?text=card2" alt="Card 2">
<div class="card-content">
<h3>CSS</h3>
<p>Habille visuellement la structure : couleurs, espacements, mise en page.</p>
</div>
</div>
<div class="card">
<img src="https://placehold.co/300x200?text=card3" alt="Card 3">
<div class="card-content">
<h3>JavaScript</h3>
<p>Ajoute du comportement et de l'interactivité à la page.</p>
</div>
</div>
</div>
</section>
<!-- ===== Section Background Image (respiration) ===== -->
<section class="section-background">
<div class="overlay"></div>
<div class="contenu-background">
<h2>Ceci est une image en arrière-plan</h2>
<p>Une background-image habille visuellement un bloc, sans passer par une balise img.</p>
</div>
</section>
<!-- ===== Section Slider ===== -->
<section id="slider">
<h2>Ceci est un Slider, une bibliothèque externe intégrée</h2>
<p class="definition">Plutôt que de coder un slider entièrement à la main, on peut intégrer une bibliothèque externe déjà construite — ici Splide, chargée depuis un CDN.</p>
<section class="splide" aria-label="Galerie d'images">
<div class="splide__track">
<div class="splide__list">
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image1" alt="Image 1">
</div>
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image2" alt="Image 2">
</div>
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image3" alt="Image 3">
</div>
<div class="splide__slide">
<img src="https://placehold.co/600x400?text=image4" alt="Image 4">
</div>
</div>
</div>
</section>
</section>
<!-- ===== Section Vidéo ===== -->
<section id="video">
<h2>Ceci est une vidéo intégrée, via un iframe</h2>
<p class="definition">Un iframe permet d'intégrer un contenu externe à une page web, comme cette vidéo YouTube. Un conteneur avec un padding-bottom en pourcentage la rend responsive.</p>
<div class="video-conteneur">
<div class="responsive-video">
<iframe src="https://www.youtube.com/embed/UCRi8niBIbA" title="Vidéo exemple" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
</div>
</section>
<!-- ===== Section Map ===== -->
<section id="map">
<h2>Ceci est une carte intégrée, elle aussi via un iframe</h2>
<p class="definition">Même principe que la vidéo : Google Maps fournit un code iframe, dont on retire les dimensions fixes pour les gérer nous-mêmes en CSS.</p>
<div class="map-container">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d21529.419930070188!2d-2.8673990264643896!3d47.58378965310169!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x48101ac23d1f14c9%3A0x71d07ab5d81f9c34!2s%C3%8Ele-aux-Moines!5e0!3m2!1sfr!2sfr!4v1734186267933!5m2!1sfr!2sfr"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade">
</iframe>
</div>
</section>
<!-- ===== Section Tableau ===== -->
<section id="tableau">
<h2>Ceci est un tableau</h2>
<p class="definition">Un tableau organise des données en lignes et colonnes, à l'aide des balises table, thead, tbody, tr, th et td.</p>
<table>
<thead>
<tr>
<th>Jour</th>
<th>Horaires</th>
</tr>
</thead>
<tbody>
<tr><td>Lundi</td><td>9h - 18h</td></tr>
<tr><td>Mardi</td><td>9h - 18h</td></tr>
<tr><td>Mercredi</td><td>9h - 18h</td></tr>
<tr><td>Jeudi</td><td>9h - 18h</td></tr>
<tr><td>Vendredi</td><td>9h - 17h</td></tr>
</tbody>
</table>
</section>
<!-- ===== Section Formulaire ===== -->
<section id="formulaire">
<h2>Ceci est un formulaire</h2>
<p class="definition">Un formulaire permet de recueillir des informations saisies par l'utilisateur, à l'aide de champs input, select, textarea, regroupés dans des fieldset.</p>
<form>
<fieldset>
<legend>Vos coordonnées</legend>
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom" placeholder="Votre nom" required>
<label for="email">Email :</label>
<input type="email" id="email" name="email" placeholder="Votre email" required>
</fieldset>
<label for="sujet">Sujet :</label>
<select id="sujet" name="sujet">
<option value="">-- Choisissez --</option>
<option value="devis">Demande de devis</option>
<option value="info">Demande d'information</option>
</select>
<label for="message">Message :</label>
<textarea id="message" name="message" rows="4" placeholder="Votre message"></textarea>
<br><br>
<button type="submit" class="btn">Envoyer</button>
</form>
</section>
<!-- ===== Footer ===== -->
<footer>
<p>Ceci est un footer</p>
<p>© 2026 Intégration réalisée par [prénom] [nom] — <a href="#top">retour en haut</a></p>
</footer>
<!-- ===== Bouton retour en haut ===== -->
<a href="#top" id="retour-haut" aria-label="Retour en haut">↑</a>
<!-- Splide JS (chapitre 810) -->
<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@4.1.4/dist/js/splide.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Activation du slider Splide
new Splide('.splide', {
type: 'loop',
perPage: 1,
}).mount();
// Menu burger (chapitre 850)
const burger = document.querySelector(".burger");
const navLinks = document.querySelector(".nav-links");
burger.addEventListener("click", function () {
navLinks.classList.toggle("active");
});
// Fermer le menu mobile après un clic sur un lien
document.querySelectorAll(".nav-links a").forEach(function (link) {
link.addEventListener("click", function () {
navLinks.classList.remove("active");
});
});
});
</script>
</body>
</html>