Aller au contenu

Clavier & Focus

Environ 5% des utilisateurs naviguent principalement au clavier. Cette population inclut les personnes avec handicap moteur, les utilisateurs avancés et les utilisateurs de lecteurs d’écran.


Interactions clavier standard

ToucheAction
TabFocus élément suivant
Shift + TabFocus élément précédent
EnterActiver bouton, lien, soumettre formulaire
EspaceCocher checkbox, activer bouton
↑ ↓ ← →Naviguer dans groupe radio, menu, select
EscapeFermer modal, dropdown, dialogue
Home / EndPremier / dernier élément d’une liste

Focus visible obligatoire

TDS applique ce style de focus sur tous les éléments interactifs :

:focus-visible {
outline: 2px solid var(--tds-color-blue-500); /* #0033A0 */
outline-offset: 3px;
border-radius: var(--tds-radius-xs);
}

Ordre du focus (tab order)

L’ordre de navigation au clavier doit suivre l’ordre visuel de la page : de haut en bas, de gauche à droite.

<!-- ✅ Ordre naturel — utiliser la structure DOM -->
<header>...</header>
<nav>...</nav>
<main>
<h1>...</h1>
<form>
<label for="nom">Nom</label>
<input id="nom" type="text">
<label for="prenom">Prénom</label>
<input id="prenom" type="text">
<button type="submit">Envoyer</button>
</form>
</main>
<footer>...</footer>
<!-- ❌ Éviter tabindex positifs — ils cassent l'ordre naturel -->
<input type="text" tabindex="3">
<input type="text" tabindex="1">
<button tabindex="2">Envoyer</button>

Règles tabindex

ValeurEffetQuand l’utiliser
tabindex="-1"Focusable par script, pas par TabÉléments focusés programmatiquement (modales)
tabindex="0"Ajout dans l’ordre naturelÉléments non-interactifs rendus focusables
tabindex="1+"DéconseilléJamais, sauf cas très rares justifiés

Focus trap (Modales)

Les modales doivent piéger le focus à l’intérieur pendant qu’elles sont ouvertes.

// Pattern de focus trap minimal
function trapFocus(modal) {
const focusable = modal.querySelectorAll(
'a[href], button:not([disabled]), input:not([disabled]), ' +
'select:not([disabled]), textarea:not([disabled]), [tabindex="0"]'
);
const first = focusable[0];
const last = focusable[focusable.length - 1];
modal.addEventListener('keydown', (e) => {
if (e.key !== 'Tab') return;
if (e.shiftKey) {
if (document.activeElement === first) {
e.preventDefault();
last.focus();
}
} else {
if (document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
// Focus le premier élément à l'ouverture
first?.focus();
}
// À la fermeture, retourner le focus sur l'élément déclencheur
function closeModal(modal, triggerElement) {
modal.hidden = true;
triggerElement?.focus();
}

Les skip links permettent aux utilisateurs clavier de sauter la navigation répétitive.

<!-- Premier élément du <body> -->
<a href="#main-content" class="tds-skip-link">
Aller au contenu principal
</a>
<!-- Dans les styles -->
<style>
.tds-skip-link {
position: absolute;
top: -100%;
left: var(--tds-spacing-4);
background: var(--tds-color-blue-500);
color: white;
padding: var(--tds-spacing-2) var(--tds-spacing-4);
border-radius: var(--tds-radius-sm);
text-decoration: none;
font-weight: var(--tds-font-weight-semibold);
z-index: var(--tds-z-tooltip);
}
.tds-skip-link:focus {
top: var(--tds-spacing-4);
}
</style>
<main id="main-content" tabindex="-1">
<!-- Contenu principal -->
</main>