layers transparent glass texture depth

The Expansion Dilemma: Controlling Arabic Layout Shift

|

Arabic fonts cause more layout shift than Latin fonts — and for structural reasons. Learn why, and fix it with font-display, fallback calibration, and self-hosting.

~2,400 words  ·  11-min read

The Expansion Dilemma

Arabic font layout shift CLS


Before we dive in: This is Article 2 of the Digital Typography & Its Impact on Technical SEO series. If you landed here directly, it’s worth reading
Article 1: Beyond Translation
first — it sets up the full picture. But if page jitter brought you here, you’re in the right place.

The Shake Everyone Sees but Nobody Can Explain

Open any Arabic blog on a mid-speed internet connection. In the first second you’ll read the headline in some font — then suddenly, without warning, everything moves. The headline drops, the image jumps, a button slides out from under your finger right as you’re about to tap it.

That’s not your connection. It’s not your browser. It’s a specific technical phenomenon called Cumulative Layout Shift (CLS) — one of the most frustrating performance problems for users, and one of the metrics Google uses when scoring page quality.

On Arabic websites specifically, fonts are the primary culprit. Not because Arabic fonts are “bad” — but because they’re structurally different from Latin fonts in ways that produce loading behavior many developers only discover when they run into it for the first time.

In this article we’ll understand the problem from its root, then write the code that fixes it.

How Browsers Handle Fonts

Start from the beginning. When a browser loads a web page, it goes through a sequence: read the HTML, build the element tree, apply CSS rules, then paint the page on screen. But what happens when it hits a text element that calls for an external font that hasn’t loaded yet?

The browser has two options. Both come with a cost:

  • FOIT — Flash of Invisible Text:
    The browser hides the text entirely and waits for the font. The page looks blank in the text area for a few seconds. The cost: users see a worrying empty space and can’t read anything.
  • FOUT — Flash of Unstyled Text:
    The browser immediately renders text in a fallback font, then swaps to the real font when it arrives. The cost: the page “jumps” — and that jump is exactly what CLS measures.

Google measures CLS as a numeric score: the sum of the areas of elements that shifted, multiplied by the distance they traveled. The target is below 0.1. Anything above 0.25 gets rated “poor” by Google and affects page ranking.

Modern browsers default to a middle-ground behavior: they wait up to 3 seconds before showing text in a fallback font (FOUT). That means 3 seconds of invisible or semi-invisible text, followed by a flash when the real font finally arrives. Both outcomes hurt user experience and performance metrics.

Why Arabic Fonts Hit Harder

Swap a Latin font for Arial and the difference is manageable — similar character heights, similar word widths, minimal visual disruption when one replaces the other.

With Arabic fonts, the gap is structurally much larger. Here’s why:

1 — File Size

An Arabic character isn’t a single fixed shape. It has at least four forms depending on where it appears in a word: isolated, initial, medial, and final. Some characters have a fifth form for special cases. Every one of those forms has to be stored in the font file.

The result: a complete Arabic font file typically weighs between 100KB and 300KB or more. A simple Latin font might weigh 20KB. That difference in download time shows up on screen.

2 — The Visual Gap Between Fallback and Target

When you switch from Arial to Tajawal, the difference isn’t a few pixels. It’s a difference in vertical metrics (line-height), horizontal word width, visual font weight, and word spacing — all of which diverge significantly. A paragraph that takes 4 lines in the fallback font might take 3 or 5 lines in the real font. Everything below it shifts.

3 — No Good Arabic System Fallbacks

Windows ships “Segoe UI” as a great Latin default. But the default Arabic fallback font on most operating systems looks nothing like any web-designed Arabic typeface. The visual gap at swap time is large and obvious.

Fix 1 — font-display and the swap Value

The fastest change you can make right now, before anything else, is telling the browser how to behave when the font isn’t ready. You do that with the font-display property inside a @font-face rule.

The available values and what they do:

