# General Translation Knowledge Base: Come si supportano le lingue RTL (right-to-left) in CSS?
URL: https://generaltranslation.com/it/kb/right-to-left-css.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Imposta dir="rtl" e lang sull'elemento html, perché lang da solo non cambia la direzione, poi sostituisci le proprietà CSS fisiche come margin-left con proprietà logiche come margin-inline-start. Le righe flex, le colonne della griglia e l'allineamento predefinito del testo si invertono da sole; translateX(), left e right no.
Category: Formattazione per impostazione regionale
Last updated: 2026-10-20
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-20

L&#39;arabo, l&#39;ebraico, il persiano e l&#39;urdu si leggono da destra a sinistra. Una volta che il documento dichiara questa direzione, il browser inverte già automaticamente le righe flex, le colonne della griglia e l&#39;allineamento predefinito del testo. La maggior parte dei bug RTL nasce da regole CSS che fanno riferimento a un lato fisico: `left`, `right`, `margin-left`, `translateX`.

## Impostare la direzione in HTML

Specifica la direzione e la lingua sull&#39;elemento radice:

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

Le [indicazioni del W3C sulla direzione del testo](https://www.w3.org/International/questions/qa-html-dir) raccomandano di dichiarare la direzione di base nel markup, anziché con la proprietà CSS `direction`, così da preservarla anche quando gli stili non vengono caricati; il [riferimento MDN su `direction`](https://developer.mozilla.org/en-US/docs/Web/CSS/direction) è dello stesso avviso. L&#39;attributo `lang` non imposta la direzione, nemmeno con un subtag del sistema di scrittura come `ar-Arab`, quindi servono entrambi. Aggiungi `dir` a livelli più interni della pagina solo quando un blocco cambia direzione, ad esempio una citazione in inglese all&#39;interno di un articolo in arabo.

Per ricavare `dir` da un codice locale in JavaScript, [`getTextInfo()` di `Intl.Locale`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/getTextInfo) restituisce la direzione: `new Intl.Locale('ar').getTextInfo().direction` è `'rtl'`. Il metodo è supportato da Chrome 130, Safari 17 e Firefox 153, mentre le versioni di Chrome dalla 99 alla 129 espongono gli stessi dati tramite la proprietà `textInfo`, quindi prevedi un fallback per i browser meno recenti.

## Quale approccio usare per invertire il layout?

Una volta impostata la direzione, bisogna fare in modo che il foglio di stile la rispetti. Ci sono quattro modi comuni per farlo:

| Approccio                                                                                 | Come si inverte il layout                                             | Manutenzione                                                | Rischio principale                                                    |
| ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------- |
| CSS `direction: rtl` al posto di `dir`                                                    | Il testo e le proprietà logiche si invertono; le proprietà fisiche no | Bassa                                                       | `:dir()` lo ignora e, senza CSS, la direzione va persa                |
| Foglio di stile RTL separato, scritto a mano o generato con [RTLCSS](https://rtlcss.com/) | Un secondo foglio di stile scambia i lati fisici                      | Due fogli di stile da distribuire e mantenere sincronizzati | Le sovrascritture si disallineano man mano che cambiano gli stili LTR |
| Attributo `dir` più proprietà logiche CSS                                                 | Ogni proprietà si risolve nel lato corretto in base a `dir`           | Un solo foglio di stile                                     | Proprietà fisiche che si reintroducono con le modifiche successive    |
| Utility logiche di Tailwind CSS più varianti `rtl:` e `ltr:`                              | Le utility vengono compilate in proprietà logiche                     | Un solo insieme di classi                                   | Varianti usate dove basterebbe una utility logica                     |

Usa le proprietà logiche (direttamente o tramite Tailwind) per il nuovo codice e per ogni componente che modifichi: un solo foglio di stile vale per entrambe le direzioni. Ricorri a un foglio di stile RTL generato quando una vasta base di codice legacy è piena di `left` e `right` e ti serve il supporto RTL prima di poterla rifattorizzare.

## Scrivere il layout con le proprietà logiche

Le [proprietà logiche CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values) indicano i lati in base al flusso del testo: inline-start corrisponde alla sinistra in LTR e alla destra in RTL. Hanno lo stato Baseline &quot;Widely available&quot;: `inset-inline-start`, ad esempio, funziona su tutti i browser da aprile 2021. Ecco una card prima e dopo:

```css
/* Prima: i lati fisici non cambiano in 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;
}

/* Dopo: i lati logici si invertono in base a 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;
}
```

In una pagina con `dir="rtl"`, `margin-inline-start: 16px` corrisponde a un margine destro di 16px e `border-start-start-radius` arrotonda l&#39;angolo in alto a destra. Usa `margin-inline` e `padding-inline` per impostare entrambi i lati inline in un&#39;unica dichiarazione.

### Cosa si inverte automaticamente

* **Righe flexbox:** con `flex-direction: row`, il primo elemento si posiziona sul bordo destro.
* **Colonne della griglia:** la colonna 1 è quella più a destra.
* **Allineamento del testo:** il valore iniziale di `text-align` è `start`, quindi il testo senza stili viene allineato a destra.
* **Contenuto inline e colonne delle tabelle:** entrambi seguono la direzione di base.

### Cosa non si inverte

* `left` e `right` sugli elementi posizionati: `left: 0` resta a sinistra.
* `margin-left`, `padding-right`, `border-left`, `float: left` e `text-align: left`.
* `transform: translateX()`: un valore positivo sposta sempre verso destra, quindi i drawer e i caroselli a scorrimento si muovono nella direzione sbagliata.
* `background-position: left`, `linear-gradient(to right, …)` e l&#39;offset orizzontale di `box-shadow`. Questi valori non hanno un equivalente logico, quindi sovrascrivili sotto `:dir(rtl)`.

Per le trasformazioni, inverti il segno con una custom property:

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

/* Un drawer che si nasconde oltre il bordo inline-start */
.drawer[data-state="closed"] {
  transform: translateX(calc(-100% * var(--inline-sign)));
}
```

### Tailwind CSS

In Tailwind CSS v4.3, le utility logiche sono `ms-*` e `me-*` (margin), `ps-*` e `pe-*` (padding), `inset-s-*` e `inset-e-*`, `text-start`, `border-s-*` e `rounded-s-*`; sono elencate nella pagina di ciascuna utility, ad esempio quella di [margin](https://tailwindcss.com/docs/margin). Le [varianti `rtl:` e `ltr:`](https://tailwindcss.com/docs/hover-focus-and-other-states#rtl-support) vengono compilate in selettori che includono `:dir()`, quindi `ltr:` corrisponde anche alle pagine che non impostano mai `dir="ltr"`. Usa `ms-3` anziché `ltr:ml-3 rtl:mr-3` e riserva le varianti a trasformazioni e icone, ad esempio `rtl:-scale-x-100`.

## Gestire icone, testo bidirezionale e font

### Rifletti solo le icone direzionali

Capovolgi orizzontalmente un&#39;icona con layout RTL:

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

La [pseudo-classe `:dir()`](https://developer.mozilla.org/en-US/docs/Web/CSS/:dir) corrisponde alla direzione ereditata da un elemento, mentre `[dir="rtl"]` corrisponde solo all&#39;elemento su cui è impostato l&#39;attributo. `:dir()` è supportata da tutti i browser da dicembre 2023 ed è ora Baseline widely available. Se devi supportare browser meno recenti, usa invece `[dir="rtl"] .icon-directional`.

Le [linee guida right-to-left](https://developer.apple.com/design/human-interface-guidelines/right-to-left) di Apple sono un valido insieme di regole anche per il web:

* **Da specchiare:** frecce avanti e indietro, controlli successivo e precedente, barre di avanzamento e slider, icone che raffigurano righe di testo e icone che indicano un movimento in avanti.
* **Da non specchiare:** logo, simboli universali come il segno di spunta, oggetti fisici come gli orologi, strumenti disegnati per chi usa la mano destra, foto e illustrazioni.
* **Non invertire mai le cifre:** un numero di telefono o il numero 541 si leggono nello stesso ordine in qualsiasi lingua.

### Isolare il testo bidirezionale

Quando testo RTL e LTR condividono la stessa riga, i caratteri neutri come spazi, trattini e numeri possono agganciarsi al lato sbagliato: la [guida al markup bidi inline](https://www.w3.org/International/articles/inline-bidi-markup/) del W3C chiama questo fenomeno spillover. Nell&#39;[esempio di `<bdi>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdi) di MDN, un nome arabo seguito da &quot;- 1st place&quot; viene renderizzato con l&#39;&quot;1&quot; all&#39;estremità sbagliata. Racchiudi ogni valore la cui direzione è diversa da quella del testo circostante:

```html
<!-- Un nome proveniente dal tuo database, direzione sconosciuta -->
<li><bdi>اَلأَعْشَى</bdi> - 1st place</li>

<!-- Un valore sempre LTR all'interno di un testo arabo -->
<p>اتصل بنا على <span dir="ltr">+1 (555) 010-2030</span></p>

<!-- Testo digitato dall'utente, direzione sconosciuta -->
<textarea dir="auto"></textarea>
```

`<bdi>` si comporta come `dir="auto"`, ricavando la propria direzione dal primo carattere forte. Usa `dir="ltr"` per i valori che sono sempre left-to-right: numeri di telefono, indirizzi email, URL e ID degli ordini. La proprietà CSS `unicode-bidi: isolate` applica lo stesso isolamento da un foglio di stile, ma MDN [sconsiglia agli autori di sovrascrivere `unicode-bidi`](https://developer.mozilla.org/en-US/docs/Web/CSS/unicode-bidi), quindi è preferibile usare `dir` e `<bdi>` direttamente nel markup.

### Font

* **Copri il sistema di scrittura.** Applica per lingua un font con glifi arabi o ebraici: `:lang(ar) { font-family: "Noto Sans Arabic", system-ui, sans-serif; }`.
* **Non applicare la spaziatura tra le lettere all&#39;arabo.** Le sue lettere sono legate tra loro e la [specifica CSS Text](https://www.w3.org/TR/css-text-3/) raccomanda agli autori di evitare `letter-spacing` sui sistemi di scrittura corsivi, perché i risultati non sono interoperabili.
* **Bilancia rispetto alle maiuscole.** L&#39;arabo e l&#39;ebraico non hanno maiuscole, quindi il testo latino tutto in maiuscolo accanto a essi sembra più grande; Apple suggerisce di aumentare di circa 2 punti la dimensione del font RTL.

## Bug RTL comuni e come risolverli

### La pagina è tradotta ma viene ancora visualizzata da sinistra a destra

**Causa:** la pagina tradotta imposta `lang="ar"` ma non `dir`, oppure imposta `direction: rtl` su un contenitore interno. **Soluzione:** imposta `dir="rtl"` su `<html>` in base al locale attivo a ogni rendering, compreso l&#39;HTML server-rendered.

### La spaziatura finisce sul lato sbagliato di icone ed etichette

**Causa:** `margin-left` o `padding-right` tra un&#39;icona e il relativo testo. **Soluzione:** passa a `margin-inline-end` o a `me-*` di Tailwind, oppure usa `gap` in un contenitore flex, che non ha alcun lato.

Da misurazioni in Chrome 155 su un pulsante inline-flex con un&#39;icona da 16px posta prima dell&#39;etichetta, nel testo right-to-left il margine fisico non lascia alcuno spazio e sposta i suoi 8px sul bordo esterno, mentre il margine logico si sposta sul lato rivolto verso l&#39;etichetta:

```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)
```

### Badge, tooltip e menu a discesa si aprono dal lato sbagliato

**Causa:** `position: absolute` con `left` o `right`, oppure una libreria JavaScript di posizionamento che calcola le coordinate partendo da sinistra. **Soluzione:** usa `inset-inline-start` e `inset-inline-end` e, se la libreria di posizionamento lo prevede, passale la direzione.

### Drawer e caroselli scorrono nella direzione sbagliata

**Causa:** `translateX()` usa coordinate fisiche. **Soluzione:** moltiplica il valore per un segno di direzione, come nell&#39;esempio del drawer visto sopra, e verifica i gesti di swipe in RTL.

### La freccia &quot;indietro&quot; punta in avanti, oppure il logo appare specchiato

**Causa:** le icone vengono capovolte in blocco, senza distinzioni. **Soluzione:** specchia solo le icone direzionali.

### La punteggiatura o i numeri finiscono all&#39;altra estremità della riga

**Causa:** un valore inserito con una direzione diversa da quella del testo circostante, come un nome utente, il nome di un prodotto o un numero di telefono. **Soluzione:** racchiudilo in `<bdi>`, oppure in un elemento con `dir="ltr"` se sai che è left-to-right.

### Le lettere arabe appaiono staccate

**Causa:** un `letter-spacing` globale pensato per i titoli in caratteri latini. **Soluzione:** reimposta `letter-spacing` a 0 per `:lang(ar)` e per gli altri sistemi di scrittura corsivi.

Per individuare questi bug prima ancora che esistano le traduzioni, naviga nell&#39;app con una [pseudo-impostazione regionale](/kb/pseudo-localization) right-to-left e, prima del lancio, esegui il controllo right-to-left previsto dalla [checklist per il lancio di un&#39;app multilingue](/kb/multilingual-app-launch-checklist).

## Impostare dir in base al locale attivo con General Translation

In un&#39;app Next.js con App Router, `gt-next` espone [`getLocaleDirection`](/docs/react/nextjs/reference/functions/get-locale-direction) da `gt-next/server`, in modo che il layout radice possa impostare `lang` e `dir` lato server. Questo esempio presuppone che il layout radice sia `app/[locale]/layout.tsx`, che secondo Next.js [deve renderizzare sia `<html>` sia `<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>
  );
}
```

Nei componenti di `gt-react`, `gt-next` e `gt-react-native`, l&#39;hook [`useLocaleDirection`](/docs/react/reference/hooks/use-locale-direction) restituisce `'ltr'` o `'rtl'` per il locale attivo. Sul web, assegna questo valore a `document.documentElement.dir` da un componente del tuo albero. React Native non dispone di `document`: la direzione del layout nativo è gestita dall&#39;[`I18nManager`](https://reactnative.dev/docs/i18nmanager) di React Native, e qualsiasi modifica tramite `allowRTL` o `forceRTL` ha effetto solo al successivo avvio dell&#39;app. Per altri stack, tra cui Vue, `gt-tanstack-start` e i template lato server, la funzione [`getLocaleDirection`](/docs/platform/core/reference/utility-functions/locales/get-locale-direction) della libreria Core, disponibile in `generaltranslation`, viene eseguita localmente senza bisogno di una chiave API e restituisce `'rtl'` per codici come `ar-SA`, `he-IL` e `fa`. In ogni caso, il tuo CSS deve comunque applicare le proprietà logiche e le regole per le icone descritte sopra.

## Punti chiave

* Imposta `lang` e `dir="rtl"` su `<html>`: `lang` da solo non cambia la direzione, e non bisogna affidarla alla proprietà CSS `direction`.
* Le righe flex, le colonne della griglia e l&#39;allineamento predefinito del testo si invertono automaticamente; `left`, `right`, `margin-left`, `translateX()`, `background-position` e gli offset delle ombre no.
* Sostituisci le proprietà fisiche con quelle logiche (`margin-inline-start`, `inset-inline-end`, `text-align: start`, `border-start-start-radius`) oppure con le classi `ms-*`, `ps-*` e `inset-s-*` di Tailwind.
* Usa `:dir(rtl)` per specchiare frecce e indicatori di avanzamento, ma mai loghi, segni di spunta od orologi, e racchiudi i valori con direzione mista in `<bdi>` o `dir="ltr"`.
* Negli SDK di General Translation, imposta `dir` con [`getLocaleDirection`](/docs/react/nextjs/reference/functions/get-locale-direction) (nel codice server di Next.js o nella libreria Core) oppure con `useLocaleDirection` (React).

## Related questions

- [Checklist per il test di localizzazione delle app multilingue](https://generaltranslation.com/it/kb/multilingual-app-launch-checklist.mdx): Verifica nove aspetti in ogni impostazione regionale supportata su una build di produzione: percorsi completi, inclusi gli stati di errore e le email, cambio di lingua, plurali, valuta e fusi orari, espansione del testo, layout right-to-left, accessibilità, distribuzione delle traduzioni e URL per lingua scansionabili. Assegna a ogni verifica un criterio di superamento esplicito.
- [Che cos'è la pseudo-localizzazione?](https://generaltranslation.com/it/kb/pseudo-localization.mdx): La pseudo-localizzazione è un test che sostituisce il testo di origine con una versione alterata, con caratteri accentati, allungata di circa il 40% e racchiusa tra parentesi quadre, così che stringhe hardcoded, troncamenti, font che non vengono visualizzati correttamente e frasi concatenate emergano prima ancora che esista una traduzione. Android include a questo scopo le pseudo-impostazioni regionali en-XA e ar-XB.
- [Come si gestiscono i plurali in React?](https://generaltranslation.com/it/kb/how-to-handle-plurals-in-react.mdx): Per gestire i plurali in React, fornisci per ogni lingua una frase per ciascuna forma plurale e scegli quella corretta in base alle regole del plurale di quella lingua, dato che l'inglese ha 2 forme, il russo 4 e l'arabo 6. Il componente `<Plural>` di General Translation in gt-react e gt-next accetta le tue forme sorgente, e General Translation genera le forme necessarie per ogni lingua di destinazione.
- [Posso fare i18n senza file di traduzione?](https://generaltranslation.com/it/kb/i18n-without-translation-files.mdx): Sì. Le librerie gt-react e gt-next di General Translation gestiscono l'i18n in React e Next.js senza chiavi di traduzione e senza dover mantenere un file JSON per ogni lingua. I testi restano inline nel JSX all'interno del componente `<T>` e il comando gt translate genera le traduzioni per ogni lingua durante la build, sfruttando il contesto del tuo codice. Locadex può mantenerle aggiornate tramite pull request.

## Previous and next questions

- Previous question: [Come si rileva la lingua del browser di un utente?](https://generaltranslation.com/it/kb/detect-user-language.mdx)
- Next question: [Come si traducono i file JSON di i18n?](https://generaltranslation.com/it/kb/translate-json-files.mdx)

## Sitemap

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