⚡ Le cahier des charges en cinq blocs
| Bloc | Contenu imposé | Technique |
| Header | nom · menu vers les 4 sections · image (option) |
Flexbox horizontal |
| À propos | photo + 2–3 lignes | Flexbox, côte à côte |
| Compétences | 4 à 6 compétences techniques | CSS Grid, en cartes |
| Expériences | titre · période · description | blocs verticaux |
| Footer | email · téléphone · LinkedIn/GitHub | fond proche du header, centré |
Livrables : cv.html + style.css, le CSS
externe via <link rel="stylesheet" href="style.css">.
La structure sémantique
html<header>
<nav>…les liens SEULEMENT…</nav>
<div class="presentation">…</div>
</header>
<main>
<section id="a-propos"></section>
<section id="competences"></section>
<section id="experiences"></section>
</main>
<footer id="contact"></footer>
Le <footer> est hors du <main>.
Les ancres
html + css<a href="#competences">…</a> ← avec #
<section id="competences"> ← sans #
html { scroll-behavior: smooth; }
section { scroll-margin-top: 70px; }
scroll-margin-top évite que le titre passe sous le menu.
⚡ <a> ou <button>
<a> = aller quelque part
<button> = déclencher
Jamais l'un dans l'autre : deux contenus interactifs imbriqués sont
interdits par la spécification.
html✘ <button><a href="#x">Voir</a></button>
✔ <a class="bouton" href="#x">Voir</a>
Un lien s'habille en bouton avec display: inline-block + padding.
Flexbox — aligner une file
css.menu {
display: flex;
justify-content: center; /* axe principal */
align-items: center; /* axe secondaire */
gap: 30px;
margin: 0; padding: 0; /* un <ul> en a par défaut */
}
.menu li { list-style: none; }
flex-wrap: wrap autorise le passage à la ligne ;
flex-shrink: 0 empêche un élément de se comprimer.
⚡ Grid — la ligne à retenir
repeat(auto-fit,
minmax(220px, 1fr))
« Autant de colonnes que possible, d'au moins 220 px, le reste partagé. »
| 1000 px | 4 colonnes |
| 700 px | 3 colonnes |
| 480 px | 2 colonnes |
| 375 px | 1 colonne |
Responsive sans media query.
auto-fit ≠ auto-fill
auto-fit | replie les colonnes vides → les cartes
s'étalent |
auto-fill | garde les colonnes vides → les cartes restent
serrées à gauche |
Pour un CV : auto-fit.
minmax(min, max) — dans cet ordre. minmax(1fr, 220px) est
invalide et la règle est ignorée.
⚡ Dimensionner une image
Une dimension → l'autre suit
Deux dimensions → object-fit: cover
css/* vignette régulière */
img {
width: 100%;
aspect-ratio: 16 / 10;
object-fit: cover;
display: block;
}
Sur le web, une image se dimensionne en %, jamais en pixels figés.
display: block supprime l'espace fantôme sous l'image.
Fonds et voiles
cssheader {
background-image:
linear-gradient(rgba(0,0,0,.55),
rgba(0,0,0,.55)),
url("asset/background.jpg");
background-size: cover;
background-position: center;
}
La première couche déclarée est celle du dessus.
Sans background-size, l'image se répète en mosaïque.
⚡ Le formulaire — 4 erreurs classiques
| ✘ | ✔ |
action="POST" |
method="post" action="contact.php" |
for="first-name" sur un champ id="email" |
for = exactement l'id |
type="number" pour un téléphone | type="tel" |
| bouton « Envoyé » | « Envoyer » — à l'infinitif |
action = l'adresse · method = le verbe
Test : cliquer sur chaque intitulé. Le curseur doit sauter dans le champ.
Choisir le type
On peut l'additionner ?
→ number. Sinon, non.
| téléphone | tel |
| email | email |
| code postal | text + inputmode="numeric" |
| portfolio | url |
| années d'expérience | number |
⚡ Les 3 conditions du responsive
<meta name="viewport" content="width=device-width, initial-scale=1.0">
*, *::before, *::after { box-sizing: border-box; }
- des dimensions souples :
%, fr, minmax(),
max-width
Les media queries vont à la fin du fichier : à spécificité égale, la
dernière règle gagne.
Test à 375 px :
zéro défilement horizontal
La media query type
css@media (max-width: 768px) {
.menu { flex-wrap: wrap; height: auto; }
header { min-height: 55vh; }
.content-a-propos { flex-direction: column;
text-align: center; }
fieldset { padding: 20px; }
}
Une media query ne sert qu'à ce que le contenu ne peut pas régler seul.
Les alt
| Photo de profil | alt="l'élève" |
| Capture de projet | alt="Accueil de SpeedrunHub" |
| Icône décorative | alt="" — volontairement |
| Fond de bannière | en CSS, jamais en HTML |
Un alt vide est une décision, pas un oubli.
⚡ Un CV en ligne est public
| en ligne | PDF envoyé |
| Nom, email, LinkedIn | ✔ | ✔ |
| Ville seule | ✔ | ✔ |
| Adresse postale | ✘ | ✔ |
| Téléphone | ✘ | ✔ |
| Date de naissance | ✘ | facultatif |
Principe RGPD de minimisation : ne publier que ce qui sert la finalité.
Ces données réunies sont la matière première de l'OSINT.
Poids des images
| Bannière | 1920 px · < 300 Ko |
| Capture de projet | 800 px · < 150 Ko |
| Photo de profil | 400 px · < 60 Ko |
| Icône | SVG · < 10 Ko |
Redimensionner puis exporter en WebP. loading="lazy" sur les images qu'on ne
voit qu'après avoir défilé.
Nommer les fichiers
minuscules · sans accent
sans espace · tiret
projet (1).png → projet-1.png.
Les serveurs web distinguent majuscules et minuscules, contrairement à macOS et Windows :
PP.jpg pour un fichier pp.jpg marche chez vous et nulle part
ailleurs.
⚡ Les 7 contrôles avant de rendre
- Copier le dossier ailleurs et l'ouvrir — ce qu'on voit est ce que le
correcteur verra.
- Relire le cahier des charges — les 5 blocs, le CSS externe, les noms
de fichiers exacts.
- Validateur W3C (
validator.w3.org) — imbrications
interdites, id dupliqués, balises mal fermées.
- Console F12 — zéro erreur rouge, zéro 404 d'image.
- 375 px — aucune barre de défilement horizontale.
- Chaque lien du menu, chaque intitulé de champ — cliqués.
- Orthographe — titres compris : ce sont eux qu'on lit en premier.
Aucun de ces contrôles n'écrit de code. Ils rapportent pourtant plus que dix minutes de CSS
supplémentaires : ils corrigent ce qui coûte des points.