ValueBehaviorBest for
autoLeaves the decision to the browser (default)Not recommended
blockHides text (FOIT) for 3 seconds then shows itIcon fonts only
swapShows fallback immediately, swaps when readyArabic body text — the right choice
fallback100ms hide, then fallback; swaps only within 3sMiddle-ground approach
optional3s to load, otherwise cancels the swap entirelyNon-critical decorative fonts

For most Arabic sites, swap is the right call: users can read the text immediately, and the real font arrives when it arrives without blocking content. Here’s how to apply it:

@font-face {
  font-family: 'Tajawal';
  font-style: normal;
  font-weight: 400;
  font-display: swap; /* ← this line is the key */
  src: url('/fonts/tajawal-regular.woff2') format('woff2');
}

If you’re loading Google Fonts via a <link> tag in your HTML, you can add display=swap directly to the font URL:

<link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700&display=swap" rel="stylesheet">

This alone improves load behavior and cuts FOIT time. But it doesn’t fully solve the layout shift — because the visual gap between the fallback and the real font is still there. That’s where Fix 2 comes in.

Fix 2 — Fallback Font Calibration

The idea is simple and clever: if the shift happens because the fallback font has different dimensions than the real font, why not adjust the fallback font to match the real one as closely as possible?

CSS lets us do exactly that through special @font-face descriptor properties for system fonts:

  • size-adjust — scales the fallback font up or down proportionally
  • ascent-override — adjusts the space above the baseline
  • descent-override — adjusts the space below the baseline
  • line-gap-override — adjusts the gap between lines

Here’s a practical example that calibrates a fallback font to approximate Tajawal:

/* The real font */
@font-face {
  font-family: 'Tajawal';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/tajawal-regular.woff2') format('woff2');
}

/* A calibrated fallback that approximates Tajawal's dimensions */
@font-face {
  font-family: 'Tajawal-Fallback';
  src: local('Arial');
  ascent-override: 98%;
  descent-override: 22%;
  line-gap-override: 0%;
  size-adjust: 105%;
}

/* Apply: real font first, calibrated fallback second */
body {
  font-family: 'Tajawal', 'Tajawal-Fallback', sans-serif;
}

What happens here: the browser renders text using Tajawal-Fallback (which is actually Arial with adjusted metrics) while the real Tajawal loads. When Tajawal swaps in, the visual difference between the two is minimal — the shift either disappears or becomes barely noticeable.

The right values for ascent-override and size-adjust vary by font — there’s no universal set of numbers. The most accurate approach is to measure them with a tool like Automatic Font Matching or Font Style Matcher, both of which compare the two fonts visually and suggest values.

Fix 3 — Self-Hosting Your Fonts

The previous fixes improve loading behavior. But the underlying bottleneck is still there: the font is loading from an external server (Google Fonts or otherwise), which means:

  • An extra DNS lookup for an external domain
  • A TCP handshake delay before the download can even start
  • Dependence on Google’s servers being faster than yours for a given region — which isn’t always true
  • A third-party dependency: if their server has an issue, your font goes with it

The fix: download the font files once and host them on your own server. The WOFF2 format is the right choice — compressed, supported by all modern browsers, and roughly 30% smaller than standard WOFF files.

To get WOFF2 files for a Google Font, Google Webfonts Helper lets you download fonts ready for self-hosting, along with the CSS code to go with them.

After downloading, place the file in a /fonts/ folder on your server and add this to your CSS:

@font-face {
  font-family: 'Tajawal';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/tajawal-v29-arabic-regular.woff2') format('woff2');
  unicode-range: U+0600-06FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE80-FEFC;
}

Notice the unicode-range property: it tells the browser this font is for Arabic characters only. The font won’t load at all unless there are Arabic characters on the page — saving a full unnecessary download on pages without Arabic content.

Fix 4 — Variable Fonts

Traditionally, each font weight is a separate file: regular in one file, bold in another, medium in a third. If your site uses three weights of Tajawal, that’s three separate download requests.

Variable fonts solve this elegantly: one file that contains all weights and styles. The browser can interpolate between values to produce any weight you ask for — including values like font-weight: 450 that weren’t possible before.

