# General Translation Knowledge Base: Comment prendre en charge les langues RTL (right-to-left) en CSS ?
URL: https://generaltranslation.com/fr/kb/right-to-left-css.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Placez dir="rtl" et lang sur l’élément html, car lang seul ne modifie pas le sens d’écriture, puis remplacez les propriétés CSS physiques comme margin-left par des propriétés logiques comme margin-inline-start. Les lignes flex, les colonnes de grille et l’alignement du texte par défaut s’inversent automatiquement ; ce n’est pas le cas de translateX(), left et right.
Category: Formatage selon les paramètres régionaux
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

L’arabe, l’hébreu, le persan et l’ourdou se lisent de droite à gauche. Dès que le document déclare ce sens d’écriture, le navigateur se charge lui-même d’inverser les lignes flex, les colonnes de grille et l’alignement du texte par défaut. La plupart des bugs RTL viennent de règles CSS qui font référence à un côté physique : `left`, `right`, `margin-left`, `translateX`.

## Définir le sens d’écriture en HTML

Indiquez le sens d’écriture et la langue sur l’élément racine :

```html
<html lang="ar" dir="rtl">
```

Les [recommandations du W3C sur le sens du texte](https://www.w3.org/International/questions/qa-html-dir) préconisent de déclarer le sens d’écriture de base dans le balisage, et non avec la propriété CSS `direction`, afin qu’il soit conservé même si les styles ne se chargent pas ; la [référence MDN sur `direction`](https://developer.mozilla.org/en-US/docs/Web/CSS/direction) va dans le même sens. L’attribut `lang` ne définit pas le sens d’écriture, même avec une sous-balise de système d’écriture comme `ar-Arab` : il vous faut donc les deux. N’ajoutez `dir` plus loin dans la page que lorsqu’un bloc change de sens d’écriture, par exemple une citation en anglais dans un article en arabe.

Pour déduire `dir` d’un code de langue en JavaScript, la méthode [`getTextInfo()` d’`Intl.Locale`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo) renvoie le sens d’écriture : `new Intl.Locale('ar').getTextInfo().direction` vaut `'rtl'`. Chrome 130, Safari 17 et Firefox 153 la prennent en charge, tandis que Chrome 99 à 129 expose les mêmes données via une propriété `textInfo` ; prévoyez donc une solution de secours pour les navigateurs plus anciens.

## Quelle approche choisir pour inverser la mise en page ?

Une fois le sens d’écriture défini, il reste à faire en sorte que la feuille de style le respecte. Il existe pour cela quatre méthodes courantes :

| Approche                                                                                       | Inversion de la mise en page                                                       | Maintenance                                                  | Risque principal                                                        |
| ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------ | ----------------------------------------------------------------------- |
| CSS `direction: rtl` au lieu de `dir`                                                          | Le texte et les propriétés logiques s’inversent, mais pas les propriétés physiques | Faible                                                       | `:dir()` l’ignore, et le sens d’écriture disparaît sans CSS             |
| Feuille de style RTL distincte, écrite à la main ou générée avec [RTLCSS](https://rtlcss.com/) | Une seconde feuille de style permute les côtés physiques                           | Deux feuilles de style à livrer et à maintenir synchronisées | Les surcharges divergent à mesure que les styles LTR évoluent           |
| Attribut `dir` et propriétés logiques CSS                                                      | Chaque propriété se résout vers le bon côté à partir de `dir`                      | Une seule feuille de style                                   | Des propriétés physiques qui se réintroduisent au fil des modifications |
| Utilitaires logiques de Tailwind CSS et variantes `rtl:` et `ltr:`                             | Les utilitaires sont compilés en propriétés logiques                               | Un seul ensemble de classes                                  | Des variantes utilisées là où un utilitaire logique suffirait           |

Utilisez les propriétés logiques (directement ou via Tailwind) pour le nouveau code et pour tout composant que vous modifiez : une seule feuille de style suffit pour les deux sens d’écriture. Optez pour une feuille de style RTL générée lorsqu’une base de code héritée volumineuse regorge de `left` et de `right` et que vous avez besoin du RTL avant de pouvoir la refactoriser.

## Construire la mise en page avec les propriétés logiques

Les [propriétés logiques CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values) désignent les côtés selon le sens d&#39;écriture : inline-start correspond à la gauche en LTR et à la droite en RTL. Elles ont le statut « Baseline widely available » ; `inset-inline-start`, par exemple, est pris en charge par tous les navigateurs depuis avril 2021. Voici une carte, avant et après :

```css
/* Avant : les côtés physiques ne bougent pas en RTL */
.card {
  margin-left: 16px;
  padding-right: 24px;
  text-align: left;
  border-left: 4px solid var(--accent);
  border-top-left-radius: 8px;
}
.card .badge {
  position: absolute;
  top: 8px;
  right: 8px;
}

/* Après : les côtés logiques s'inversent en fonction de dir */
.card {
  margin-inline-start: 16px;
  padding-inline-end: 24px;
  text-align: start;
  border-inline-start: 4px solid var(--accent);
  border-start-start-radius: 8px;
}
.card .badge {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 8px;
}
```

Dans une page avec `dir="rtl"`, `margin-inline-start: 16px` donne une marge droite de 16 px, et `border-start-start-radius` arrondit le coin supérieur droit. Utilisez `margin-inline` et `padding-inline` pour définir en une seule fois les deux côtés de l&#39;axe en ligne.

### Ce qui s’inverse automatiquement

* **Lignes Flexbox :** avec `flex-direction: row`, le premier élément se place contre le bord droit.
* **Colonnes de grille :** la colonne 1 est celle située le plus à droite.
* **Alignement du texte :** la valeur initiale de `text-align` est `start`, si bien que le texte non stylé s’aligne à droite.
* **Contenu en ligne et colonnes de tableau :** tous deux suivent le sens d’écriture de base.

### Ce qui ne s&#39;inverse pas

* `left` et `right` sur les éléments positionnés : `left: 0` reste à gauche.
* `margin-left`, `padding-right`, `border-left`, `float: left` et `text-align: left`.
* `transform: translateX()` : une valeur positive déplace toujours vers la droite, si bien que les tiroirs coulissants et les carrousels défilent dans le mauvais sens.
* `background-position: left`, `linear-gradient(to right, …)` et le décalage horizontal de `box-shadow`. Ces valeurs n&#39;ont pas d&#39;équivalent logique : remplacez-les donc sous `:dir(rtl)`.

Pour les transformations, inversez le signe à l&#39;aide d&#39;une propriété personnalisée :

```css
:root { --inline-sign: 1; }
:root:dir(rtl) { --inline-sign: -1; }

/* Un tiroir qui se masque en sortant par son bord inline-start */
.drawer[data-state="closed"] {
  transform: translateX(calc(-100% * var(--inline-sign)));
}
```

### Tailwind CSS

Dans Tailwind CSS v4.3, les utilitaires logiques sont `ms-*` et `me-*` (marge), `ps-*` et `pe-*` (padding), `inset-s-*` et `inset-e-*`, `text-start`, `border-s-*` et `rounded-s-*` ; ils sont répertoriés sur la page de chaque utilitaire, par exemple [margin](https://tailwindcss.com/docs/margin). Les [variantes `rtl:` et `ltr:`](https://tailwindcss.com/docs/hover-focus-and-other-states#rtl-support) sont compilées en sélecteurs incluant `:dir()`, si bien que `ltr:` s&#39;applique aussi aux pages qui ne définissent jamais `dir="ltr"`. Privilégiez `ms-3` plutôt que `ltr:ml-3 rtl:mr-3`, et réservez les variantes aux transformations et aux icônes, comme `rtl:-scale-x-100`.

## Gérer les icônes, le texte bidirectionnel et les polices

### Inverser uniquement les icônes directionnelles

Retournez une icône horizontalement en mode RTL :

```css
.icon-directional:dir(rtl) {
  transform: scaleX(-1);
}
```

La [pseudo-classe `:dir()`](https://developer.mozilla.org/en-US/docs/Web/CSS/:dir) cible le sens d’écriture dont un élément hérite, tandis que `[dir="rtl"]` ne cible que l’élément qui porte l’attribut. `:dir()` est disponible dans tous les navigateurs depuis décembre 2023 et a désormais le statut Baseline Widely available. Si vous devez prendre en charge des navigateurs plus anciens, utilisez plutôt `[dir="rtl"] .icon-directional`.

Les [recommandations right-to-left](https://developer.apple.com/design/human-interface-guidelines/right-to-left) d&#39;Apple constituent un bon ensemble de règles, y compris pour le web :

* **À inverser :** les flèches retour et avance, les commandes suivant et précédent, les barres de progression et les curseurs, les icônes représentant des lignes de texte et celles qui évoquent un mouvement vers l&#39;avant.
* **À ne pas inverser :** les logos, les symboles universels comme la coche, les objets physiques comme les horloges, les outils dessinés pour les droitiers, ainsi que les photos et illustrations.
* **Ne jamais inverser les chiffres :** un numéro de téléphone ou le nombre 541 se lit dans le même ordre dans toutes les langues.

### Isoler le texte bidirectionnel

Lorsque du texte RTL et du texte LTR partagent une même ligne, les caractères neutres tels que les espaces, les traits d’union et les chiffres peuvent se rattacher au mauvais côté ; le [guide du W3C sur le balisage bidi intégré](https://www.w3.org/International/articles/inline-bidi-markup/) appelle ce phénomène « spillover » (débordement). Dans l’[exemple `<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi) de MDN, un nom arabe suivi de « - 1st place » s’affiche avec le « 1 » à la mauvaise extrémité. Encapsulez chaque valeur dont le sens d’écriture diffère de celui du texte qui l’entoure :

```html
<!-- Un nom issu de votre base de données, sens d’écriture inconnu -->
<li><bdi>اَلأَعْشَى</bdi> - 1st place</li>

<!-- Une valeur toujours en LTR dans un texte arabe -->
<p>اتصل بنا على <span dir="ltr">+1 (555) 010-2030</span></p>

<!-- Texte saisi par l’utilisateur, sens d’écriture inconnu -->
<textarea dir="auto"></textarea>
```

`<bdi>` se comporte comme `dir="auto"` : il déduit son sens d’écriture du premier caractère fort. Utilisez `dir="ltr"` sur les valeurs toujours écrites de gauche à droite (left-to-right) : numéros de téléphone, adresses e-mail, URL et numéros de commande. La propriété CSS `unicode-bidi: isolate` assure la même isolation depuis une feuille de style, mais MDN [déconseille aux auteurs de redéfinir `unicode-bidi`](https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi) ; privilégiez donc `dir` et `<bdi>` dans le balisage.

### Polices

* **Couvrez le système d’écriture.** Appliquez, par langue, une police comportant des glyphes arabes ou hébreux : `:lang(ar) { font-family: "Noto Sans Arabic", system-ui, sans-serif; }`.
* **N’espacez pas les lettres en arabe.** Ses lettres sont liées entre elles, et la [spécification CSS Text](https://www.w3.org/TR/css-text-3/) recommande aux auteurs d’éviter `letter-spacing` sur les écritures cursives, dont le rendu n’est pas interopérable.
* **Compensez l’effet des capitales.** L’arabe et l’hébreu ne connaissent pas les majuscules : à leurs côtés, du texte latin tout en capitales paraît donc plus grand. Apple suggère d’augmenter d’environ 2 points la taille de la police RTL.

## Bugs RTL courants et solutions

### La page est traduite, mais s&#39;affiche toujours de gauche à droite

**Cause :** la page traduite définit `lang="ar"` sans `dir`, ou applique `direction: rtl` à un conteneur interne. **Solution :** définissez `dir="rtl"` sur `<html>` en fonction de la locale active à chaque affichage, y compris pour le HTML server-rendered.

### L&#39;espacement se retrouve du mauvais côté des icônes et des libellés

**Cause :** un `margin-left` ou un `padding-right` entre une icône et son texte. **Correctif :** passez à `margin-inline-end` ou au `me-*` de Tailwind, ou utilisez `gap` dans un conteneur flex : cette propriété n&#39;est liée à aucun côté.

Mesures effectuées dans Chrome 155 sur un bouton inline-flex doté d&#39;une icône de 16px placée avant son libellé : en texte right-to-left, la marge physique ne laisse aucun espace et repousse ses 8px vers le bord extérieur, tandis que la marge logique passe du côté tourné vers le libellé :

```text title="Output"
.icon { margin-right: 8px }        ltr: 8px gap   rtl: 0px gap
.icon { margin-inline-end: 8px }   ltr: 8px gap   rtl: 8px gap (computed as margin-left)
```

### Les badges, infobulles et listes déroulantes s’ouvrent du mauvais côté

**Cause :** `position: absolute` avec `left` ou `right`, ou une bibliothèque de positionnement JavaScript qui effectue ses calculs depuis la gauche. **Correctif :** utilisez `inset-inline-start` et `inset-inline-end`, et transmettez le sens d’écriture à la bibliothèque de positionnement si elle le permet.

### Les tiroirs et carrousels glissent dans le mauvais sens

**Cause :** `translateX()` est une fonction physique. **Solution :** multipliez la valeur par un signe qui dépend du sens d’écriture, comme dans l’exemple de tiroir ci-dessus, et testez les gestes de balayage en RTL.

### La flèche de retour pointe vers l’avant, ou le logo est inversé

**Cause :** les icônes sont inversées en bloc, sans distinction. **Correctif :** n’inversez que les icônes directionnelles.

### La ponctuation ou les nombres se retrouvent à l’autre extrémité de la ligne

**Cause :** une valeur insérée dont le sens d’écriture diffère de celui du texte qui l’entoure, comme un nom d’utilisateur, un nom de produit ou un numéro de téléphone. **Solution :** encapsulez-la dans `<bdi>`, ou dans un élément avec `dir="ltr"` si vous savez qu’elle s’écrit en left-to-right.

### Les lettres arabes apparaissent détachées

**Cause :** un `letter-spacing` global prévu pour les titres en caractères latins. **Solution :** réinitialisez `letter-spacing` à 0 pour `:lang(ar)` et les autres systèmes d’écriture cursifs.

Pour repérer ces bugs avant même que les traductions n’existent, parcourez l’application avec un [pseudo-paramètre régional](/kb/pseudo-localization) right-to-left, puis effectuez la vérification right-to-left de la [checklist de lancement d’une application multilingue](/kb/multilingual-app-launch-checklist) avant la mise en production.

## Définir dir à partir de la locale active avec General Translation

Dans une application Next.js utilisant l’App Router, `gt-next` expose [`getLocaleDirection`](/docs/react/nextjs/reference/functions/get-locale-direction) depuis `gt-next/server`, ce qui permet à la mise en page racine de définir `lang` et `dir` côté serveur. Dans cet exemple, on part du principe que `app/[locale]/layout.tsx` est la mise en page racine, qui, comme l’exige Next.js, doit [afficher à la fois `<html>` et `<body>`](https://nextjs.org/docs/app/api-reference/file-conventions/layout#root-layout) :

```tsx title="app/[locale]/layout.tsx"
import { getLocale, getLocaleDirection } from 'gt-next/server';
import type { ReactNode } from 'react';

export default async function LocaleLayout({ children }: { children: ReactNode }) {
  const [locale, direction] = await Promise.all([
    getLocale(),
    getLocaleDirection(),
  ]);
  return (
    <html lang={locale} dir={direction}>
      <body>{children}</body>
    </html>
  );
}
```

Dans les composants `gt-react`, `gt-next` et `gt-react-native`, le hook [`useLocaleDirection`](/docs/react/reference/hooks/use-locale-direction) renvoie `'ltr'` ou `'rtl'` pour la locale active. Sur le web, reportez cette valeur dans `document.documentElement.dir` depuis un composant de votre arborescence. React Native ne dispose pas de `document` : le sens de mise en page natif est géré par l&#39;[`I18nManager`](https://reactnative.dev/docs/i18nmanager) de React Native, et toute modification via `allowRTL` ou `forceRTL` ne prend effet qu&#39;au prochain démarrage de l&#39;application. Pour les autres stacks, notamment Vue, `gt-tanstack-start` et les modèles côté serveur, la fonction [`getLocaleDirection`](/docs/platform/core/reference/utility-functions/locales/get-locale-direction) de la bibliothèque Core, fournie par `generaltranslation`, s&#39;exécute localement sans clé API et renvoie `'rtl'` pour des codes tels que `ar-SA`, `he-IL` ou `fa`. Dans tous les cas, votre CSS doit tout de même appliquer les propriétés logiques et les règles d&#39;icônes présentées plus haut.

## Points clés

* Placez `lang` et `dir="rtl"` sur `<html>` : `lang` seul ne modifie pas le sens d’écriture, et ce n’est pas à la propriété CSS `direction` de le définir.
* Les lignes flex, les colonnes de grille et l’alignement de texte par défaut s’inversent automatiquement, contrairement à `left`, `right`, `margin-left`, `translateX()`, `background-position` et aux décalages d’ombre.
* Remplacez les propriétés physiques par des propriétés logiques (`margin-inline-start`, `inset-inline-end`, `text-align: start`, `border-start-start-radius`), ou par les classes Tailwind `ms-*`, `ps-*` et `inset-s-*`.
* Inversez les flèches et les indicateurs de progression avec `:dir(rtl)`, mais jamais les logos, les coches ni les horloges, et encapsulez les valeurs à sens d’écriture mixte dans `<bdi>` ou `dir="ltr"`.
* Dans les SDK de General Translation, définissez `dir` à partir de [`getLocaleDirection`](/docs/react/nextjs/reference/functions/get-locale-direction) (code serveur Next.js ou bibliothèque Core) ou de `useLocaleDirection` (React).

## Related questions

- [Liste de contrôle des tests de localisation pour les applications multilingues](https://generaltranslation.com/fr/kb/multilingual-app-launch-checklist.mdx): Testez neuf points dans chaque paramètre régional pris en charge sur une compilation de Production : les parcours complets, y compris les états d’erreur et les e-mails, le changement de langue, les formes plurielles, la devise et les fuseaux horaires, le foisonnement du texte, la mise en page right-to-left, l’accessibilité, la distribution des traductions et des URL de langue explorables. Associez à chaque vérification un critère de réussite explicite.
- [Qu’est-ce que la pseudo-localisation ?](https://generaltranslation.com/fr/kb/pseudo-localization.mdx): La pseudo-localisation est un test qui remplace votre texte source par une version modifiée, accentuée, allongée d’environ 40 % et encadrée de crochets, afin de faire apparaître les chaînes codées en dur, les troncatures, les polices défaillantes et les phrases concaténées avant même qu’une traduction n’existe. Android propose à cet effet les pseudo-paramètres régionaux en-XA et ar-XB.
- [Comment gérer les formes plurielles dans React ?](https://generaltranslation.com/fr/kb/how-to-handle-plurals-in-react.mdx): Pour gérer les formes plurielles dans React, fournissez à chaque langue une phrase par forme du pluriel et sélectionnez-la selon les règles de pluriel de cette langue, car l’anglais compte 2 formes, le russe 4 et l’arabe 6. Le composant `<Plural>` de General Translation, disponible dans gt-react et gt-next, prend vos formes source, et General Translation génère les formes requises par chaque langue cible.
- [Peut-on faire de l’i18n sans fichiers de traduction ?](https://generaltranslation.com/fr/kb/i18n-without-translation-files.mdx): Oui. Les bibliothèques gt-react et gt-next de General Translation permettent d’internationaliser React et Next.js sans clés de traduction ni fichier JSON par langue à maintenir. Le texte reste intégré au JSX, dans le composant `<T>`, et la commande gt translate génère les traductions de chaque langue lors de la compilation, en s’appuyant sur le contexte de votre code. Locadex peut les tenir à jour via des pull requests.

## Previous and next questions

- Previous question: [Comment nommer les clés de traduction i18n ?](https://generaltranslation.com/fr/kb/i18n-key-naming.mdx)
- Next question: [Comment rendre un site web multilingue ?](https://generaltranslation.com/fr/kb/make-website-multilingual.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/fr/kb/sitemap.md) for every article.
