Skip to Content

Arabic, Persian & RTLExplainer7 min read

Arabic and Persian typography for the web

Arabic letters join, reach further above and below the line than Latin, and can read smaller at the same size. Type settings made for English break them in ways a native reader sees at once.

By Gravity EditorialPublished
A rising row of chrome and red chart candlesticks between two navy curtains.

The short answer

Arabic web fonts are typefaces drawn for the Arabic script, which also writes Persian, and served to the browser with the page. Choose one that covers the language you publish, because Persian needs letters and digits that Arabic does not use. Name it directly in the font stack after your Latin family. Then set it by its own rules: no letter-spacing, a taller line height, and a size judged by eye against the Latin beside it. Vazirmatn, IBM Plex Sans Arabic, Noto Naskh Arabic and Amiri are open families on Google Fonts.

  1. Arabic letters join, so letter-spacing breaks words. Stretch Arabic deliberately, with kashida, never with tracking.
  2. Arabic reaches further above and below the line than Latin and can read smaller at the same size: open the line height, and scale the Arabic face rather than the whole line.
  3. Persian needs four extra letters, its own yeh and kaf, the zero-width non-joiner and its own digits. Test a font with real Persian before you commit to it.
  4. Name the Arabic family directly in the stack. A generated Latin fallback with no unicode-range can catch every Arabic letter first.

What changes when the script is Arabic

Most web type is tuned for Latin: tight tracking, close display lines, weights chosen by number. Applied to Arabic or Persian, those settings pull letters apart and make wrapped lines collide. Setting a page right-to-left fixes none of this; direction is covered in publishing right-to-left. This article covers the type. Three facts drive it: the letters join, the ascenders and descenders extend much further than Latin ones, and Persian uses characters Arabic does not2.

Joined letters: why tracking breaks Arabic

Arabic is cursive: the only spaces inside a word sit next to letters that do not join on both sides2. The CSS specification says cursive scripts "do not admit gaps between their letters"3. Faced with letter-spacing, a browser may stretch the joins or leave the letters unspaced, and authors are advised to avoid it unless they accept results that differ between browsers3.

Tracking also costs ligatures. When spacing between characters is not zero, browsers should not apply optional ligatures34, and in OpenType only the rlig feature counts as required3. Gravity sets letter-spacing to zero on Arabic-script labels and headings, because tracking breaks joined letters1.

Stretching Arabic on purpose

Arabic widens words its own way. Kashida lengthens the connection between joined letters; tatweel, U+0640, is a fixed-width character inserted between them2. Both justify lines and can make a heading more visible, but neither is letter-spacing: the stretch runs along the baseline, unevenly, and too much of it makes the text look patchy2. Tatweel is part of the text, so it is copied and indexed with the word; keep it for display lines you control. CSS forbids justification from opening gaps between joined Arabic letters but does not require elongation3, so test justified Arabic in each browser you support.

Size and line height across two scripts

Arabic's tall ascenders and deep descenders need room, or a wrapped headline collides with itself. Publishing right-to-left gives Gravity's values; check yours on real headlines that wrap.

Size is harder: at the same font-size, the two scripts often do not look the same size. The W3C lists "the size issue" in mixed texts among the points to weigh when choosing an Arabic font2, and its own example of styling by language sets Arabic at 120%5. But a font-size on :lang(ar) also enlarges any Latin inside, such as a brand name in an Arabic headline. The size-adjust descriptor scales one font face instead, multiplying its glyph outlines and metrics; it has worked across browsers since September 20237. Declare the Arabic face with size-adjust, and only its glyphs grow.

Persian is more than Arabic with extra letters

Persian and Arabic share a script but not a character set. Persian adds پ, چ, ژ and گ. It writes ی (U+06CC) and ک (U+06A9) where Arabic writes ي (U+064A) and ك (U+0643)2. A font must include the Persian forms, and draw them well, before it can set Persian.

Persian also relies on the zero-width non-joiner, U+200C, an invisible character that stops two letters within a word from joining. The W3C marks it as used in Persian, not Arabic, and says such control characters should be kept when text is stored and displayed2. Delete it and letters join that should not; turn it into a space and one word becomes two.

Digits are characters too; which set each audience reads is covered in the pillar article. Put the digits you want in the text rather than relying on a font. Intl.NumberFormat's numberingSystem option has a locale-dependent default10, so name arabext, the Extended Arabic-Indic digits of a Persian edition, or latn explicitly11. Gravity keeps Latin digits in its market ticker1.

Choosing an Arabic-script family

All four families below are on Google Fonts under the SIL Open Font License.

