Arabic Script
Arabic is an abjad written right to left, like Hebrew, but it adds a mechanism Hebrew doesn't have: true cursive joining. Nearly every letter changes shape depending on whether it opens, sits inside, closes, or stands alone in a word, and a shaping engine has to pick the right one automatically, in real time, for every letter in every word. This article covers that joining system, the required ligatures it produces, and what a font needs to get it right.
Arabic, in one screen
An abjad with true cursive joining: most letters take up to four different shapes depending on position.
Arabic has 28 base letters, plus several hamza-carrying letters that behave as their own units in shaping. A user types a single, unchanging code point for each letter. The visual form that appears, isolated, initial, medial, or final, is chosen entirely by the shaping engine based on what comes before and after it. This is the core difference from Latin bold or italic, which a user selects: Arabic joining is automatic and mandatory.
Six letters in the alphabet (alef, dal, dhal, ra, zay, and waw) only ever connect to the letter before them, never to the one after, which breaks a word into visually separate "runs" even though it's a single connected word linguistically. Every other letter joins on both sides when its neighbors allow it. A shaping engine has to track this letter by letter across an entire word and select the correct isolated, initial, medial, or final glyph for each one, every time the word is rendered.
This is structurally different from anything in this track so far. Latin and Cyrillic never change a letter's shape based on neighbors. Hebrew doesn't either. Arabic's default state, mid-word, mid-run, is the joined form, and the isolated form a person sees in a type specimen or an alphabet chart is actually the exception.
ع (ayn) makes the joining behavior easy to see because its four forms are visually distinct from each other, not just lightly modified.
A reader never chooses among these, the shaping engine resolves the correct form automatically from the letters on either side. The isolated form is the only one that ever appears alone.
لا (lam followed by alef) is the clearest required ligature in the script: rather than drawing lam's final form next to alef's isolated form, type design fuses them into a single glyph shape. Leaving it unfused is a visible, immediately recognizable error to any Arabic reader.
Arabic text is commonly justified by stretching the joining strokes between letters rather than by adding space between words, the way Latin justification does. This uses the kashida (also called tatweel), a horizontal elongation character that lengthens a connector without changing which letters are present. A font intended for justified Arabic setting needs kashida-aware connecting strokes, or justified paragraphs will visibly break at the joins.
Arabic's OpenType feature list is built around one core job: resolving positional forms correctly for every letter in every word, then layering required ligatures and optional stylistic variation on top.
| Feature | Tag | What it builds here |
|---|---|---|
| Isolated forms | isol | Selects a letter's standalone shape when it joins to nothing. |
| Initial forms | init | Selects the shape a letter takes when it opens a joined run. |
| Medial forms | medi | Selects the shape a letter takes inside a joined run. |
| Final forms | fina | Selects the shape a letter takes when it closes a joined run. |
| Required ligatures | rlig | Builds mandatory fused shapes such as lam-alef. |
| Mark positioning | mark | Anchors harakat and the shadda to their base letters. |
| Cursive positioning | curs | Aligns connecting strokes between joined letterforms. |
| Stylistic sets | ss01-ss20 | Regional style variation, such as Persian or Urdu (Nastaliq) letterform preferences. |
| Symptom | Likely cause | Fix |
|---|---|---|
| Letters appear disconnected or in isolated form throughout a word | Shaping engine not applying init/medi/fina substitutions | Confirm the text layout pipeline runs full Arabic shaping, not a naive per-character render |
| لا renders as two separate letters instead of one fused shape | Required rlig ligature missing or not applied | Verify lam-alef and other mandatory ligatures are built and enabled |
| Justified paragraphs show gaps at word joins instead of stretched connectors | No kashida-aware justification, only word-spacing used | Support kashida insertion for justified Arabic text |
| Harakat marks float away from their letters or overlap | Mark anchors untested against real vowel-pointed text | Test fully voweled Quranic or pedagogical text, not just unvoweled prose |
| Persian or Urdu text uses the wrong regional letterforms | Font ships only Arabic-language conventions | Add language-specific forms via stylistic sets or locl for each target language |
- 1Draw isolated, initial, medial, and final forms for every joining letter, and the isolated-plus-final pair for non-joining ones.
- 2Build required ligatures, lam-alef first, then check for others your target languages need.
- 3Tune cursive connector alignment so strokes meet cleanly across every letter pair.
- 4Support kashida-based justification if the font targets justified paragraph text.
- 5Test harakat placement on fully voweled text, not just everyday unvoweled prose.
- 6Review with a fluent reader across full connected words, never isolated glyphs alone.
Copy these into a test document. Each targets a different part of the coverage and shaping surface covered above.