Accessibilité de base et mentions légales
Temps 1 · séance 5 · ~25 min
Les slides du chapitre (PDF)PDF
- Passer cinq vérifications d'accessibilité dans le navigateur.
- Corriger dans vos pages ce que ces vérifications révèlent.
- Publier une page de mentions légales exacte.
- Relier les mentions légales depuis chaque page publique.
1. Cinq vérifications
Un site accessible se lit et s'utilise par tout le monde : au clavier sans souris, avec une vue faible, ou avec un lecteur d'écran, le logiciel qui lit la page à voix haute. Cinq vérifications couvrent les erreurs les plus fréquentes d'un portfolio. Elles se font dans le navigateur, page par page, en quelques minutes.
| Vérification | Ce qu'elle protège | Comment la faire |
|---|---|---|
| Texte alternatif des images | le lecteur d'écran sait ce que montre l'image | une ligne dans la console, puis relire chaque alt |
| Titres dans l'ordre | la navigation de titre en titre | une ligne dans la console qui liste les titres |
| Contraste de la palette | la lecture avec une vue faible ou en plein soleil | le sélecteur de couleur des outils de développement |
| Focus visible au clavier | l'utilisation sans souris | la touche Tab, de haut en bas de la page |
| Libellés des champs | le remplissage du formulaire de contact | un clic sur chaque libellé |
Le texte alternatif des images
L'attribut alt d'une image donne le texte que le lecteur d'écran lit à sa place. Une image qui apporte une information reçoit une phrase qui la décrit. Une image décorative, ou qui répète le texte voisin, reçoit alt="" : le lecteur d'écran la saute. Sans attribut alt, il lit le nom du fichier.
Dans la console des outils de développement, cette ligne compte les images sans attribut alt :
document.querySelectorAll('img:not([alt])').length
La réponse doit être 0 sur chaque page. Relisez ensuite chaque alt avec la même question : que perd un lecteur qui n'a pas l'image ? Dans ProjectCard.vue, le titre du projet suit l'image et dit ce qu'elle montre, d'où alt="". Si la capture d'une fiche montre ce que le texte ne dit pas, décrivez-la.
Les titres dans l'ordre
Un lecteur d'écran permet de sauter de titre en titre, comme on parcourt une table des matières. Une page a un seul h1, puis des h2, puis des h3 sous un h2, sans sauter de niveau. Cette ligne liste les titres de la page dans l'ordre :
[...document.querySelectorAll('h1, h2, h3, h4')].map((h) => h.tagName + ' ' + h.textContent.trim())
Relisez le code du chapitre 1.18. Sur l'accueil, le h1 de votre nom est suivi du h2 « Projets récents », puis des h3 des cartes : l'ordre est respecté. Sur la liste des projets, le h1 « Mes projets » est suivi directement des h3 des cartes, et le niveau 2 manque. Donnez à la carte un h2 : sur l'accueil, les titres des cartes sont alors au même niveau que « Projets récents », et aucun niveau ne saute sur les deux pages.
Le niveau d'un titre dit sa place dans la structure, pas sa taille. La taille vient des classes, comme text-lg, qui ne changent pas.
Le contraste
Vous avez mesuré les paires de votre planche au chapitre 1.09. Le site en ajoute d'autres : le blanc sur bg-brand de l'appel à l'action, le gris text-muted-foreground des résumés sur le fond, les liens text-brand. Mesurez chaque paire réellement affichée, en mode clair et en mode sombre.
Dans Chrome, inspectez un élément de texte, puis cliquez sur le petit carré de couleur à côté de color dans le panneau Styles. Le sélecteur de couleur affiche le contraste de ce texte sur son fond, avec les seuils atteints ou non. Les seuils restent ceux du chapitre 1.09 : 4,5:1 pour tout texte, boutons compris, et 3:1 pour une icône, le contour d'un champ ou la forme d'un bouton face à la page.
Le focus visible au clavier
Le focus marque l'élément qui recevra la prochaine frappe du clavier. La touche Tab le fait passer au lien ou au bouton suivant, et Entrée l'active. Sans cadre visible autour de l'élément qui a le focus, une personne qui navigue au clavier ne sait plus où elle est.
Cliquez dans la barre d'adresse, puis appuyez sur Tab jusqu'au bas de la page. Chaque lien et chaque bouton doit montrer un cadre ou un changement net. Les boutons du kit ont un anneau de focus, écrit avec focus-visible:ring-[3px] dans resources/js/components/ui/button/index.ts. Vos liens gardent le contour que le navigateur dessine par défaut. Ne le retirez jamais avec outline-none sans le remplacer.
Sur la page de contact, le focus passe du nom à l'adresse, au message, puis au bouton.

