多言語UIの落とし穴:directionとunicode-bidiで制御する「双方向テキスト」の深淵
Webアプリケーションのグローバル化が進む昨今、英語や日本語のような「左書き(LTR)」だけでなく、アラビア語やヘブライ語のような「右書き(RTL)」のテキストを扱う機会は増えています。
しかし、いざ実装しようとすると、`direction`や`unicode-bidi`といったプロパティの仕様に翻弄され、レイアウトが崩壊したり、カーソル位置が謎の挙動を示したりした経験はありませんか?
今日は、ブラウザのレンダリングエンジンの裏側を覗きながら、インライン要素における「双方向テキスト(BiDi)」制御の最適解を解説します。
—
ブラウザが裏側で行っている「Unicodeアルゴリズム」の正体
まず前提として、ブラウザは「Unicode Bidirectional Algorithm (UBA)」というルールに従って文字を配置しています。
普段、私たちが意識せずに書いているHTMLは、基本的には左から右へ流れます。しかし、RTL言語が混ざった瞬間、ブラウザは「どこが論理的な文章の区切りか?」を必死に解析し始めます。ここで厄介なのが、インライン要素の境界線です。
`span`や`strong`といったインライン要素は、本来「コンテナ」としての意識が薄いため、ブラウザはこれらを無視して(あるいは断片化して)テキストを並べ替えようとします。この制御を開発者が明示的にコントロールするために必要なのが、`direction`と`unicode-bidi`のコンビネーションです。
—
directionだけでは不十分な理由
「`direction: rtl`を当てれば解決じゃないの?」という声が聞こえてきそうですが、それは半分正解で半分間違いです。
`direction`はあくまで「テキストの方向性」を示すもの。これだけだと、インライン要素が親要素のコンテキストを無視して、断片的に並び替えられてしまうリスクがあります。
ここで登場するのが `unicode-bidi` です。特に重要なのは以下の2つの値です。
1. `isolate`: インライン要素を「独立した単位」として扱い、親の双方向テキストアルゴリズムの影響を遮断します。
2. `embed`: 親の方向性に従いつつ、要素内での再配置を許容します。
現場でのベストプラクティスは、`direction`を指定する際は、セットで `unicode-bidi: isolate` を適用することです。これにより、意図しない文字の並び順の崩れを防ぐことができます。
—
実践:コピペで使える!堅牢な双方向テキスト制御
現場ですぐ使える、堅牢なCSSクラス設計の例です。多言語対応のフォームや、ユーザーが入力するコメント欄などで重宝します。
メッセージ:
مرحبا بالعالم
ユーザーID: user_123_abc
は、RTL環境でも左から右に正しく表示されます。
—
シニアエンジニアからのアドバイス:ハマりどころの回避術
最後に、実務でよくある「ハマりポイント」を2つだけ共有しておきます。
1. `bidi-override`の乱用は厳禁
`unicode-bidi: bidi-override`を使うと、テキストを強制的に指定方向へ並べ替えます。しかし、これは「論理的な順序」を破壊するため、スクリーンリーダーでの読み上げ順序がおかしくなります。本当に特殊なケース(暗号や特定のUIパーツ)以外では使わないのが賢明です。
2. CSSの論理プロパティへの移行
最近のモダンブラウザでは、`margin-left`や`padding-right`といった物理プロパティの代わりに、`margin-inline-start`や`padding-inline-end`といった論理プロパティを使うのが主流です。RTL対応を前提とするなら、今のうちに物理プロパティから卒業しておきましょう。
双方向テキストの制御は、一見すると地味で面倒なタスクに思えるかもしれません。しかし、ここを丁寧に作り込むことは、世界中のユーザーに対する「アクセシビリティへの敬意」の証明でもあります。
ぜひ、次回の多言語対応プロジェクトでは、この記事を思い出して実装してみてください。コードの質が一段階引き上がるはずです。

コメント