What "RTL" actually breaks in a personalization storefront
RTL doesn't just flip the text direction — it flips the entire layout. In an Arabic storefront, the primary nav appears on the right, the sidebar collapses on the left, form labels sit to the right of inputs, and the cart drawer slides in from the left instead of the right. The personalization option selector needs the same treatment: dropdowns open toward the reading direction, character counters live at the input's start-edge (right, in RTL), and progress indicators fill right-to-left.
Set the direction at the root
Shopify's default themes ship with basic RTL support if you set the language direction correctly. In your theme's theme.liquid:
<html lang="{{ request.locale.iso_code }}" dir="{{ request.locale.iso_code | rtl_ltr }}">
<!-- Custom filter (Liquid snippet) -->
{% assign rtl_langs = "ar,he,fa,ur" | split: "," %}
{% if rtl_langs contains request.locale.iso_code %}
{% assign dir = "rtl" %}
{% else %}
{% assign dir = "ltr" %}
{% endif %}
<html lang="{{ request.locale.iso_code }}" dir="{{ dir }}">
Use CSS logical properties, not physical directions
Physical CSS (margin-left, padding-right) requires you to write a separate RTL stylesheet. Logical CSS (margin-inline-start, padding-inline-end) inverts automatically based on the document direction. Rewrite your personalization option CSS with logical properties and one stylesheet works for both directions:
/* WRONG — hard-coded direction */
.option-label { margin-left: 12px; padding-right: 8px; }
/* RIGHT — inverts automatically */
.option-label { margin-inline-start: 12px; padding-inline-end: 8px; }
/* Logical property mapping */
margin-left → margin-inline-start
margin-right → margin-inline-end
padding-left → padding-inline-start
padding-right → padding-inline-end
border-left → border-inline-start
text-align: left → text-align: start
left / right → inset-inline-start / inset-inline-end
Handle mixed-script input
Arabic-market customers frequently mix Arabic + Latin text — an Arabic name followed by an English company. Force a single direction and the mixed input looks scrambled. Use dir="auto" on text inputs so the browser detects direction per input:
<label for="engraving">نص التخصيص</label>
<input id="engraving" type="text" dir="auto"
placeholder="Type your text — أدخل النص">
With dir="auto", if the first strong-directional character is Arabic, the cursor sits right and text flows RTL. If it's Latin, the cursor sits left. Both feel native.
POD partner Arabic font matrix
| POD partner | Arabic fonts | Hebrew fonts | Diacritics (tashkeel) | Kashida (justification) |
|---|---|---|---|---|
| Printful | Noto Sans Arabic + 3 display | Noto Sans Hebrew | Supported | Manual only |
| Printify | Noto Sans Arabic | Noto Sans Hebrew | Supported | Not supported |
| Gelato | Noto + Tajawal + Cairo | Noto Sans Hebrew + Frank Ruhl | Supported | Supported |
| Gooten | Not supported | Not supported | — | — |
| CustomCat | Not supported | Not supported | — | — |
Live preview font swap
Your live preview canvas needs an Arabic-capable font. Load Noto Sans Arabic when the input contains Arabic characters:
const ARABIC_RANGE = /[-ۿݐ-ݿ]/;
const HEBREW_RANGE = /[-]/;
function fontFor(text) {
if (ARABIC_RANGE.test(text)) return "'Noto Sans Arabic', sans-serif";
if (HEBREW_RANGE.test(text)) return "'Noto Sans Hebrew', sans-serif";
return "'Inter', sans-serif";
}
engravingInput.addEventListener('input', e => {
previewCanvas.font = `48px ${fontFor(e.target.value)}`;
previewCanvas.direction = 'inherit'; // uses dir=auto from input
redrawPreview(e.target.value);
});
Character-count and validation
Arabic letters connect and take more physical width than Latin. A 20-character English name and a 20-character Arabic name are not the same physical length on a printed item. Set per-script character limits (Arabic 12-15, Hebrew 15-18, Latin 20). Also, Arabic combining marks (tashkeel) count as separate codepoints — normalize before counting so "مُحَمَّد" (with vowels) counts as 6 letters, not 10 codepoints.
Cart drawer + option review
The cart drawer that slides in from the right in LTR should slide from the left in RTL. Personalization option summaries in the cart line ("Text: John") need the label direction to follow the input direction — Arabic labels with Latin values in the middle of an RTL layout should use bidi isolation with <bdi> tags:
<li>النص: <bdi>{{ property_value }}</bdi></li>
Frequently asked questions
How do I enable RTL on Shopify for Arabic personalization?
Set dir="rtl" on the html element when the current locale is Arabic, Hebrew, Persian, or Urdu. Use CSS logical properties (margin-inline-start) instead of physical (margin-left) so one stylesheet works for both directions.
Does Shopify support Arabic personalization out of the box?
Partially — Shopify Markets + Translate & Adapt handle Arabic UI translation, but the option-input handling (mixed-script, dir=auto, character-count per script) requires an app that supports RTL. Print It My Way handles this natively.
What Arabic font should I use for personalization previews?
Noto Sans Arabic is the safest default — every major POD partner supports it, it's free via Google Fonts, and it renders diacritics correctly. Cairo and Tajawal are good display alternatives when supported by your POD partner.
How do I handle mixed Arabic + English input?
Use dir="auto" on the input element. The browser detects direction from the first strong-directional character and orients cursor + text flow accordingly. For displaying mixed input in an RTL layout (e.g., cart line), wrap the value in a <bdi> tag to isolate its direction from the surrounding text.
Which POD partners support Arabic personalization?
Printful, Printify, and Gelato all support Arabic (Noto Sans Arabic minimum). Gooten and CustomCat do not. Gelato has the most robust Arabic support including diacritics and kashida justification.
Do Arabic personalizations count characters differently?
Yes — Arabic letters connect and take more physical width than Latin. Set a lower character limit for Arabic (~12-15) than Latin (~20). Also normalize combining marks (tashkeel) so "مُحَمَّد" counts as 6 letters instead of 10 codepoints.
Best Shopify app for RTL personalization?
Print It My Way — supports dir=auto inputs, script-aware character limits, RTL cart drawers, and CSS logical-property styling that works across LTR and RTL themes.
How do I test my RTL personalization storefront?
Set your browser language to Arabic (chrome://settings/languages), visit your Arabic-market URL, and complete a full purchase with mixed Arabic + Latin text. Verify: cart drawer slides from left, character count respects Arabic width, POD partner receives the correct file with diacritics preserved.
Related reading
- Markets multi-language options — full multi-language setup
- Hreflang variant URLs — SEO across markets
- Localized swatches — market-specific color options
- Live product preview setup — canvas rendering
Try it free on Shopify
Print It My Way's permanent Free plan includes native RTL support, mixed-script input handling, and Arabic-capable preview rendering.
Install Print It My Way