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.
À l'intérieur d'un conteneur, chaque bloc prend une rangée complète et remplit son conteneur de haut en bas.
Blocs empilés verticalement, de haut en bas

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.

À l'intérieur d'un bloc, chaque élément en ligne prend la largeur requise par le contenu et remplit son conteneur de gauche à droite.
Empilement horizontal d'éléments en ligne, de gauche à droite

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.

À l'intérieur d'un bloc écrit de droite à gauche, chaque élément en ligne prend la largeur requise par son contenu et remplit son conteneur de la droite vers la gauche.
Alignement horizontal d'éléments en ligne, de droite à gauche

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;
}
Carte 1
Carte 2
Carte 3

Cela vous convient-il ? Essayons de passer à un mode d’écriture RTL (right-to-left, de droite à gauche).

Carte 1
Carte 2
Carte 3

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;
}
Carte 1
Carte 2
Carte 3

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.
Deux conteneurs, l'un avec une écriture de gauche à droite, l'autre de droite à gauche. Sur chacun, une flèche indique le sens d'écriture du texte et des marqueurs de «début» et de «fin» sont placés de chaque côté : début à gauche pour les conteneurs allant de gauche à droite, à droite pour les conteneurs allant de droite à gauche.
Points de références indépendants de la direction du texte

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.

Carte 1
Carte 2
Carte 3

La même règle CSS est appliquée correctement lorsque le texte s’écoule de la droite vers la gauche.

Carte 1
Carte 2
Carte 3

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
Diagramme global des marges, des bordures, des paddings (espace internes) et du contenu d'un élément avec la légende positionnant chaque propriété de début et de fin à gauche ou à droite, selon la direction LTR ou RTL.
Points de référence en ligne et propriétés CSS

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.
Carte 1
Carte 2
Carte 3

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.
dir="ltr"
Carte 1
Carte 2
Carte 3
dir="rtl"
Carte 1
Carte 2
Carte 3
.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.
dir="ltr"
Carte 1
Carte 2
Carte 3
Carte 4
Carte 5
dir="rtl"
Carte 1
Carte 2
Carte 3
Carte 4
Carte 5

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.