Aller au contenu principal

CSS pour une interface lisible

CSS ne décide pas seul de l’expérience. HTML porte la structure et le sens ; CSS rend cette structure perceptible dans différentes tailles, densités et préférences. Le bon CSS donne une règle claire à un problème réel et laisse le contenu respirer.

Le flux avant le positionnement

Commence par le flux normal, Flexbox et Grid. Le positionnement absolu est utile pour une relation locale — une icône dans un champ par exemple — mais il ne doit pas devenir le plan de la page.

.session {
width: min(100% - 2rem, 72rem);
margin-inline: auto;
}

.session__content {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(16rem, 22rem);
gap: var(--sl-space-8);
align-items: start;
}

@media (max-width: 48rem) {
.session__content {
grid-template-columns: 1fr;
}
}

minmax(0, 1fr) évite qu’un contenu long force une colonne à déborder. La media query adapte la structure quand les deux colonnes ne peuvent plus préserver leur lisibilité, plutôt que de réduire la police jusqu’à la rendre inconfortable.

Les tokens nomment les décisions

Une valeur copiée plusieurs fois devient difficile à faire évoluer. Un token dit pourquoi elle existe :

:root {
--ui-space-1: 0.25rem;
--ui-space-2: 0.5rem;
--ui-space-4: 1rem;
--ui-color-surface: #0b141e;
--ui-color-text: #ffffff;
--ui-color-muted: rgba(255, 255, 255, 0.72);
--ui-color-accent: #00d1ff;
--ui-radius-control: 0.75rem;
}

Dans DevLab101, les tokens partagés commencent par --sl-*. Utilise ceux de src/design-system/tokens.css avant d’en créer un nouveau. Évite les noms comme --blue-3 si le rôle réel est « accent des actions principales » : une couleur peut changer, son intention doit rester stable.

Une échelle d’espace cohérente

L’espace regroupe ou sépare les décisions. Une petite échelle suffit :

  • espace court entre un label et son champ ;
  • espace moyen entre les éléments d’un même groupe ;
  • espace large entre deux sections ;
  • espace de page pour dégager le contenu principal.

Ne corrige pas chaque décalage avec une marge différente. Si une distance ne correspond à aucune relation de contenu, demande si le composant ou la hiérarchie n’est pas le vrai problème.

Typographie et mesure de lecture

Définis explicitement le corps, la hauteur de ligne et la longueur de ligne. Une unité comme ch peut limiter un paragraphe sans imposer une largeur fixe à tous les écrans.

.lesson-copy {
max-inline-size: 70ch;
color: var(--sl-text-secondary);
font-size: 1rem;
line-height: 1.7;
}

.lesson-copy h1,
.lesson-copy h2,
.lesson-copy h3 {
color: var(--sl-text-primary);
line-height: 1.15;
}

Ne masque pas le focus avec outline: none sans fournir une alternative visible. Ne mets pas une information importante uniquement en text-transform ou avec une opacité faible : le sens doit rester disponible dans le texte.

Les états font partie du composant

Un bouton a au minimum un état de repos, de survol, de focus-visible, d’appui, de chargement, de succès, d’erreur et de désactivation selon son contrat.

.action {
min-block-size: var(--sl-control-height);
padding-inline: var(--sl-space-4);
color: var(--sl-accent-contrast);
border: 1px solid var(--sl-accent);
border-radius: var(--sl-radius);
background: var(--sl-accent);
}

.action:hover {
filter: brightness(1.08);
}

.action:focus-visible {
outline: 3px solid var(--sl-focus);
outline-offset: 3px;
}

.action:disabled,
.action[aria-disabled='true'] {
cursor: not-allowed;
opacity: 0.45;
}

@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
scroll-behavior: auto !important;
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
}
}

aria-disabled n’empêche pas automatiquement le clic : si tu l’utilises, implémente aussi la règle dans le comportement. Pour une action indisponible, un vrai disabled est souvent plus sûr.

Formulaires et erreurs

L’erreur doit être identifiable sans couleur seule et reliée au champ. Le CSS peut renforcer la distinction ; il ne doit pas inventer le message.

<label for="answer">Ta réponse</label>
<input id="answer" aria-describedby="answer-help answer-error"
aria-invalid="true">
<p id="answer-help">Deux phrases suffisent.</p>
<p id="answer-error">Indique ce que tu as observé.</p>
.field[aria-invalid='true'] {
border-color: var(--sl-danger);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--sl-danger) 18%, transparent);
}

.field-error {
color: var(--sl-danger);
font-weight: 600;
}

Le champ conserve sa valeur lorsqu’une requête échoue. Une erreur réseau ne doit pas se transformer en formulaire vidé ni en écran bloqué.

Responsive et contenu imprévisible

Teste au moins :

  • 320 px de largeur ;
  • 768 px, lorsque la structure change souvent ;
  • 1440 px, pour éviter une ligne de lecture trop longue ;
  • un titre deux fois plus long ;
  • une traduction anglaise ou française plus expansive ;
  • un zoom navigateur à 200 % ;
  • une taille de texte augmentée.

Préférer min(), max(), clamp(), minmax() et des dimensions logiques (inline-size, block-size, margin-inline) aux hauteurs fixes et aux coordonnées précises. Une carte peut grandir avec son texte ; son contenu ne doit pas être coupé pour préserver une capture d’écran.

Le reset n’est pas une stratégie

Un reset minimal peut harmoniser les marges, mais un reset universel qui supprime tous les comportements natifs oblige ensuite à reconstruire les listes, boutons, focus et formulaires. Part du HTML sémantique et neutralise seulement ce qui sert une décision de design documentée.

Revue CSS en cinq questions

  1. Quelle relation de contenu cette règle rend-elle visible ?
  2. Est-ce un token ou une exception réellement nécessaire ?
  3. Que se passe-t-il avec une ligne longue, une erreur et un état de focus ?
  4. La règle tient-elle à 320 px, au zoom et dans l’autre locale ?
  5. Le composant reste-t-il compréhensible sans couleur, animation ou survol ?

Atelier FlashLearning

Prends l’écran de session de révision et écris trois règles avant d’écrire du CSS :

  1. quelle largeur doit garder le texte de la question ;
  2. quelle action doit rester visible sur mobile ;
  3. comment le focus et l’erreur restent perceptibles.
Une réponse possible

Limiter la question à une largeur de lecture, garder « Révéler la réponse » dans le flux principal et empiler les actions sous 48 rem. Donner au focus une bordure visible, relier l’erreur au champ et utiliser un texte ou une icône en plus de la couleur. Les tokens portent les espaces, le rayon et l’accent afin que les cartes et les boutons partagent la même grammaire.

Sources sérieuses

Pour relier ces règles au sens produit, reviens à Concevoir une interface qui se comprend, puis ouvre le parcours UI/UX interactif.