tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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>`__