There's a post I kept wishing existed when we first took on an Arabic Shopify build. A post that covered the real implementation — not just "add dir=rtl to your HTML" (which breaks more than it fixes), but the actual CSS overrides, the font stack decisions, the Liquid conditionals, and the third-party apps that silently wreck your layout the moment a customer switches to Arabic.
This is that post.
As a Shopify Partner that's built RTL stores for clients across Saudi Arabia and the UAE, we've made every mistake this guide warns you about. Consider this the distilled version.
What You'll Learn
- How Shopify OS 2.0 handles RTL natively (and where it falls short)
- The CSS properties that require manual overrides in RTL
- Arabic font stacks that actually render well at small screen sizes
- Using Liquid's
locale.directionfor conditional rendering - Handling bidirectional (bidi) content: Arabic text with embedded English numbers
- Which popular Shopify apps break in RTL and how to fix them
Prerequisites
- A Shopify store on a 2.0 theme (Dawn, Sense, Refresh, or a premium 2.0-compatible theme)
- Access to Online Store > Themes > Edit Code
- Arabic added as a language via Settings > Languages
- Basic CSS knowledge
Step 1: Enable Arabic as a Language in Shopify
Before any code changes, add Arabic through Shopify's language system.
- Go to Settings > Languages
- Click Add language and select Arabic (ar)
- Use Shopify's Translate & Adapt app (free, from Shopify) to translate your theme strings, or use a third-party translation app
- Once Arabic is active, Shopify OS 2.0 themes with
dir="rtl"support will automatically flip to RTL layout when a customer's locale is Arabic
What Shopify handles automatically in OS 2.0:
- Text direction (
dir="rtl"applied to<html>) - Text alignment for paragraph content
- Some Flexbox reversals
What it does NOT handle automatically (you must fix these manually):
- CSS
left/rightpositioning on absolutely or fixed positioned elements floatdeclarations (largely legacy but still common in older themes/apps)margin-left/margin-rightasymmetric values- Icon direction (arrows, chevrons that point left in LTR should point right in RTL)
- Third-party app widgets injected via JavaScript
Step 2: The Core CSS Overrides
Create a new snippet file called rtl-overrides.css.liquid and include it conditionally. Then add your RTL styles inside a conditional block.
In your theme.liquid (inside the <head> tag), add:
{% if locale.direction == 'rtl' %}
{{ 'rtl-overrides.css' | asset_url | stylesheet_tag }}
{% endif %}
In your assets/rtl-overrides.css file:
/* =============================================
INNOVATRIX RTL OVERRIDES — Arabic Shopify Stores
============================================= */
/* Flip all left/right margin/padding pairs */
[dir="rtl"] .left-content { margin-left: 0; margin-right: var(--spacing); }
[dir="rtl"] .right-content { margin-right: 0; margin-left: var(--spacing); }
/* Flip Flexbox row direction */
[dir="rtl"] .flex-row { flex-direction: row-reverse; }
/* Product grid — image + content alignment */
[dir="rtl"] .product-card__info { text-align: right; }
[dir="rtl"] .product-card__price { text-align: right; }
/* Navigation — reverse the dropdown direction */
[dir="rtl"] .header__menu-item .header__submenu {
left: auto;
right: 0;
}
/* Chevron/arrow icons — flip horizontally */
[dir="rtl"] .icon-arrow-right,
[dir="rtl"] .icon-chevron-right {
transform: scaleX(-1);
}
/* Breadcrumb separator */
[dir="rtl"] .breadcrumb__separator { transform: scaleX(-1); }
/* Input fields — right-align text */
[dir="rtl"] input,
[dir="rtl"] textarea,
[dir="rtl"] select {
text-align: right;
direction: rtl;
}
/* Cart quantity — fix mis-aligned stepper */
[dir="rtl"] .quantity-selector {
flex-direction: row-reverse;
}
Critical gotcha: Don't use [dir="rtl"] * { direction: rtl; } as a catch-all. It will break embedded iframes (payment widgets, review apps, chat tools) that need to render LTR internally. Target elements explicitly.
Step 3: Arabic Font Stack
Shopify themes ship with Latin fonts by default. Arabic text rendered in a Latin font falls back to the browser's default Arabic font, which is usually inconsistent across devices and rarely legible at small sizes.
The three Arabic Google Fonts that perform well in ecommerce contexts:
- Cairo — clean, geometric, excellent readability at all sizes, works at 14px+
- Tajawal — slightly more rounded, good for headings and hero text
- Noto Sans Arabic — extremely legible at small sizes, ideal for body copy and meta
Add to the <head> in theme.liquid:
{% if locale.direction == 'rtl' %}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cairo:wght@400;500;600;700&family=Tajawal:wght@400;500;700&display=swap" rel="stylesheet">
{% endif %}
In your rtl-overrides.css:
/* Apply Arabic font stack when RTL is active */
[dir="rtl"] body,
[dir="rtl"] p,
[dir="rtl"] .product-card__title,
[dir="rtl"] .cart__item-name {
font-family: 'Cairo', 'Tajawal', 'Noto Sans Arabic', Arial, sans-serif;
line-height: 1.7; /* Arabic text needs more line height than Latin */
font-size: 1.05rem; /* Slight upsize — Arabic at 14px is harder to read */
}
[dir="rtl"] h1,
[dir="rtl"] h2,
[dir="rtl"] h3 {
font-family: 'Tajawal', 'Cairo', sans-serif;
font-weight: 700;
letter-spacing: 0; /* Zero letter-spacing — Arabic glyphs connect */
}
Important: Arabic is a cursive script — glyphs connect to each other. Never apply letter-spacing values to Arabic text. It breaks the visual joining of characters and looks like corrupted text.
Step 4: Liquid Conditional Rendering
Some layout decisions require Liquid logic, not just CSS. The locale.direction variable returns "rtl" or "ltr" based on the active language.
Example: Conditional icon rendering
{% if locale.direction == 'rtl' %}
{% render 'icon-arrow-left' %}
{% else %}
{% render 'icon-arrow-right' %}
{% endif %}
Example: RTL-aware product card layout
<div class="product-card {% if locale.direction == 'rtl' %}product-card--rtl{% endif %}">
<div class="product-card__image">...</div>
<div class="product-card__info">
<h3 class="product-card__title">{{ product.title }}</h3>
<p class="product-card__price">{{ product.price | money }}</p>
</div>
</div>
Example: RTL-aware <html> tag (add to theme.liquid)
<html lang="{{ request.locale.iso_code }}" dir="{{ locale.direction }}">
This ensures the dir attribute is dynamically set on the document root based on the active language — which is what drives all CSS [dir="rtl"] selectors.
Step 5: Handling Bidirectional (Bidi) Content
Mixed Arabic/English content is common in ecommerce: product names in Arabic, prices in Arabic numerals or English numerals, brand names in Latin characters embedded in Arabic descriptions.
The Unicode bidirectional algorithm handles most of this automatically, but it can produce unexpected results in specific cases — especially around punctuation, numbers at the end of Arabic strings, and parentheses.
Use the unicode-bidi CSS property for mixed-direction containers:
[dir="rtl"] .product-description {
unicode-bidi: plaintext;
/* Renders bidi content in its natural direction without forcing the container direction */
}
For product names with embedded English brand names:
<span dir="auto">{{ product.title }}</span>
The dir="auto" HTML attribute uses the first strong character in the text to set direction — if the product name starts with Arabic, it renders RTL; if it starts with a Latin brand name, it renders LTR. This is more reliable than hard-coding for mixed catalogs.
Step 6: Third-Party Apps That Break in RTL
This is the section you won't find in most guides. Here are the apps and widget categories that commonly produce broken layouts in Arabic RTL Shopify stores, and how to handle each:
Review Apps (Judge.me, Loox, Stamped.io)
Stars-and-review widgets inject their own CSS, often with hard-coded text-align: left and float: left. Override via the Shopify theme's custom CSS:
[dir="rtl"] .jdgm-rev__body,
[dir="rtl"] .jdgm-rev__author {
text-align: right;
direction: rtl;
}
BNPL Widgets (Tabby, Tamara)
Tabby and Tamara both have Arabic-aware widget options — pass lang="ar" in their embed configuration to get Arabic-localised messaging. Without this, they default to English.
Klaviyo / Email Capture Popups Klaviyo's popup form renders LTR by default. In Klaviyo's form editor, set text direction to RTL in the form settings for Arabic templates.
Live Chat (Tidio, Freshchat, Intercom) Most live chat tools auto-detect the user's browser language and flip their own widget. If yours doesn't, check the language configuration in the chat tool's settings — most enterprise-tier chat tools have explicit RTL support.
Search Apps (Searchie, Boost Commerce) Search result dropdowns and filter panels often have their own CSS scope. You'll need app-specific overrides. Test your search experience in Arabic explicitly — it's commonly broken and commonly overlooked.
Common Issues and Fixes
Problem: Checkout page is still LTR in Arabic mode. Fix: Shopify's checkout (for non-Shopify Plus merchants) is a Shopify-controlled surface. You cannot customise its RTL behaviour without a Shopify Plus checkout.liquid. For standard plans, the checkout will use Shopify's built-in Arabic support, which is reasonable but not fully customisable.
Problem: Product image gallery carousel swiping direction is inverted (swipe left in Arabic, but it goes right).
Fix: Most carousel libraries (Splide, Swiper) have a dir option. Set dir: 'rtl' in your carousel initialisation when locale.direction == 'rtl'.
Problem: Breadcrumb shows Home / Products / Product Name instead of اسم المنتج / المنتجات / الرئيسية.
Fix: This is a translation issue, not an RTL issue. Use Translate & Adapt to translate breadcrumb strings. The RTL layout will handle direction once translation is in place.
Problem: Email notifications are still LTR.
Fix: Shopify email notification templates are separate from theme files. Go to Settings > Notifications and manually add dir="rtl" to the relevant email HTML templates for Arabic-language notifications.
Results: What Proper RTL Delivers
For one of our Saudi Arabia-facing clients, we implemented the full RTL treatment described above on a mid-size fashion store. The before/after on the Arabic-language variant told the story clearly: session duration in Arabic increased substantially, and cart abandonment on the Arabic checkout path dropped to match the English path — which it had meaningfully underperformed before the RTL work.
Proper RTL is not cosmetic. Saudi and UAE consumers who encounter a broken Arabic layout typically don't report it. They leave. The conversion gap between a properly-built Arabic store and a half-implemented one is measurable in direct revenue.
If you want us to audit your existing Shopify store's Arabic experience or build a new RTL-ready store, start with a discovery call here.
Frequently Asked Questions
Written by

Founder & CEO
Rishabh Sethia is the founder and CEO of Innovatrix Infotech, a Kolkata-based digital engineering agency. He leads a team that delivers web development, mobile apps, Shopify stores, and AI automation for startups and SMBs across India and beyond.
Connect on LinkedIn