/* One file instead of three or four */
@font-face {
  font-family: 'Tajawal';
  font-style: normal;
  font-weight: 200 900; /* weight range from 200 to 900 */
  font-display: swap;
  src: url('/fonts/tajawal-variable.woff2') format('woff2-variations');
}

/* Use any weight between 200 and 900 */
h1 { font-weight: 700; }
p  { font-weight: 400; }
.light { font-weight: 300; }

Not every Arabic font is available as a variable font yet, but support is growing. IBM Plex Arabic and several Noto Arabic variable releases are stable and production-ready.

Measuring the Fix: How to Confirm It Worked

After applying any of these fixes, don’t just look at the page and say “seems better.” Measure it with numbers.

Tool 1: Google PageSpeed Insights

Enter your page URL at pagespeed.web.dev. You’ll get a CLS score along with a visual report showing which elements shifted and by how much. Compare the score before and after your changes.

Tool 2: Chrome DevTools — Performance Recorder

Open the browser, press F12, go to the Performance tab, hit Record, then reload the page. The CLS metric is built into the report along with a timeline showing exactly when each shift happened and what caused it.

Tool 3: Web Vitals Extension

Google’s Web Vitals browser extension displays CLS, LCP, and INP scores live as you browse — great for quick before-and-after comparisons.

The target: a CLS score below 0.1 on a simulated mid-speed 4G connection (configurable in DevTools). Hit that, and you’re in the good range from Google’s perspective.

layers transparent glass texture depth

A Note for WordPress Users

If your site runs on WordPress, you have a few shortcuts:

  • Perfmatters or WP Rocket: Both can apply font-display: swap automatically across all fonts loaded from Google Fonts or your theme, without manual CSS edits.
  • wp_enqueue_style: If you’re loading fonts manually through your theme, add display=swap directly to the Google Fonts URL in your enqueue function.
  • Modern themes (GeneratePress, Astra): Most include a “font optimization” toggle in the theme options panel that enables swap with one click.

One caution: performance plugins are useful, but don’t rely on them without understanding what they’re doing. Code you understand is more reliable than an automatic setting you can’t debug — because when something breaks, you’ll know where to look.

Closing: Every Pixel That Moves Has a Price

Layout shift isn’t just a visual annoyance. It sends an unintentional message to users: “This site wasn’t built carefully.” And it sends a signal to Google: “This page wasn’t finished loading when the user arrived.”

The good news: the problem is completely fixable, with code that runs to a few dozen lines. The steps we covered today — from font-display: swap to fallback font calibration to self-hosting — aren’t advanced techniques for specialists. They’re basic practice for any Arabic site that takes its performance seriously.

In the next article we move to the second problem in the series: Arabic URLs that turn into encoded strings no user can read and no crawler can make sense of — and how to engineer a link structure that works for everyone.


— Digital Typography & Its Impact on Technical SEO —

Previous article: 1 — Beyond Translation: Intro to Arabic Web Localization

Current article: 2 — The Expansion Dilemma: Controlling Arabic Layout Shift

Next article: 3 — Permalink Engineering: Decoding Arabic Percent-Encoded URLs

Related series:
RTL Interface Engineering Guide | Hybrid Text Processing Guide | Financial Data Localization Guide | Web 3.0 Localization Workshop

Zy Yazan Platform © 2026

Localization Series

Digital Typography & Its Impact on Technical SEO — 4 Articles

Article 1
1 / 4

Beyond Translation: Intro to Arabic Web Localization

Understanding web localization frameworks for Arabic and adapting typography for optimal user experience.

Article 2
2 / 4

The Expansion Dilemma: Controlling Arabic Layout Shift

Managing spacing and Cumulative Layout Shift (CLS) caused by script expansion in web browsers.

Article 3
3 / 4

Permalink Engineering: Decoding Arabic Percent-Encoded URLs

Analyzing percent-encoding issues and technical solutions for structuring Arabic permalinks effectively.

Article 4
4 / 4

Practical Project: Optimizing an Arabic Landing Page

A hands-on guide to improving performance and search engine compatibility for Arabic landing pages.

Series: Digital Typography & Its Impact on Technical SEO — 4 Articles  |  Zyyazan Platform © 2026

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *