rtl_guidelines.rst (14924B)
1 RTL Guidelines 2 ============== 3 4 RTL languages such as Arabic, Hebrew, Persian and Urdu are read and 5 written from right-to-left, and the user interface for these languages 6 should be mirrored to ensure the content is easy to understand. 7 8 When a UI is changed from LTR to RTL (or vice-versa), it’s often called 9 mirroring. An RTL layout is the mirror image of an LTR layout, and it 10 affects layout, text, and graphics. 11 12 In RTL, anything that relates to time should be depicted as moving from 13 right to left. For example, forward points to the left, and backwards 14 points to the right. 15 16 Mirroring layout 17 ~~~~~~~~~~~~~~~~ 18 19 When a UI is mirrored, these changes occur: 20 21 - Text fields icons are displayed on the opposite side of a field 22 - Navigation buttons are displayed in reverse order 23 - Icons that communicate direction, like arrows, are mirrored 24 - Text is usually aligned to the right 25 26 In CSS, while it's possible to apply a rule for LTR and a separate one 27 specifically for RTL, it's usually better to use CSS `Logical Properties <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties>`_ 28 which provide the ability to control layout through logical, rather than 29 physical mappings. 30 31 +---------------------------------------------------------+--------------------------------------------------+ 32 | Do | Don't do | 33 +---------------------------------------------------------+--------------------------------------------------+ 34 | ``margin-inline-start: 5px`` | ``margin-left: 5px`` | 35 +---------------------------------------------------------+--------------------------------------------------+ 36 | ``padding-inline-end: 5px`` | ``padding-right: 5px`` | 37 +---------------------------------------------------------+--------------------------------------------------+ 38 | ``float: inline-start`` | ``float: left`` | 39 +---------------------------------------------------------+--------------------------------------------------+ 40 | ``inset-inline-start: 5px`` | ``left: 5px`` | 41 +---------------------------------------------------------+--------------------------------------------------+ 42 | ``border-inline-end: 1px`` | ``border-right: 1px`` | 43 +---------------------------------------------------------+--------------------------------------------------+ 44 | ``border-{start/end}-{start/end}-radius: 2px`` | ``border-{top/bottom}-{left/right}-radius: 2px`` | 45 +---------------------------------------------------------+--------------------------------------------------+ 46 | ``padding: 1px 2px`` | ``padding: 1px 2px 1px 2px`` | 47 +---------------------------------------------------------+--------------------------------------------------+ 48 | ``margin-block: 1px 3px`` && ``margin-inline: 4px 2px`` | ``margin: 1px 2px 3px 4px`` | 49 +---------------------------------------------------------+--------------------------------------------------+ 50 | ``text-align: start`` or ``text-align: match-parent`` | ``text-align: left`` | 51 | (depends on the context) | | 52 +---------------------------------------------------------+--------------------------------------------------+ 53 54 When there is no special RTL-aware property available, or when 55 left/right properties must be used specifically for RTL, use the pseudo 56 ``:-moz-locale-dir(rtl)`` (for XUL documents) or ``:dir(rtl)`` (for HTML 57 documents). 58 59 For example, this rule covers LTR to display searchicon.svg 7 pixels 60 from the left: 61 62 .. code:: css 63 64 .search-box { 65 background-image: url(chrome://path/to/searchicon.svg); 66 background-position: 7px center; 67 } 68 69 but an additional rule is necessary to cover RTL and place the search 70 icon on the right: 71 72 .. code:: css 73 74 .search-box:dir(rtl) { 75 background-position-x: right 7px; 76 } 77 78 .. warning:: 79 80 It may be inappropriate to use logical properties when embedding LTR 81 within RTL contexts. This is described further in the document. 82 83 Mirroring elements 84 ~~~~~~~~~~~~~~~~~~ 85 86 RTL content also affects the direction in which some icons and images 87 are displayed, particularly those depicting a sequence of events. 88 89 What to mirror 90 ^^^^^^^^^^^^^^ 91 92 - Icons or animations that imply directionality or motion like 93 back/forward buttons or progress bars 94 - Icons that imply text direction, like 95 `reader-mode.svg <https://searchfox.org/mozilla-central/rev/f9beb753a84aa297713d1565dcd0c5e3c66e4174/browser/themes/shared/icons/reader-mode.svg>`__ 96 - Icons that imply location of UI elements in the screen, like 97 `sidebars-right.svg <https://searchfox.org/mozilla-central/rev/74cc0f4dce444fe0757e2a6b8307d19e4d0e0212/browser/themes/shared/icons/sidebars-right.svg>`__, 98 `open-in-new.svg <https://searchfox.org/mozilla-central/rev/f9beb753a84aa297713d1565dcd0c5e3c66e4174/toolkit/themes/shared/icons/open-in-new.svg>`__, 99 `default theme's preview.svg <https://searchfox.org/mozilla-central/rev/f9beb753a84aa297713d1565dcd0c5e3c66e4174/toolkit/mozapps/extensions/default-theme/preview.svg>`__ 100 or 101 `pane-collapse.svg <https://searchfox.org/mozilla-central/rev/74cc0f4dce444fe0757e2a6b8307d19e4d0e0212/devtools/client/debugger/images/pane-collapse.svg>`__ 102 - Icons representing objects that are meant to be handheld should look 103 like they're being right-handed, like the `magnifying glass 104 icon <https://searchfox.org/mozilla-central/rev/e7c61f4a68b974d5fecd216dc7407b631a24eb8f/toolkit/themes/windows/global/icons/search-textbox.svg>`__ 105 - Twisties in their collapsed state. Note that if the context in which 106 they appear is LTR (e.g. code in a devtools HTML view), they should 107 not be mirrored, even if the user might be using an RTL locale. 108 109 What NOT to mirror 110 ^^^^^^^^^^^^^^^^^^ 111 112 - Text/numbers 113 - Icons containing text/numbers 114 - Icons/animations that are direction neutral 115 - Icons that wouldn't look differently if they'd be mirrored, like `X 116 buttons <https://searchfox.org/mozilla-central/rev/a78233c11a6baf2c308fbed17eb16c6e57b6a2ac/devtools/client/debugger/images/close.svg>`__ 117 or the `bookmark 118 star <https://searchfox.org/mozilla-central/rev/a78233c11a6baf2c308fbed17eb16c6e57b6a2ac/browser/themes/shared/icons/bookmark-hollow.svg>`__ 119 icon, or any other symmetric icon 120 - Icons that should look the same as LTR, like icons related to code 121 (which is always LTR) like 122 `tool-webconsole.svg <https://searchfox.org/mozilla-central/rev/74cc0f4dce444fe0757e2a6b8307d19e4d0e0212/devtools/client/themes/images/tool-webconsole.svg>`__ 123 - Checkmark icons 124 - Video/audio player controls 125 - Product logos 126 - Order of size dimensions (e.g., ``1920x1080`` should not become 127 ``1080x1920``) 128 - Order of size units (e.g., ``10 px`` should not become ``px 10`` 129 (unless the size unit is localizable)) 130 131 How 132 ^^^ 133 134 The most common way to mirror images is by flipping the X axis: 135 136 .. code:: css 137 138 transform: scaleX(-1); 139 140 Or, if you're already using ``transform`` with a different value on the same 141 element, you can also use `scale`: 142 143 .. code:: css 144 145 scale: -1 1; 146 147 Note that mirroring images that way doesn't work when the image is a part of 148 an element with text using ``background-image``, because then the text would 149 be mirrored along with the image, and the image would be positioned incorrectly. 150 For such cases, try to use a different method for displaying the image, 151 like having it as an element all on its own. 152 If that's not possible, add a separate pre-mirrored image asset and specify 153 it in a separate ``:dir(rtl)`` rule: 154 155 .. code:: css 156 157 .element-with-icon { 158 background-image: url("path/to/image/image.svg"); 159 } 160 161 .element-with-icon:dir(rtl) { 162 background-image: url("path/to/image/image-rtl.svg"); 163 } 164 165 For animations like a progress bar, when using ``@keyframes`` to change 166 the ``transform: translateX()`` states, make sure to add a different 167 ``@keyframes`` suited for RTL, and target that in a separate ``:dir()`` rule: 168 169 .. code:: css 170 171 #progressbar { 172 animation: progressbar-animation 1s linear infinite; 173 } 174 175 #progressbar:dir(rtl) { 176 animation-name: progressbar-animation-rtl; 177 } 178 179 @keyframes progressbar-animation { 180 0% { 181 transform: translateX(-100px); 182 } 183 100% { 184 transform: translateX(0); 185 } 186 } 187 188 @keyframes progressbar-animation-rtl { 189 0% { 190 transform: translateX(100px); 191 } 192 100% { 193 transform: translateX(0); 194 } 195 } 196 197 Likewise, if you're using ``transform-origin``, make sure to specify the 198 correct origin for RTL: 199 200 .. code:: css 201 202 #progressbar { 203 transform-origin: 0 0; 204 } 205 206 #progressbar:dir(rtl) { 207 transform-origin: 100% 0; 208 } 209 210 LTR text inside RTL contexts 211 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 212 213 By default, in RTL locales, some symbols like ``/`` and ``.`` will be moved 214 around and won't be displayed in the order that they were typed in. This 215 may be problematic for URLs for instance, where you don't want dots to 216 change position. 217 218 Here's a non-exhaustive list of elements that should be displayed like 219 they would be in LTR locales: 220 221 - Paths (e.g., C:\\Users\\username\\Desktop) 222 - Full URLs 223 - Code and code containers (like the DevTools' Inspector or the CSS 224 rules panel) 225 - about:config preference names and values 226 - Telephone numbers 227 - Usernames & passwords (most sites on the web expect LTR 228 usernames/passwords, but there may be exceptions) 229 - Other text fields where only LTR text is expected 230 231 To make sure these are displayed correctly, you can use one of the 232 following on the relevant element: 233 234 - ``direction: ltr`` 235 - ``dir="ltr"`` in HTML 236 237 Since the direction of such elements is forced to LTR, the text will 238 also be aligned to the left, which is undesirable from an UI 239 perspective, given that is inconsistent with the rest of the RTL UI 240 which has text usually aligned to the right. You can fix this using 241 ``text-align: match-parent``. In the following screenshot, both text 242 fields (username and password) and the URL have their direction set to 243 LTR (to display text correctly), but the text itself is aligned to the 244 right for consistency with the rest of the UI: 245 246 .. image:: about-logins-rtl.png 247 :alt: about:logins textboxes in RTL layout 248 249 However, since the direction in LTR, this also means that the start/end 250 properties will correspond to left/right respectively, which is probably 251 not what you expect. This means you have to use extra rules instead of 252 using logical properties. 253 254 Here's a full code example: 255 256 .. code:: css 257 258 .url { 259 direction: ltr; /* Force text direction to be LTR */ 260 261 /* `start` (the default value) will correspond to `left`, 262 * so we match the parent's direction in order to align the text to the right */ 263 text-align: match-parent; 264 } 265 266 /* :dir(ltr/rtl) isn't meaningful on .url, since it has direction: ltr, hence 267 * why it is matched on .container. */ 268 .container:dir(ltr) .url { 269 padding-left: 1em; 270 } 271 272 .container:dir(rtl) .url { 273 padding-right: 1em; 274 } 275 276 .. note:: 277 278 The LTR rule is separate from the global rule to avoid having the 279 left padding apply on RTL without having to reset it in the RTL rule. 280 281 Auto-directionality 282 ^^^^^^^^^^^^^^^^^^^ 283 284 Sometimes, the text direction on an element should vary dynamically 285 depending on the situation. This can be the case for a search input for 286 instance, a user may input a query in an LTR language, but may also 287 input a query in a RTL language. In this case, the search input has to 288 dynamically pick the correct directionality based on the first word, in 289 order to display the query text correctly. The typical way to do this is 290 to use ``dir="auto"`` in HTML. It is essential that 291 ``text-align: match-parent`` is set, to avoid having the text alignment 292 change based on the query, and logical properties also cannot be used on 293 the element itself given they can change meaning depending on the query. 294 295 Testing 296 ~~~~~~~ 297 298 To test for RTL layouts in Firefox, you can go to about:config and 299 set ``intl.l10n.pseudo`` to ``bidi``, or select the ``Enable "bidi" locale`` 300 option in the 3-dots menu in the :doc:`Browser Toolbox </devtools-user/browser_toolbox/index>`. 301 The Firefox UI should immediately flip, but a restart may be required 302 to take effect in some Firefox features and interactions. 303 304 .. note:: 305 306 When testing with ``intl.l10n.pseudo`` set to ``bidi``, you may see some 307 oddities regarding text ordering due to the nature of displaying LTR 308 text in RTL layout. 309 310 .. image:: about-protections-rtl.png 311 :alt: about:protections in RTL layout- English vs. Hebrew 312 313 This shouldn't be an issue when using an actual RTL build or language pack. 314 315 How to spot RTL-related issues 316 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 317 318 - Punctuation marks should appear on the left side of a 319 word/sentence/paragraph on RTL, so if a *localizable* string appears 320 in the UI with a dot, colon, ellipsis, question or exclamation mark 321 on the right side of the text, this probably means that the text 322 field is forced to be displayed as LTR. 323 - If icons/images/checkmarks do not appear on the opposite side of 324 text, when compared to LTR. 325 - If buttons (like the close button, "OK" and "Cancel" etc.) do not 326 appear on the opposite side of the UI and not in the opposite order, 327 when compared to LTR. 328 - If paddings/margins/borders are not the same from the opposite side, 329 when compared to LTR. 330 - Although Hebrew uses ``1 2 3``, all the other RTL locales we support 331 should use ``١ ٢ ٣`` as digits. So if you see ``1 2 3`` on any such 332 locale, that likely indicates a bug. 333 - If navigating in the UI using the left/right arrow keys does not 334 select the correct element (i.e., pressing Left selects an item on 335 the right). 336 - If navigating in the UI using the Tab key does not focus elements 337 from right to left, in an RTL context. 338 - If code is displayed as RTL (e.g., ``;padding: 20px`` - the semicolon 339 should appear on the right side of the code). Code can still be 340 aligned to the right if it appears in an RTL context. 341 342 See also 343 ~~~~~~~~ 344 345 - `RTL Best 346 Practices <https://docs.google.com/document/d/1Rc8rvwsLI06xArFQouTinSh3wNte9Sqn9KWi1r7xY4Y/edit#heading=h.pw54h41h12ct>`__ 347 - Building RTL-Aware Web Apps & Websites: `Part 348 1 <https://hacks.mozilla.org/2015/09/building-rtl-aware-web-apps-and-websites-part-1/>`__, 349 `Part 350 2 <https://hacks.mozilla.org/2015/10/building-rtl-aware-web-apps-websites-part-2/>`__ 351 352 Credits 353 ~~~~~~~ 354 355 Google's `Material Design guide for 356 RTL <https://material.io/design/usability/bidirectionality.html>`__