Les libellés des champs
Chaque champ a besoin d'un libellé relié à lui : une balise <label> dont l'attribut for vaut l'id du champ. Le lecteur d'écran annonce ce libellé quand le champ reçoit le focus. Un texte d'exemple dans le champ, l'attribut placeholder, ne le remplace pas, car il disparaît dès qu'on tape.
Dans Contact.vue, <Label for="name"> est relié à <Input id="name">. Pour vérifier, cliquez sur chaque libellé : le curseur doit se placer dans le champ correspondant.
Astuce
L'onglet Lighthouse des outils de développement de Chrome fait un audit automatique de l'accessibilité d'une page. Il trouve une partie de ces erreurs, mais pas toutes : il ne sait pas si un alt décrit bien l'image. Gardez les cinq vérifications faites à la main.
2. Les mentions légales
Un visiteur doit pouvoir savoir qui publie le site, qui l'héberge et ce que deviennent les données qu'il y laisse. La page de mentions légales le dit. Elle n'affiche aucune donnée de la base, donc elle n'a pas besoin de contrôleur.
La route d'abord
Ajoutez la route dans routes/web.php, à côté de about :
Route::inertia('mentions-legales', 'Legal')->name('legal');
Enregistrez le fichier avant d'écrire la page et le lien. Wayfinder génère alors la fonction legal() dans resources/js/routes/index.ts. Dans l'ordre inverse, un import de legal écrit avant la route fait échouer Vite, avec ce message dans la console :
SyntaxError: The requested module '/resources/js/routes/index.ts' does not provide an export named 'legal'
L'erreur disparaît dès que la route existe et que le terminal affiche Types generated for actions, routes, form variants.
La page
Créez resources/js/pages/Legal.vue :
<script setup>
import { Head } from '@inertiajs/vue3';
</script>
<template>
<Head title="Mentions légales">
<meta
head-key="description"
name="description"
content="Éditeur, hébergeur et données personnelles du portfolio de Nora Benali."
/>
</Head>
<article class="prose max-w-none py-8 dark:prose-invert">
<h1 class="font-display">Mentions légales</h1>
<h2>Éditeur du site</h2>
<p>
Nora Benali, étudiante à l'IFOSUP Wavre. Contact : par le formulaire
de la page Contact.
</p>
<h2>Hébergeur</h2>
<p>OVH SAS, 2 rue Kellermann, 59100 Roubaix, France.</p>
<h2>Données personnelles</h2>
<p>
Le formulaire de contact enregistre votre nom, votre adresse e-mail
et votre message, pour vous répondre et pour rien d'autre. Ils ne
sont ni vendus ni transmis. Écrivez-moi pour les faire effacer.
</p>
<h2>Cookies</h2>
<p>
Ce site ne dépose aucun cookie de mesure d'audience ni de publicité.
Il utilise seulement les cookies techniques nécessaires à son
fonctionnement (session et protection des formulaires).
</p>
</article>
</template>
Les textes sont ceux de l'exemple. Écrivez les vôtres, et ne déclarez que ce que votre site fait vraiment.

- L'éditeur, c'est vous : votre nom, et un moyen de vous joindre. Le formulaire de contact suffit, sans publier votre adresse e-mail.
- L'hébergeur est la société qui loue le serveur. Recopiez son nom et son adresse depuis les conditions de votre hébergement chez OVH, et vérifiez-les.
- Les données personnelles sont celles du formulaire du chapitre 1.20 : le nom, l'adresse e-mail et le message, enregistrés dans la table
contact_messageset envoyés à votre boîte. Dites pourquoi vous les gardez, et comment en demander l'effacement. - Les cookies : le kit dépose un cookie de session, un cookie
XSRF-TOKENqui protège les formulaires, et un cookieappearancepour le thème choisi dans le back-office. Ce sont des cookies techniques. Aucun ne sert à mesurer l'audience ou à faire de la publicité, et le site n'affiche donc pas de bandeau de cookies.
Les polices ne demandent aucune ligne. Depuis le chapitre 1.18, le site sert lui-même leurs fichiers, et aucune donnée du visiteur ne part vers un service tiers.
prose met en forme les titres et les paragraphes, comme pour l'à-propos.
Le lien dans le pied de page
Chaque page publique mène aux mentions légales. Dans PublicLayout.vue, ajoutez legal à l'import de @/routes, puis le lien dans le pied de page :
<footer
class="flex flex-col gap-2 border-t py-6 text-sm text-muted-foreground sm:flex-row sm:justify-between"
>
<p>© Nora Benali</p>
<Link :href="legal()" class="underline">Mentions légales</Link>
</footer>
import { about, contact, home, legal } from '@/routes';
Le test
Ajoutez ce test dans tests/Feature/PublicPagesTest.php, le fichier du chapitre 1.19 :
test('the legal notice page exists', function () {
$this->get('/mentions-legales')
->assertOk()
->assertInertia(fn (Assert $page) => $page->component('Legal'));
});
Assert est la classe du chapitre 1.17, importée en tête du fichier avec use Inertia\Testing\AssertableInertia as Assert;. La sortie de php artisan test tests/Feature/PublicPagesTest.php est celle du chapitre 1.19, avec ce test en dernière ligne.
L'accessibilité complète d'un site et son cadre légal, déclaration d'accessibilité et protection des données comprises, viendront avec le projet en binôme.
3. Pratique : les cinq vérifications et vos mentions (20 min)
Temps annoncé : 20 minutes.
Faites les cinq vérifications sur chaque page publique : l'accueil, la liste, une fiche, l'à-propos, le contact et les mentions légales. Corrigez au fur et à mesure.
- La console répond 0 à
document.querySelectorAll('img:not([alt])').length, et chaquealtnon vide décrit l'image. - Chaque page a un seul
h1, et les titres se suivent sans sauter de niveau. - Chaque texte atteint 4,5:1 sur son fond, dans chaque mode que votre site propose, appel à l'action compris.
- Avec la touche Tab, chaque lien et chaque bouton montre un focus visible.
- Un clic sur chaque libellé du contact place le curseur dans son champ.
-
/mentions-legalesnomme l'éditeur et l'hébergeur, dit ce que deviennent les messages du formulaire, et indique qu'aucun cookie tiers n'est déposé. - Le pied de page de chaque page publique mène aux mentions légales.
- Le test des mentions légales est vert, et
php artisan testaussi.
Ce que votre portfolio contient maintenant
Des pages publiques qui passent les cinq vérifications de base : des images avec leur texte alternatif, des titres dans l'ordre, des contrastes mesurés, un focus visible et des champs avec leur libellé. Une page de mentions légales, reliée depuis chaque page publique, qui dit qui édite le site, qui l'héberge et ce que deviennent les données du formulaire.
À retenir
- Chaque image a un attribut
alt, vide pour une image décorative, descriptif pour une image qui informe. - Les titres se suivent sans sauter de niveau, et leur taille vient des classes, pas du niveau.
- Le contraste se mesure dans le sélecteur de couleur du navigateur, pour chaque paire réellement affichée.
- La touche Tab montre un focus visible sur chaque lien et chaque bouton, et chaque champ a un
<label for>relié à sonid. Route::inertia('mentions-legales', 'Legal')suffit pour une page sans données, à condition de déclarer la route avant d'importerlegal().