Cours CSS / créer un petit site adaptatif avec HTML et CSS
Vous pouvez combiner HTML sémantique, variables CSS partagées, navigation Flexbox et disposition Grid pour les cartes afin de créer un petit site web adaptatif. Commencez par un contenu lisible et une disposition utilisable sur écran étroit, puis ajoutez des ajustements pour les écrans plus larges et des états d'interaction visibles.
Définir la page et les vérifications d'acceptation
Décidez quel contenu et quel comportement la page doit avoir avant de la styliser. Sur les écrans étroits, la navigation se replie lorsque nécessaire et les cartes forment une seule colonne. Un espace plus grand permet deux ou trois colonnes. Limitez la largeur de lecture globale afin que le texte ne devienne pas excessivement long sur les écrans larges.
| Exigences | Critères d'achèvement |
|---|---|
| structure du contenu | Un titre principal, une phrase d'introduction, trois cartes et un pied de page sont lus dans l'ordre. |
| écran étroit | Les menus et les cartes sont lisibles sans défilement horizontal complet |
| écran large | Les cartes sont disposées en plusieurs colonnes tout en maintenant la largeur maximale du corps |
| navigation au clavier | Le lien d’évitement vers le contenu principal et les autres liens ont un indicateur de focus visible. |
| Changements de contenu | Les cartes grandissent avec les descriptions longues et laissent les chaînes sans espaces passer à la ligne, sans couper le contenu à une hauteur fixe. |
| mouvement réduit | Permet de se déplacer selon les besoins sans défilement fluide et transitions décoratives. |
Cet exemple est un écran statique et il n'y a pas de liens sur la carte elle-même. Le menu d'introduction/de cours et les grands liens de navigation mènent à des sections du même document. Pour développer votre liste de cours réels, mettez l'URL du post vérifié dans le titre de la carte. Il n'est pas nécessaire d'ajouter de force des formulaires inutilisés ou des animations infinies pour compléter cet exercice.
Préparer les fichiers et le HTML sémantique
Créez index.html et style.css au même emplacement dans un dossier vide. Lors de la création du fichier, assurez-vous qu'il ne s'agit pas de index.html.txt à cause de l'extension cachée et enregistrez-le en UTF-8. La balise link dans index.html pointe vers style.css dans le même dossier. Aucune installation ou compilation séparée n'est requise.
learning-site/
index.html
style.css
Tout d'abord, enregistrez le HTML complet ci-dessous sous le nom index.html. Même si le CSS est vide, le titre, le lien et le contenu de la carte doivent être lus dans l'ordre. header est la zone d'en-tête du site, nav est la navigation, main est le contenu principal, et footer est le pied de page. Placez le sujet d'étude h2 et la carte h3 sous h1 dans le document. Ce HTML est un exemple de fichier indépendant, il est donc séparé de la structure de la page directement attachée au corps de WordPress.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>A Small Learning Site</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<a class="skip-link" href="#main">Skip to main content</a>
<header class="site-header">
<div class="container header-inner">
<p class="site-name">Learning Notes</p>
<nav aria-label="Main navigation">
<a href="#intro">About</a><a href="#lessons">Lessons</a>
</nav>
</div>
</header>
<main id="main" tabindex="-1">
<section id="intro" class="hero" aria-labelledby="intro-title">
<div class="container">
<h1 id="intro-title">Learn to Build Webpages Step by Step</h1>
<p>Structure content with HTML and adapt its appearance with CSS.</p>
<a class="button" href="#lessons">Explore the lessons</a>
</div>
</section>
<section id="lessons" class="lessons container" aria-labelledby="lessons-title">
<h2 id="lessons-title">Learning topics</h2>
<ul class="card-grid" role="list">
<li><article class="card"><h3>HTML structure</h3><p>Organize content with headings and paragraphs.</p></article></li>
<li><article class="card"><h3>CSS styles</h3><p>Adjust colors, fonts, and spacing.</p></article></li>
<li><article class="card"><h3>Responsive layout</h3><p>Arrange cards to fit the available width.</p></article></li>
</ul>
</section>
</main>
<footer class="site-footer"><div class="container"><p>Small learning site exercise</p></div></footer>
</body>
</html>
Le raccourci vers le texte principal est relié à l'ID de main. tabindex="-1" permet à main de recevoir le focus sans l'ajouter à l'ordre normal des tabulations. Appuyez sur un menu ou un raccourci pour naviguer vers cette section et assurez-vous que la navigation au clavier continue à partir du contenu principal. Pour le but et la composition du raccourci, veuillez vous référer à la technique de raccourci texte W3C.
Définir les valeurs partagées et la largeur du contenu
Commencez le fichier style.css avec la section suivante. Nommer les variables de couleur selon leur rôle facilite le changement de la couleur d'accent partagée. border-box inclut le remplissage et les bordures dans la largeur déclarée, simplifiant ainsi le dimensionnement. Établissez une mise en page de base pouvant accueillir un contenu croissant au lieu d'attribuer des dimensions fixes partout. Avant de modifier les valeurs partagées, distinguez Variables CSS : var(), portée, héritage et valeurs de repli.
/* Shared values and base styles */
:root {
--ink: #183044;
--accent: #166b92;
--surface: #eef6fa;
--line: #c9dbe4;
--focus: #164f73;
}
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; color: var(--ink); font-family: sans-serif; line-height: 1.6; }
a { color: var(--accent); text-underline-offset: .15em; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.container { width: min(100% - 2rem, 68rem); margin-inline: auto; }
.container, .card { overflow-wrap: anywhere; }
La largeur du conteneur est le minimum entre « la largeur disponible moins 2rem au total, soit 1rem de chaque côté » et 68rem. Fournit des marges gauche et droite pour les écrans étroits et une largeur maximale pour les écrans larges. auto pour margin-inline centre la zone. overflow-wrap: anywhere permet aux adresses ou identifiants longs sans espaces de passer à la ligne si nécessaire, sans modifier la chaîne copiée. Il faut faire la distinction entre la pratique qui ne fait qu'augmenter la longueur d'une phrase générale et la pratique qui ajoute un mot long.
Si vous actualisez à ce stade, les couleurs, la police par défaut et la largeur du contenu seront appliquées, mais les en-têtes et les cartes ne seront pas encore disposés en détail. S'il n'y a aucun changement, vérifiez le chemin du fichier avant d'ajouter la section arrière. Les concepts de taille fluide et de largeur maximale sont liés aux mises en page CSS fluides avec min(), max-width et clamp().
Construire la navigation Flexbox et les chemins de focus
Ajoutez la section suivante sous Règles communes dans style.css : Le placement entre le nom du site et le menu est géré par le header-inner, et l'espacement à l'intérieur du menu est géré par le nav. En séparant l'écart entre les deux positions, vous pouvez réduire la possibilité de modifications involontaires de l'espacement entre les liens du menu lors du changement de l'espacement de l'ensemble de l'en-tête. Les principes de base de la direction de l'axe et du placement des éléments peuvent être trouvés dans Les bases de Flexbox : conteneur, éléments et axes.
/* Navigation and header */
.skip-link { position: absolute; left: 1rem; top: -6rem; padding: .5rem; background: white; }
.skip-link:focus { top: 1rem; z-index: 10; }
.site-header { border-bottom: 1px solid var(--line); }
.header-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
gap: .5rem 1.5rem; padding-block: 1rem; }
.site-name { margin: 0; font-weight: 700; }
nav { display: flex; flex-wrap: wrap; gap: 1rem; }
flex-wrap place l'élément sur la ligne suivante s'il n'y a pas assez d'espace. Avoir un menu sur deux lignes sur un écran étroit n'est pas un échec. Les critères pour juger sont s'il y a des liens qui se chevauchent, sont tronqués ou non cliquables. Conservez un ordre de navigation cohérent dans le HTML, sans inverser seulement la disposition visuelle avec order.
Le lien d’évitement est placé au-dessus de la zone visible, puis apparaît lorsqu’il reçoit le focus. display: none empêcherait aussi de l’atteindre au clavier et ne convient donc pas ici. Au premier appui sur Tab, vérifiez l’apparition du lien ; activez-le avec Entrée, puis appuyez à nouveau sur Tab pour atteindre le grand lien de l’introduction. Le contour de focus foncé se distingue des arrière-plans blanc et bleu clair.
Styliser l'introduction fluide et les états des liens
L'ajout des sections suivantes complète le contexte introductif, le titre et les grands liens de navigation. La limitation de la taille du titre fixe les valeurs minimale, préférée et maximale. La police ne devient pas infiniment plus grande à mesure que la largeur augmente, et le réglage de la taille de la police, y compris le terme rem, est également pris en compte. Un contrôle séparé de l'écran est nécessaire pour vérifier s'il est réellement facile à lire lorsque l'utilisateur effectue un zoom.
/* Introduction and navigation link */
.hero { padding-block: clamp(3rem, 8vw, 6rem); background: var(--surface); }
.hero h1 { max-width: 18ch; margin-block: 0 1rem;
font-size: clamp(1.8rem, 1.2rem + 2vw, 3rem); line-height: 1.25; }
.hero p { max-width: 50ch; }
.button { display: inline-block; margin-top: .5rem; padding: .7rem 1rem;
border-radius: .4rem; background: var(--accent); color: white; text-decoration: none;
transition: background-color 180ms ease; }
.button:hover { background: #104d6a; }
Le max-width: 18ch du titre utilise la largeur du glyphe "0" de la police ; il ne garantit pas 18 lettres par ligne. Son line-height contrôle les lignes de titre renvoyées à la ligne, tandis que le paragraphe introductif est limité à 50ch. Cet exemple utilise des polices système sans-serif et ne télécharge aucune police externe.
Le grand lien utilise l’élément a, car il mène à la section des leçons du même document. Si l'opération consistait à changer l'état sans déplacer la page, le bouton doit être vérifié. Seules les transitions de couleur de fond sont utilisées au survol, et aucun mouvement décoratif ou agrandissement n'est requis. Le statut de focus peut être confirmé par un contour commun.
Construisez des cartes de grille qui accueillent du contenu
Ajoutez les sections suivantes pour compléter votre carte de cours et le pied de page. Supprimez les marges et les puces par défaut de la liste, mais laissez les structures ul et li dans le HTML. Si une liste avec list-style: none est en dehors de nav, elle peut ne pas être reconnue comme une liste dans l'arbre d'accessibilité de Safari. Dans l'exemple, ul spécifie role="list" pour définir le rôle de liste. Cette condition peut également être trouvée dans la description d'accessibilité MDN listing. L'ordre de lecture du HTML ne change pas pour la disposition des lignes et des colonnes dans la grille.
/* Cards and footer */
.lessons { padding-block: 3rem; }
.lessons h2 { margin-block: 0 1.5rem; }
.card-grid { display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem; margin: 0; padding: 0; list-style: none; }
.card-grid > li { min-width: 0; }
.card { height: 100%; padding: 1.5rem; border: 1px solid var(--line); border-radius: .5rem; }
.card h3 { margin-block: 0 .75rem; }
.card p { margin-block: 0; }
.site-footer { padding-block: 2rem; border-top: 1px solid var(--line); }
.site-footer p { margin: 0; }
auto-fit calcule les pistes qui tiennent dans l’espace disponible ; minmax() fixe leur minimum et leur maximum. Avec min(100%, 16rem), une zone plus étroite que 16rem peut encore accueillir une colonne. L’espace restant est distribué par 1fr. Comme l’exemple comporte trois cartes, auto-fit réduit les pistes répétées vides : une grande largeur ne fait pas apparaître une quatrième carte ni une colonne vide conservée. Comparez avec Grid : repeat, auto-fit, auto-fill et zones nommées, puis consultez la documentation MDN sur repeat() et la documentation MDN sur minmax().
À condition que la taille du texte de premier niveau soit de 16px et que la largeur de page disponible soit la même que la fenêtre d’affichage, la largeur minimale de la carte soit de 256px, l’écart de 16px, et les marges totales gauche et droite soient de 32px. Vous avez besoin d’au moins 560px d’espace pour deux colonnes et 832px pour trois colonnes. À mesure que la barre de défilement, la largeur du parent et la taille de la police changent, la largeur réelle de la transition change aussi, donc ne la mémorisez pas en fonction du nom de l’appareil.
La hauteur de 100 % d’une carte est la valeur qui remplit la hauteur des éléments de la liste dans la même ligne. Ce n’est pas une hauteur fixe de pixel, donc les lignes peuvent s’allonger au fur et à mesure que la description s’agrandit. Pour éviter que de longs mots ne dépassent la taille de l’élément de la grille, fixez la largeur minimale de li à 0 et utilisez les règles de retour à la ligne de la carte.
Ajouter des conditions pour grand écran et mouvement réduit
Ajouter cette section à la fin de style.css. À partir de 64rem, le fond de l'introduction passe à un dégradé. La grille continue de déterminer le nombre de colonnes de cartes indépendamment ; cette requête média ne définit pas ce nombre.
/* Conditional adjustments */
@media (min-width: 64rem) {
.hero { background: linear-gradient(100deg, var(--surface), #fff); }
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.button { transition: none; }
}
Dans la condition de mouvement réduit, nous changeons le défilement pour un mouvement instantané et éliminons également les transitions de couleur de fond. Le but et l'accent du lien et de son contenu sont maintenus. L'application de règles conditionnelles est liée à Media queries et points de rupture adaptés au contenu, et le contrôle du mouvement et de l'accessibilité est lié à Vérifier le design adaptatif : largeur, zoom et clavier.
Exécutez la feuille de style complète
Ceci est un fichier qui combine toutes les règles ajoutées étape par étape. Utilisez ce fichier entier pour vérifier l'ordre de votre code ou recommencer. Après l'avoir enregistré dans le même dossier que index.html, ouvrez index.html avec un navigateur et actualisez.
/* Shared values and base styles */
:root {
--ink: #183044;
--accent: #166b92;
--surface: #eef6fa;
--line: #c9dbe4;
--focus: #164f73;
}
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body { margin: 0; color: var(--ink); font-family: sans-serif; line-height: 1.6; }
a { color: var(--accent); text-underline-offset: .15em; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }
.container { width: min(100% - 2rem, 68rem); margin-inline: auto; }
.container, .card { overflow-wrap: anywhere; }
/* Navigation and header */
.skip-link { position: absolute; left: 1rem; top: -6rem; padding: .5rem; background: white; }
.skip-link:focus { top: 1rem; z-index: 10; }
.site-header { border-bottom: 1px solid var(--line); }
.header-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
gap: .5rem 1.5rem; padding-block: 1rem; }
.site-name { margin: 0; font-weight: 700; }
nav { display: flex; flex-wrap: wrap; gap: 1rem; }
/* Introduction and navigation link */
.hero { padding-block: clamp(3rem, 8vw, 6rem); background: var(--surface); }
.hero h1 { max-width: 18ch; margin-block: 0 1rem;
font-size: clamp(1.8rem, 1.2rem + 2vw, 3rem); line-height: 1.25; }
.hero p { max-width: 50ch; }
.button { display: inline-block; margin-top: .5rem; padding: .7rem 1rem;
border-radius: .4rem; background: var(--accent); color: white; text-decoration: none;
transition: background-color 180ms ease; }
.button:hover { background: #104d6a; }
/* Cards and footer */
.lessons { padding-block: 3rem; }
.lessons h2 { margin-block: 0 1.5rem; }
.card-grid { display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem; margin: 0; padding: 0; list-style: none; }
.card-grid > li { min-width: 0; }
.card { height: 100%; padding: 1.5rem; border: 1px solid var(--line); border-radius: .5rem; }
.card h3 { margin-block: 0 .75rem; }
.card p { margin-block: 0; }
.site-footer { padding-block: 2rem; border-top: 1px solid var(--line); }
.site-footer p { margin: 0; }
/* Conditional adjustments */
@media (min-width: 64rem) {
.hero { background: linear-gradient(100deg, var(--surface), #fff); }
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
.button { transition: none; }
}
Changez les valeurs et diagnostiquez les problèmes
- Réduisez la largeur de l'écran à environ 390px puis élargissez-la en gardant la valeur originale. Pour les petites largeurs, il devrait y avoir une colonne, pour les grandes largeurs, il devrait y avoir deux ou trois colonnes. Si les conditions décrites ci-dessus sont les mêmes, les différences entre 559px et 560px ainsi qu'entre 831px et 832px sont également comparées.
- Changer uniquement 16rem de la grille de cartes à 20rem. Ajouter plus de colonnes sur le même écran nécessite plus d'espace. Après confirmation, restaurer à 16rem.
- Changer uniquement 68rem du conteneur à 50rem. Même sur des écrans plus grands, la largeur globale du contenu devient plus étroite. Après confirmation, restaurer à 68rem.
- Modifiez uniquement --accent en choisissant une couleur assez foncée. Vérifiez que la couleur des liens ordinaires et l’arrière-plan du grand lien changent ensemble. Le texte blanc et le contour de focus doivent rester lisibles ; rétablissez ensuite la couleur d’origine.
- Étirez la description d'une carte en plusieurs phrases. Assurez-vous que le contenu ne soit pas tronqué à mesure que la hauteur augmente et que la hauteur des cartes dans la même rangée soit organisée. Après la pratique, restaurez la phrase originale.
- Insérez une chaîne anglaise sans espaces dans la carte. overflow-wrap: anywhere permet à cette chaîne de passer à la ligne à l’intérieur de la carte. Le simple fait de supprimer temporairement cette règle de saut de ligne peut provoquer un débordement. Après comparaison, les règles et les phrases sont toutes deux restaurées.
- Déplacez-vous avec Tab et Shift+Tab et appuyez sur Entrée pour chaque lien. Vous devriez pouvoir naviguer vers l'introduction et les sujets d'étude sans avoir besoin d'une souris.
- Reproduire les conditions de réduction du mouvement. Le déplacement des liens doit être maintenu et les défilements/transitions fluides doivent disparaître. Après confirmation, restaurer les paramètres de reproduction par défaut.
Vérifier que la navigation, les cartes, les indicateurs de focus et les paragraphes restent lisibles lorsque le navigateur est zoomé ou que les paramètres de police changent. L'agrandissement temporaire de la taille de la police de html dans DevTools teste la taille en rem, mais cela diffère du zoom du navigateur. Une seule configuration réussie ne garantit pas l'utilisabilité dans toutes les conditions de zoom et de taille de texte.
| problème | Vérifier d'abord |
|---|---|
| Aucun style du tout | Extension de fichier, statut de sauvegarde, chemin relatif du lien |
| Le défilement horizontal se produit | Mots longs, taille minimale de colonne, largeur réelle du parent, box-sizing: border-box absent |
| La hauteur de la carte est irrégulière | Définir la hauteur de la même ligne et de la carte ; les lignes différentes n'ont pas besoin d'être identiques |
| Aucun indicateur de focus visible | Règles qui remplacent le contour, que le contour soit coupé en raison du débordement |
| Effet de mouvement indésirable | Conditions réelles des médias et valeurs de scroll-behavior·transition appliquées |
Sélectionnez l'élément problématique dans les Outils de développement pour voir la largeur calculée réelle, le sélecteur et les colonnes de la grille. Au lieu de masquer le problème en forçant tous les sauts de ligne ou en ajoutant overflow:hidden au corps, corrigez d'abord la taille et le contenu de l'élément dépassé. En vérifiant l'état de base, l'état de changement et l'état de restauration pour chaque exigence, vous pouvez aller un pas plus loin que simplement copier le code terminé et l'appliquer également à d'autres contenus.




