Right-to-Left (RTL)
Elements render left-to-right by default. Set direction: 'rtl' at initialization to render them right-to-left for languages such as Arabic and Hebrew.
Enabling RTL
direction is an SDK option, so it applies to every element created from that SDK instance.
import BasisTheory from '@basis-theory/web-elements';
const bt = BasisTheory('<PUBLIC_API_KEY>', {
direction: 'rtl',
});
With React Elements, pass it through the options prop:
import { BasisTheoryProvider } from '@basis-theory/react-elements';
function App() {
return (
<BasisTheoryProvider
apiKey="<PUBLIC_API_KEY>"
options={{ direction: 'rtl' }}
>
<PaymentForm />
</BasisTheoryProvider>
);
}
| Option | Type | Default | Description |
|---|---|---|---|
direction | 'ltr' | 'rtl' | 'ltr' | Writing direction applied to every element. Any other value throws a ConfigurationError. |
language | string | — | BCP 47 tag applied to every element. A value that is not a BCP 47 tag throws a ConfigurationError. |
What changes inside the elements
With direction: 'rtl':
- Placeholders and the card brand picker align to the right.
- In the
cardelement, the expiration date and CVV fields swap position, without you changinglayout. - The card brand icon and the CVV reveal toggle move to the opposite side of the input.
Your own markup is unaffected. Field labels, headings, and the surrounding form live on your page, outside the element iframes, so set the direction there yourself:
<html lang="ar" dir="rtl">
Card fields stay left-to-right
The card number, expiration date, and CVV fields keep a left-to-right writing direction even when direction is 'rtl'. They are aligned to the right, but their digits are not reordered.
This matters for the card number. A space is a neutral character, and European numbers act as right-to-left when they influence adjacent neutrals (Unicode UAX #9, rule N1). In a right-to-left paragraph the spaces between digit groups therefore resolve to right-to-left, each group becomes its own run, and the runs are laid out right to left. A card number entered as 4111 2222 3333 4444 displays as 4444 3333 2222 4111 while the submitted value stays correct — the shopper reads their own card number back reversed.
The expiration date and CVV do not reorder on their own. 12/25 collapses to a single run because a lone separator between two numbers takes their type (rule W4), and 123 has no separator at all. Elements pins all three fields to left-to-right regardless, so a change to how a value is formatted cannot reintroduce the problem.
direction: ltr; unicode-bidi: isolate. On an inline element such as a <span>, direction on its own has no effect — it applies only when unicode-bidi is embed, isolate, isolate-override, bidi-override, or plaintext. The same reordering affects masked values that contain spaces or parentheses, such as (555) 123-4567.Language
Element iframes declare lang="en" until you set language. Pass a BCP 47 tag so
assistive technology announces your placeholder and ariaLabel text with the right
pronunciation rules:
const bt = BasisTheory('<PUBLIC_API_KEY>', {
direction: 'rtl',
language: 'ar',
});
Set it independently of direction. Right-to-left does not imply Arabic — Hebrew,
Persian, and Urdu are also right-to-left — so neither value can be inferred from the
other. Set lang on your own markup too, since your labels sit outside the iframes.
Arabic-Indic digits
The card number, expiration date, and CVV fields accept Arabic-Indic (٠-٩,
U+0660-U+0669) and extended Arabic-Indic (۰-۹, U+06F0-U+06F9) digits, which a
keyboard in an Arabic or Persian locale may produce instead of ASCII.
They are normalized to ASCII as the shopper types, so the field shows the same digits embossed on the card and the tokenized value is unchanged.
\d matches
ASCII digits only — /\p{Nd}/u matches the full set.Text elements
text elements hold arbitrary values, so each value takes its direction from its own
content rather than from the page. An Arabic or Hebrew cardholder name reads
right-to-left, while a value with no letters in it — a masked phone number such as
(555) 123-4567, for example — renders left-to-right and keeps its groups in order.
You do not need to configure this.
Changing direction
direction is fixed for the life of an element. Passing it to update() has no effect.
To switch direction — for example when a shopper changes language — re-initialize the SDK with the new value and mount the elements again:
cardNumber.unmount();
expiry.unmount();
cvv.unmount();
const bt = BasisTheory('<PUBLIC_API_KEY>', { direction: 'rtl' });
Related
- Initialization — all SDK options
- Theming — colors, typography, spacing, and borders