Gérer les directions d'écriture avec CSS
Le World Wide Web est, par nature, conçu pour l’internationalisation.
Mais de nombreux contenus sont centrés sur des langues occidentales, souvent l’anglais. Pour un internationalisation plus large, vous devez gérer un éventail plus varié de langues, et inclure celles qui s’écriivent de droite à gauche ou même dans d’autres directions.
Cet article illustre comment utiliser de bonnes pratiques CSS fournit, dès le départ, un support linguistique diversifié.
Laisser le contenu s’exprimer
Le contenu montre la voie !
Votre navigateur doit être en mesure de détecter si un texte spécifique utilise une langue qui s’écrit de gauche à droite, ou de droite à gauche. Mais, parfois, il est plus facile et robuste de lui donner directement l’information.
C’est ici qu’intervient l’attribute universel dir
!
Comme l’indique le qualificatif universel, cet attribut peut être appliqué à n’importe quel élément, n’importe où dans votre document HTML.
Vous pouvez le spécifier à la racine de votre document sur l’élément body
, ou sur un span
enveloppant un seul mot.
Cet attribut accepte trois valeurs différentes :
auto
, le comportement par défaut, pour laisser le navigateur deviner la meilleure direction du texte, sur la base d’une heuristique interne ;ltr
, qui signifie gauche à droite (left to right) indique que le texte est écrit de gauche… à droite ;rtl
, à l’inverse, signifie de droite à gauche (right to left) ce qui correspond aux langues qui s’écrivent dans ce sens, comme l’arabe.
Les axes de lignes ou de blocs
Le système de mise en page sur le web s’appuie sur la longue histoire de l’imprimerie et sur la manière de créer une page imprimée en assemblant des rangées de glyphes dans des blocs de texte.
Hormis quelques cas d’utilisation particuliers comme les éléments flottants, la plupart des éléments d’une page sont positionnés selon l’un de ces deux modèles :
- en tant que block ;
- en ligne.
Les éléments blocs, comme le montre le diagramme précédent, sont empilés verticalement dans leur conteneur, du haut vers le bas. Une fois le bas de ce dernier atteint, les blocs s’enroulent dans le conteneur suivant, comme la colonne suivante dans une mise en page à plusieurs colonnes.
Le diagramme ci-dessus montre des éléments en ligne qui s’empilent horizontalement, de la gauche vers la droite. Ils passent à la ligne suivante lorsqu’il n’y a plus d’espace disponible dans la rangée.
Dans un langage écrit de droite à gauche, les éléments en ligne s’allignent toujours horizontalement, mais dans le sens inverse, comme le montre le diagramme suivant.
Pour l’instant, et par souci de simplicité, je m’en tiendrai à la direction horizontale. N’oubliez pas que tout ceci s’applique tout autant à une présentation verticale.
Impact du sens d’écriture sur la mise en page
Nous allons voir comment la mise en forme d’une simple rangée de cartes peut être cassée lorsque la direction du texte change.
Comment la marge casse en cas de changement de direction
Commençons par un exemple simple :
- vous avez un ensemble de cartes qui sont disposées à l’écran sous forme de blocs en ligne ;
- chaque carte doit être alignée à gauche sur le bord de la zone de contenu ;
- chaque carte a une marge droite pour assurer l’espacement entre les éléments.
.card-item {
margin-right: 2rem;
}
Cela vous convient-il ? Essayons de passer à un mode d’écriture RTL (right-to-left, de droite à gauche).
Ce n’est plus aussi joli, n’est-ce pas ?
L’alignement en début de ligne est maintenant perdu parce que l’espacement des cartes est spécifié comme une marge droite.
Mais la gauche et la droite n’ont pas bougé, seule la direction du texte a changé.
Appelons les sélecteurs à la rescousse !
Vous me direz qu’il n’y a pas de problème. Le sélecteur ’:dir()’ n’existe t’il pas exactement pour gérer ce genre de scénario ?
La solution est simple. Il suffit d’ajouter une règle CSS supplémentaire pour gérer ce cas d’utilisation :
.card-item {
margin-right: 2rem;
}
.card-item:dir(rtl) {
/* Pour la langue RTL, il suffit d'inverser les marges gauche et droite ! */
margin-left: 2rem;
margin-right: 0;
}
C’est réparé ! Mission accomplie. Vraiment?
Vous savez que vous pouvez mieux faire, non ? Voyons comment !
Passez à une mise en page sémantique
Ne dépendez plus du sens d’écriture
Comment utiliser les blocs et les éléments en ligne pour créer une mise en page qui fonctionnera quelle que soit l’orientation de la langue ?
La solution consiste à ne pas s’appuyer sur les côtés gauche et droite de la ligne, mais à utiliser des points de référence qui correspondent au début et à la fin de sens d’écriture.
Et ces propriétés sont intégrées à CSS, et même si elles sont encore considérées comme expérimentales, elles sont assez bien supportées par tous les principaux navigateurs.
Lorsque vous devez spécifier une marge horizontale sans tenir compte de la direction d’écriture du texte, vous devez utiliser les propriétés suivantes :
- ‘margin-inline-start’ : spécifie les marges sur le côté où commence le conteneur : à gauche pour LTR, à droite pour RTL.
- “margin-inline-end” spécifie les marges du côté où le conteneur s’arrête : à droite sur LTR, à gauche sur RTL.
- ‘margin-inline’ raccourci pour spécifier les marges de début et de fin. Accepte une ou deux valeurs.
Nous pouvons donc simplifier notre premier exemple en utilisant cette propriété.
.card-item {
/* Pas de gauche/droite, il suffit de respecter la direction du texte */
margin-inline-end: 2rem;
}
La direction de gauche à droite fonctionne comme dans le premier exemple.
La même règle CSS est appliquée correctement lorsque le texte s’écoule de la droite vers la gauche.
C’est ainsi qu’une seule règle CSS peut gérer les marges dans toutes les directions du texte.
Nous venons de voir dans l’exemple précédent que nous pouvons remplacer les marges de gauche et de droite par quelque chose de plus générique : les marges du début (start) et de la fin (end) d’écriture.
Contrairement aux positions qui explicitent la gauche et la droite, ces derniers sont définis par le sens de l’écriture du texte pour se positionner.
Présentation en ligne
Les marges ne représentent que l’espace autour d’un élément. Et vous avez probablement deviné que le CSS donne le même type de propriétés pour tous les constituants de la mise en page en ligne :
- marges
- bordures
- paddings
Disposition en blocs
Ce que le CSS a fait pour les éléments en ligne et les propriétés sur l’axe horizontal est également disponible pour les éléments en bloc et les propriétés verticales.
Voici une variante verticale pour nos cartes :
- chaque carte est désormais un bloc avec une largeur maximale, centré horizontalement ;
- la première carte est alignée sur le dessus du conteneur ;
- chaque carte est séparée des autres par un espace vertical.
Dans cet exemple, la modification des règles CSS est simple.
/* Dans ce conteneur, les cartes sont empilées verticalement */
.card-column > .card-item {
display: block;
max-width: 12rem;
margin-inline: auto;
margin-block: 0 2rem;
}
Comme vous pouvez le voir, il n’y a pas de margin-top
ou margin-bottom
dans ce code, mais une propriété générique margin-block
, qui définit des valeurs combinées pour les propriétés margin-block-start
et margin-block-end
.
En règle générale, vous pouvez remplacer «top» par «block-start» et «bottom» par «block-end» dans les noms de propriétés pour margin, border, padding afin d’utiliser des propriétés indépendantes du sens d’écriture.
C’est un ajout intéressant pour la symétrie des noms, mais qui ne semble pas avoir grand-chose à voir avec la direction du texte LTR ou RTL. Néanmoins, c’est aussi un moyen de soutenir des conceptions plus capables, plus portables et plus créatives.
Au cas où vous ne le sauriez pas, il existe une propriété ‘writing-mode’ qui permet de spécifier si le texte est écrit horizontalement ou verticalement, ainsi que la direction du texte (LTR ou RTL).
Qu’en est-il de vos conteneurs préférés ?
Conteneur flex
Le conteneur flex respecte le sens de l’écriture du texte et le contenu s’écoule en conséquence.
Dans l’exemple suivant :
- la ligne est maintenant un conteneur flexible ;
- l’espacement des éléments est géré à l’aide de la propriété
gap
; - le contenu est justifié à la fin de la ligne flexible ;
- les marges sont supprimées sur les cartes pour laisser la place à l’espacement.
.flex-row {
display: flex;
flex-direction: row;
justify-content: end;
gap: 2rem;
}
.card-item {
margin-inline: 0;
margin-block: 0;
}
Conteneur de grille
Comme pour le conteneur flex, la grille respecte également le sens d’écriture du texte.
Dans l’exemple ci-dessous :
- les cartes sont placées dans une grille de 3 colonnes ;
- un espace est spécifié pour ajouter de l’espace entre les éléments.
Pour finir
Si vous devez prendre en charge les langues écrites de gauche à droite et celles écrites de droite à gauche, vous devez éviter de spécifier des marges de gauche ou de droite dans votre CSS. En vous appuyant sur les propriétés de début et de fin, vous serez en mesure de construire une mise en page capable de s’adapter à n’importe quelle direction de langue, à la fois horizontalement et verticalement.
Ne partez pas du principe que toutes les mises en page se font de gauche à droite. Il est courant de modifier la mise en page pour l’adapter aux spécificités de la langue.
Vous devriez consulter les directives des principaux fournisseurs :
Un dernier exemple serait celui d’un bouton avec une icône et une étiquette de texte. Pour un langage de gauche à droite, l’icône est affichée devant l’étiquette dans le sens de la lecture.
Mais dans le cas d’un texte rédigé de droite à gauche, l’icône se trouve toujours devant l’étiquette dans le sens de la lecture.
Cela se fait sans CSS spécial, uniquement en utilisant des propriétés neutres vis à vis de la direction du texte et en s’appuyant sur le comportement naturel d’un conteneur flex.
Dans les deux scénarios, le HTML est le même à l’exception de la valeur de l’attribut dir
sur le div contenant.
<div dir="rtl">
<button class="btn" type="button">
<img class="btn__icon" src="gear-icon.svg" alt="gear"/>
<span class="btn__label">Action</span>
</button>
</div>
En revanche, l’utilisation d’une feuille de style CSS neutre permet au navigateur de gérer la mise en page en fonction des contraintes imposées par la direction du texte.
.btn {
display: flex;
align-items: center;
gap: .5rem;
margin-block: .5rem;
margin-inline: 1rem;
border: 2px solid black;
border-radius: .25rem;
padding-inline: 1rem;
padding-block: .25rem;
font-size: 1.2rem;
}
Ces propriétés neutres vous aident à écriture du HTML et du CSS adaptatifs. Vous vous appuyez alors sur la véritable nature déclarative de ces langages, au lieu d’appliquer une définition plus impérative de la mise en page.
Le HTML et les CSS reflètent ce que vous voulez, et non la manière dont cela doit être mis en œuvre.
Il y a bien plus que la direction horizontale du texte. Les feuilles de style CSS prennent également en charge le texte écrit à la verticale, avec une variété de combinaisons. Mais ce sera le sujet d’un tout autre article.