Chapitre 43 : Support du mode d'écriture avec la propriété writing-mode
Changement de l'orientation du texte (vertical vs horizontal) et impact sur le flux CSS
Le concept de Writing Mode
1. Quoi
La propriété writing-mode est un outil puissant du CSS permettant de définir si le texte d'un élément est écrit horizontalement ou verticalement, ainsi que la direction dans laquelle les lignes de texte progressent.
Contrairement à la propriété direction (qui gère uniquement le sens de lecture LTR ou RTL sur un axe horizontal), writing-mode change l'orientation même du flux de rendu. Elle redéfinit la notion d'axe "inline" (l'axe suivant lequel le texte s'écoule) et d'axe "block" (l'axe suivant lequel les lignes s'empilent).
Les valeurs principales sont :
horizontal-tb: Le mode par défaut. Le texte est horizontal, et les blocs s'empilent de haut en bas (Top to Bottom).vertical-rl: Le texte est vertical, et les lignes progressent de droite à gauche (Right to Left). C'est le standard pour le japonais et le chinois traditionnel.vertical-lr: Le texte est vertical, et les lignes progressent de gauche à droite (Left to Right).
2. Pourquoi
L'utilisation de writing-mode est cruciale pour deux raisons majeures :
L'Internationalisation (i18n) : Pour créer des interfaces véritablement globales, vous ne pouvez pas supposer que tout texte s'écrit de gauche à droite et horizontalement. De nombreuses langues asiatiques utilisent nativement des modes verticaux. Ignorer cela revient à rendre votre application inutilisable ou culturellement incorrecte pour des millions d'utilisateurs.
Le Design d'Interface (UI) : Même dans des contextes occidentaux, le mode vertical est utilisé pour des besoins esthétiques ou ergonomiques :
- En-têtes de colonnes de tableaux très étroites.
- Onglets latéraux de navigation.
- Éléments de décoration typographique dans des magazines numériques.
3. Comment
A. Syntaxe de base
L'application est simple, mais son effet est radical sur le layout.
.vertical-text {
/* Texte vertical, lignes progressant de droite à gauche */
writing-mode: vertical-rl;
}
.horizontal-text {
/* Retour au mode standard */
writing-mode: horizontal-tb;
}
B. Cas concret : En-têtes de tableau optimisés
L'un des cas d'usage les plus fréquents est la rotation des en-têtes de colonnes pour gagner de l'espace horizontal tout en gardant des labels lisibles.
<table class="data-table">
<thead>
<tr>
<th>Nom</th>
<th class="vertical-header">Date de création</th>
<th class="vertical-header">Dernière modification</th>
<th class="vertical-header">Statut du projet</th>
</tr>
</thead>
<tbody>
<tr>
<td>Projet Alpha</td>
<td>2023-01-10</td>
<td>2023-12-01</td>
<td>Terminé</td>
</tr>
</tbody>
</table>
.data-table {
border-collapse: collapse;
font-family: sans-serif;
}
.data-table th, .data-table td {
border: 1px solid #ccc;
padding: 8px;
text-align: center;
}
.vertical-header {
/* On bascule le texte en vertical */
writing-mode: vertical-rl;
/* On force l'orientation des caractères pour qu'ils restent
droits (upright) plutôt que pivotés, selon le besoin */
text-orientation: mixed;
/* On utilise des propriétés logiques pour le padding
afin que l'espacement s'adapte au nouveau flux */
padding-inline-start: 10px;
padding-inline-end: 10px;
white-space: nowrap;
background-color: #f4f4f4;
}
C. Limitations et interactions
Le writing-mode ne travaille jamais seul. Il interagit avec deux autres concepts :
-
text-orientation: Alors quewriting-modedéfinit le flux des lignes,text-orientationdéfinit comment les caractères individuels sont tournés.mixed: Les caractères latins sont pivotés à 90°, les caractères CJK restent droits.upright: Tous les caractères restent droits, même les lettres latines (créant un effet de "pile" de lettres).sideways: Tous les caractères sont pivotés.
-
Les Propriétés Logiques : C'est le point le plus critique. Si vous utilisez
widthetheightavecwriting-mode: vertical-rl, vous allez vous perdre.widthreste toujours la dimension horizontale physique.heightreste toujours la dimension verticale physique.- Solution : Utilisez
inline-size(la taille dans le sens de l'écriture) etblock-size(la taille perpendiculaire à l'écriture).
4. Zone de Danger
❌ L'erreur classique : Utiliser des propriétés physiques
Tenter de centrer un texte vertical avec margin-left: auto; margin-right: auto;. Dans un mode vertical-rl, le "haut" et le "bas" du bloc sont maintenant les côtés gauche et droit.
✅ La bonne pratique : Utiliser les propriétés logiques
Utilisez margin-inline: auto; ou margin-block: auto;. Les propriétés logiques s'adaptent automatiquement au writing-mode actif.
margin-top→margin-block-startmargin-bottom→margin-block-endmargin-left→margin-inline-startmargin-right→margin-inline-end
Impact du writing-mode sur les axes CSS
Questions clés
1. Quelle est la différence fondamentale entre direction: rtl et writing-mode: vertical-rl ?
Découvrir la réponse
direction: rtl change le point de départ du texte sur une ligne horizontale (le texte commence à droite et va vers la gauche), mais la ligne reste horizontale. writing-mode: vertical-rl change l'orientation de la ligne elle-même : le texte s'écrit de haut en bas, et les lignes successives se placent à gauche de la précédente.
2. Pourquoi text-orientation: upright est-il souvent utilisé avec le mode vertical ?
Découvrir la réponse
Par défaut, en mode vertical, les caractères latins sont pivotés à 90 degrés. Pour créer un effet de texte "empilé" (comme on le voit souvent dans les titres de mangas ou certaines affiches), on utilise text-orientation: upright pour forcer chaque lettre à rester droite.
3. Comment writing-mode affecte-t-il le positionnement Flexbox ou Grid ?
Découvrir la réponse
Flexbox et Grid reposent sur les axes inline et block. Si vous changez le writing-mode, l'axe principal (justify-content) et l'axe secondaire (align-items) pivotent. Par exemple, dans un flex-direction: row, les éléments s'alignent normalement horizontalement. En vertical-rl, ils s'aligneront verticalement.
4. Quel est l'impact sur l'accessibilité (a11y) ?
Découvrir la réponse
Le writing-mode est purement visuel. Les lecteurs d'écran ignorent généralement cette propriété et lisent le contenu selon l'ordre du DOM et l'attribut lang du document. Cependant, il est crucial de s'assurer que le contraste reste suffisant et que le texte ne soit pas tronqué par des hauteurs fixes (height) qui deviendraient restrictives en mode vertical.
Mise en pratique
Exercice 1 : Reproduction guidée
Objectif : Créer un badge latéral "Nouveau" qui s'affiche verticalement sur le côté gauche d'une carte de produit.
- Le badge doit utiliser
writing-mode: vertical-rl. - Le texte doit être écrit de bas en haut (utilisez
rotateouvertical-lrselon votre approche, mais ici on veut tester le mode vertical). - Utilisez
text-orientation: mixed.
HTML de départ :
<div class="card">
<span class="badge">Nouveau</span>
<h3>Casque Audio Pro</h3>
<p>Description du produit...</p>
</div>
Découvrir la solution commentée
.card {
position: relative;
width: 300px;
height: 200px;
border: 1px solid #ddd;
padding: 20px;
}
.badge {
position: absolute;
left: 0;
top: 50px;
/* On active le mode vertical */
writing-mode: vertical-rl;
/* On pivote le bloc pour que le texte aille du bas vers le haut */
/* Note: vertical-rl va du haut vers le bas.
Pour aller du bas vers le haut, on peut utiliser rotate ou vertical-lr */
transform: rotate(180deg);
background: #ff4757;
color: white;
padding: 10px 5px;
font-size: 12px;
font-weight: bold;
text-transform: uppercase;
}
Exercice 2 : Adaptation
Objectif : Modifier un menu de navigation horizontal classique pour qu'il devienne un menu vertical "style asiatique" (lecture de droite à gauche) uniquement sur les grands écrans.
- Utilisez une Media Query (
min-width: 1024px). - Le conteneur du menu doit passer en
writing-mode: vertical-rl. - Assurez-vous que les liens (
<a>) conservent un espacement correct en utilisant des propriétés logiques.
HTML et CSS de départ :
<nav class="nav-container">
<a href="#" class="nav-link">Accueil</a>
<a href="#" class="nav-link">Produits</a>
<a href="#" class="nav-link">Services</a>
<a href="#" class="nav-link">Contact</a>
</nav>
/* CSS de départ — navigation horizontale à adapter */
.nav-container {
display: flex;
gap: 20px;
}
.nav-link {
text-decoration: none;
color: #333;
padding: 10px;
}
Ce que vous devez modifier :
- Ajouter une
@media (min-width: 1024px)qui bascule.nav-containerenwriting-mode: vertical-rl. - Positionner la barre de navigation à droite de l'écran en
position: fixed. - Remplacer le
paddingdes liens par des propriétés logiques (margin-block-start/margin-block-end).
Découvrir la solution commentée
.nav-container {
display: flex;
gap: 20px;
}
@media (min-width: 1024px) {
.nav-container {
/* Le flux global devient vertical */
writing-mode: vertical-rl;
/* On aligne les éléments en haut */
align-items: flex-start;
/* On définit une hauteur pour le conteneur car
le flux vertical ne s'étend pas naturellement en largeur */
height: 100vh;
position: fixed;
right: 0;
top: 0;
}
.nav-link {
/* Utilisation de propriétés logiques pour l'espacement */
margin-block-start: 15px;
margin-block-end: 15px;
text-decoration: none;
color: #333;
}
}
Exercice 3 : Conception
Objectif : Concevoir un tableau de bord de données où les labels des lignes sont affichés verticalement à gauche pour maximiser l'espace pour les valeurs numériques.
- Le tableau doit être responsive (
width: 100%). - Les labels de lignes (première colonne, classe
.label-cell) doivent être enwriting-mode: vertical-lr. - Utilisez
text-orientation: uprightpour que les lettres soient empilées verticalement. - Appliquez un
block-size: 30pxaux labels pour obtenir une colonne étroite (envertical-lr, l'axe block est horizontal →block-size= la largeur physique de la cellule). - Les cellules de valeurs (classe
.value-cell) doivent avoir unpadding: 10pxet les valeurs alignées à droite.
HTML de départ :
<table class="dashboard-table">
<tr>
<td class="label-cell">Ventes</td>
<td class="value-cell">12 450 €</td>
<td class="value-cell">9 800 €</td>
<td class="value-cell">15 300 €</td>
</tr>
<tr>
<td class="label-cell">Clients</td>
<td class="value-cell">342</td>
<td class="value-cell">289</td>
<td class="value-cell">401</td>
</tr>
<tr>
<td class="label-cell">Marge</td>
<td class="value-cell">28 %</td>
<td class="value-cell">31 %</td>
<td class="value-cell">24 %</td>
</tr>
</table>
vertical-lrEn writing-mode: vertical-lr, les axes sont inversés par rapport au mode horizontal :
| Propriété logique | Axe en vertical-lr | Propriété physique équivalente |
|---|---|---|
inline-size | Vertical (haut → bas) | height |
block-size | Horizontal (gauche → droite) | width |
Pour obtenir une colonne étroite, on veut limiter la largeur → c'est block-size: 30px.
inline-size fixerait la hauteur à 30 px et écraserait le texte empilé.
Découvrir la solution commentée
.dashboard-table {
border-collapse: collapse;
width: 100%;
}
.label-cell {
/* Mode vertical, lecture de gauche à droite */
writing-mode: vertical-lr;
/* Lettres empilées verticalement (chaque lettre reste droite) */
text-orientation: upright;
/* En vertical-lr, l'axe "block" est horizontal.
block-size contrôle donc la LARGEUR physique → colonne étroite. */
block-size: 30px;
/* inline-size laissé à auto : la HAUTEUR s'adapte au contenu de la ligne */
text-align: center;
padding-block: 8px; /* Espacement haut/bas de la cellule */
background: #eee;
font-weight: bold;
border: 1px solid #ccc;
}
.value-cell {
padding: 10px;
border: 1px solid #ccc;
text-align: right;
}