Four open Arabic-script families, as listed by Google Fonts
FamilyStyleWeightsVariableDesigned by
VazirmatnSans-serif100 to 900Yes, one weight axisSaber Rastikerdar13
IBM Plex Sans ArabicSans-serif100, 200, 300, 400, 500, 600, 700NoMike Abbink, Bold Monday, Khajag Apelian, Wael Morcos14
Noto Naskh ArabicSerif (Naskh)400 to 700Yes, one weight axisGoogle15
AmiriSerif (Naskh)400 and 700, each with an italicNoKhaled Hosny, Sebastian Kosch16

Vazirmatn describes itself as a Persian/Arabic font for web pages and applications18; Amiri is a classical Naskh for books and running text17; Google Fonts lists Persian among Noto Naskh Arabic's languages15. Whatever a listing says, test with real Persian: the four extra letters, ی and ک in every position, a zero-width non-joiner, and the digits ۴۵۶.

A weight number is only a request

A static family renders only the weights it has. For a missing weight, the browser substitutes by rule: below 400 it tries lighter weights first, then heavier; above 500, heavier first9. Amiri has only 400 and 70016, so a headline set at 300 renders in Amiri Regular and one at 600 in Amiri Bold. A variable family renders any weight on its axis; Gravity's own pages set Vazirmatn at 100 for display, 200 for titles and 300 for ledes1. Two families can also divide the work: the Arabic edition of Gravity's Luxury template uses Amiri for display and IBM Plex Sans Arabic for the interface1.

Pairing a Latin family with an Arabic one

Arabic-script pages still carry Latin: brand names, handles, tickers. The font stack's order decides which family draws it. Many Arabic families include Latin glyphs; Vazirmatn's come from Roboto, and the project also publishes a version without them18. List the Latin family first and the Arabic one second, so Latin characters use the Latin family and Arabic letters fall through to the Arabic one. Then match the two by eye, not by weight number, adjusting the Arabic face's weight and size-adjust until they look consistent.

Scope Arabic styles with :lang() rather than classes: it matches elements that inherit their language from an ancestor, and :lang(fa) also matches fa-IR5. It depends on the language being declared, usually with the lang attribute6. Latin handles inside Arabic also need isolating, with dir="auto" or bdi, or "@handle" displays as "handle@"1; that bidirectional text problem is covered in the pillar article.

The fallback trap

Web fonts arrive after the page, so frameworks generate stand-in faces to hold the layout; the Next.js font loader adds an automatic fallback by default to reduce layout shift12. A stand-in is an ordinary @font-face rule, and a rule with no unicode-range covers every character: the initial value is U+0-10FFFF8.

There are two fixes. Gravity names the families directly, in order: Latin family, Arabic family, then the generated fallback, so Arabic letters reach the Arabic face first1. If you write the fallback face yourself, give it a Latin-only unicode-range; a face is used, and downloaded, only for characters in its range8.

A CSS checklist for Arabic-script type

/* Latin family first, the Arabic face by name, fallbacks last. */
:root {
  --font-text: "Latin Sans", "Arabic Sans", "Latin Sans Fallback",
    system-ui, sans-serif;
}

/* The Arabic face: Arabic code points only, scaled to sit
   level with the Latin beside it. */
@font-face {
  font-family: "Arabic Sans";
  src: url("/fonts/vazirmatn.woff2") format("woff2");
  font-weight: 100 900;
  unicode-range: U+0600-06FF, U+0750-077F, U+200C-200D,
    U+FB50-FDFF, U+FE70-FEFF;
  size-adjust: 108%; /* illustrative: judge by eye */
}

/* A fallback you write yourself: Latin only, so it can
   never claim an Arabic letter. */
@font-face {
  font-family: "Latin Sans Fallback";
  src: local("Arial");
  unicode-range: U+0000-00FF;
}

/* Arabic-script settings, scoped by language. */
:lang(ar),
:lang(fa) {
  letter-spacing: 0;
  line-height: 1.8; /* illustrative */
}
A sketch of the settings above. The size and line height are illustrative.
  • lang and dir on the html element, so :lang() has a language to match.
  • letter-spacing: 0 for Arabic and Persian, labels and buttons included.
  • Stretching only on purpose, with kashida or tatweel.
  • A taller line height, checked on headlines that wrap.
  • Arabic size matched by eye, with size-adjust where scripts share a line.
  • The Arabic family named after the Latin one, before any generated fallback.
  • Your own fallback faces limited by unicode-range.
  • Persian tested with پ چ ژ گ, ی, ک, a zero-width non-joiner and ۴۵۶.
  • Digits produced as characters, numbering system named.

What this means for an IB's page

For an introducing broker whose audience reads Arabic or Persian, the type is seen before a word is read, and broken words or colliding lines say the page was made for someone else. The risk warning needs the same care: it only protects readers who can read it comfortably. A page that reads natively is the point of an IB website over a social feed.

Questions

What is the best Arabic web font?
No single font is best. Choose a family drawn for the Arabic script that covers your language and weights. Vazirmatn, IBM Plex Sans Arabic, Noto Naskh Arabic and Amiri are open families on Google Fonts; test any of them with real headlines, Persian letters and digits.
Should I use letter-spacing on Arabic text?
No. Arabic letters join, and the CSS specification says cursive scripts do not admit gaps between letters. Browsers treat letter-spacing on Arabic inconsistently, and non-zero spacing turns off optional ligatures. Set it to 0 for Arabic and Persian, and use kashida deliberately where a design needs wider text.
Why does my Arabic text render in Arial?
Usually a fallback face sits before your Arabic font in the stack. Font loaders can generate a Latin fallback from local Arial with no unicode-range, and Arial includes Arabic, so it draws those letters first. Name the Arabic family directly after the Latin one, or limit your own fallbacks to Latin with unicode-range.

Sources

First-party figures are Gravity's own observations of its product. External sources were read on the date shown.

  1. What Gravity learned setting Arabic-script type — Gravity

    Gravity, first-party · From Gravity's own type rules: zero letter-spacing for Arabic-script labels, Vazirmatn at 100/200/300 on Gravity's pages, Amiri with IBM Plex Sans Arabic in the Luxury template's Arabic edition, Latin digits in the market ticker, the font-fallback trap, and isolated Latin handles.

  2. Arabic & Persian Layout Requirements — W3C

    Standard · read 29 September 2026 · A W3C Group Draft Note, 2 October 2025.

  3. CSS Text Module Level 3 — W3C

    Standard · read 29 September 2026 · A W3C Candidate Recommendation Draft, 14 August 2026.

  4. letter-spacing — MDN Web Docs

    Documentation · read 29 September 2026

  5. Styling using language attributes — W3C Internationalization

    Standard · read 29 September 2026

  6. :lang() — MDN Web Docs

    Documentation · read 29 September 2026

  7. size-adjust — MDN Web Docs

    Documentation · read 29 September 2026

  8. unicode-range — MDN Web Docs

    Documentation · read 29 September 2026

  9. font-weight — MDN Web Docs

    Documentation · read 29 September 2026

  10. Intl.NumberFormat() constructor — MDN Web Docs

    Documentation · read 29 September 2026

  11. Intl.supportedValuesOf(): supported numbering system types — MDN Web Docs

    Documentation · read 29 September 2026

  12. Font Module — Next.js

    Documentation · read 29 September 2026 · The adjustFontFallback option.

  13. Vazirmatn: family metadata — Google Fonts (google/fonts repository)

    Documentation · read 29 September 2026

  14. IBM Plex Sans Arabic: family metadata — Google Fonts (google/fonts repository)

    Documentation · read 29 September 2026

  15. Noto Naskh Arabic: family metadata — Google Fonts (google/fonts repository)

    Documentation · read 29 September 2026

  16. Amiri: family metadata — Google Fonts (google/fonts repository)

    Documentation · read 29 September 2026

  17. Amiri: description — Google Fonts (google/fonts repository)

    Documentation · read 29 September 2026

  18. Vazirmatn — Vazirmatn project, GitHub

    Documentation · read 29 September 2026

Terms in this article

Written by

Gravity Editorial

The team that builds Gravity

Written by the people who build Gravity, from what the product does and what building it taught us. Figures come from Gravity's own measurements or from the source cited beside them; nothing on these pages is trading advice. See how we write.

  1. 01

    Arabic, Persian & RTLGuide9 min read

    Publishing right-to-left: an Arabic and Persian website that reads natively

    Direction is one attribute. Reading natively is everything after it — the handles, tickers, numbers and type that run through an Arabic or Persian page.

  2. 02

    Websites & presenceGuide8 min read

    Why an IB needs a website, not just a social feed

    A feed is where people find you. A website is where they decide whether to trust you — the one place your offer, your broker and your risk warning sit together.

  3. 03

    Marketing & advertisingGuide10 min read

    Forex IB marketing: how introducing brokers win and keep clients

    An IB's marketing is one system, not a feed: attention, trust, a disclosed link and a reason to stay. What each channel does, what advertising may do, and where the rules draw the line.

Start

One profile is all Gravity needs to begin.

Give Gravity a public Instagram, TikTok or YouTube profile. It reads it and builds your website in your own language — in minutes, with nothing on it you can't stand behind.