tor-browser

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

css_guidelines.rst (18738B)


      1 CSS Guidelines
      2 ==============
      3 
      4 This document contains guidelines defining how CSS inside the Firefox
      5 codebase should be written, it is notably relevant for Firefox front-end
      6 engineers.
      7 
      8 Basics
      9 ------
     10 
     11 Here are some basic tips that can optimize reviews if you are changing
     12 CSS:
     13 
     14 -  Avoid ``!important`` but if you have to use it, make sure it's
     15   obvious why you're using it (ideally with a comment). The
     16   `Overriding CSS`_ section contains more information about this.
     17 -  Avoid magic numbers; prefer automatic sizing or alignment methods.
     18   Some examples to avoid:
     19 
     20   -  absolutely positioned elements
     21   -  hardcoded values such as: ``vertical-align: -2px;`` . The reason
     22      you should avoid such "hardcoded" values is that, they don't
     23      necessarily work for all font-size configurations.
     24 
     25 -  Avoid setting styles in JavaScript. It's generally better to set a
     26   class and then specify the styles in CSS.
     27 -  ``classList`` is generally better than ``className``. There's less
     28   chance of overwriting an existing class.
     29 -  Only use generic selectors such as ``:last-child``, when it is what
     30   you mean semantically. If not, using a semantic class name is more
     31   descriptive and usually better.
     32 
     33 Boilerplate
     34 ~~~~~~~~~~~
     35 
     36 Make sure each file starts with the standard copyright header (see
     37 `License Boilerplate <https://www.mozilla.org/MPL/headers/>`__).
     38 
     39 Before adding more CSS
     40 ~~~~~~~~~~~~~~~~~~~~~~
     41 
     42 It is good practice to check if the CSS that is being written is needed,
     43 it can be the case that a common component has been already written
     44 could be reused with or without changes. Most of the time, the common
     45 component already follows the a11y/theme standards defined in this
     46 guide. So, when possible, always prefer editing common components to
     47 writing your own.
     48 
     49 Also, it is good practice to introduce a common class when the new
     50 element you are styling reuses some styles from another element, this
     51 allows the maintenance cost and the amount of code duplication to be
     52 reduced.
     53 
     54 Formatting
     55 ----------
     56 
     57 Spacing & Indentation
     58 ~~~~~~~~~~~~~~~~~~~~~
     59 
     60 -  2 spaces indentation is preferred
     61 -  Add a space after each comma, **except** within color functions:
     62 
     63 .. code:: css
     64 
     65   linear-gradient(to bottom, black 1px, rgba(255,255,255,0.2) 1px)
     66 
     67 -  Always add a space before ``!important``.
     68 
     69 Omit units on 0 values
     70 ~~~~~~~~~~~~~~~~~~~~~~
     71 
     72 Do this:
     73 
     74 .. code:: css
     75 
     76     margin: 0;
     77 
     78 Not this:
     79 
     80 .. code:: css
     81 
     82     margin: 0px;
     83 
     84 Use expanded syntax
     85 ~~~~~~~~~~~~~~~~~~~
     86 
     87 It is often harder to understand what the shorthand is doing and the
     88 shorthand can also hide some unwanted default values. It is good to
     89 privilege expanded syntax to make your intentions explicit.
     90 
     91 Do this:
     92 
     93 .. code:: css
     94 
     95     border-color: red;
     96 
     97 Not this:
     98 
     99 .. code:: css
    100 
    101     border: red;
    102 
    103 Put multiple selectors on different lines
    104 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    105 
    106 Do this:
    107 
    108 .. code:: css
    109 
    110   h1,
    111   h2,
    112   h3 {
    113     font-family: sans-serif;
    114     text-align: center;
    115   }
    116 
    117 Not this:
    118 
    119 .. code:: css
    120 
    121   h1, h2, h3 {
    122     font-family: sans-serif;
    123     text-align: center;
    124   }
    125 
    126 Naming standards for class names
    127 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    128 
    129 -  ``lower-case-with-dashes`` is the most common.
    130 -  But ``camelCase`` is also used sometimes. Try to follow the style of
    131   existing or related code.
    132 
    133 Other tips
    134 ~~~~~~~~~~
    135 
    136 -  Assume ``="true"`` in attribute selectors.
    137 
    138   -  Example: Use ``option[checked]``, not ``option[checked="true"]``.
    139 
    140 -  Avoid ID selectors unless it is really the wanted goal, since IDs
    141   have higher specificity and therefore are harder to override.
    142 -  Using descendant selectors is good practice for performance when
    143   possible:
    144 
    145   -  For example:
    146      ``.autocomplete-item[selected] > .autocomplete-item-title`` would
    147      be more efficient than
    148      ``.autocomplete-item[selected] .autocomplete-item-title``
    149 
    150 Overriding CSS
    151 --------------
    152 
    153 Before overriding any CSS rules, check whether overriding is really
    154 needed. Sometimes, when copy-pasting older code, it happens that the
    155 code in question contains unnecessary overrides. This could be because
    156 the CSS that it was overriding got removed in the meantime. In this
    157 case, dropping the override should work.
    158 
    159 It is also good practice to look at whether the rule you are overriding
    160 is still needed: maybe the UX spec for the component has changed and
    161 that rule can actually be updated or removed. When this is the case,
    162 don't be afraid to remove or update that rule.
    163 
    164 Once the two things above have been checked, check if the other rule you
    165 are overriding contains ``!important``, if that is case, try putting it
    166 in question, because it might have become obsolete.
    167 
    168 Afterwards, check the specificity of the other selector; if it is
    169 causing your rule to be overridden, you can try reducing its
    170 specificity, either by simplifying the selector or by changing where the
    171 rule is placed in the stylesheet. If this isn't possible, you can also
    172 try introducing a ``:not()`` to prevent the other rule from applying,
    173 this is especially relevant for different element states (``:hover``,
    174 ``:active``, ``[checked]`` or ``[disabled]``). However, never try to
    175 increase the selector of the rule you are adding as it can easily become
    176 hard to understand.
    177 
    178 Finally, once you have checked all the things above, you can permit
    179 yourself to use ``!important`` along with a comment why it is needed.
    180 
    181 Using CSS variables
    182 -------------------
    183 
    184 Adding new variables
    185 ~~~~~~~~~~~~~~~~~~~~
    186 
    187 Before adding new CSS variables, please consider the following
    188 questions:
    189 
    190 #. **Is the variable value changed at runtime?**
    191   *(Either from JavaScript or overridden by another CSS file)*
    192   **If the answer is no**, consider using a preprocessor variable or
    193   inlining the value.
    194 
    195 #. **Is the variable value used multiple times?**
    196   **If the answer is no and the value isn't changed at runtime**, then
    197   you likely don't need a CSS variable.
    198 
    199 #. **Is there an alternative to using the variable like inheriting or
    200   using the ``currentcolor`` keyword?**
    201   Using inheriting or using ``currentcolor`` will prevent repetition of
    202   the value and it is usually good practice to do so.
    203 
    204 In general, it's good to first think of how some CSS could be written
    205 cleanly without the CSS variable(s) and then think of how the CSS
    206 variable could improve that CSS.
    207 
    208 Using variables
    209 ~~~~~~~~~~~~~~~
    210 
    211 Use the variable according to its naming
    212 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    213 
    214 Do this:
    215 
    216 .. code:: css
    217 
    218   xul|tab:hover {
    219     background-color: var(--in-content-box-background-hover);
    220   }
    221 
    222 Not this:
    223 
    224 .. code:: css
    225 
    226   #certificateErrorDebugInformation {
    227     background-color: var(--in-content-box-background-hover);
    228   }
    229 
    230 Localization
    231 ------------
    232 
    233 Text Direction
    234 ~~~~~~~~~~~~~~
    235 
    236 -  For margins, padding and borders, use
    237   ``inline-start``/``inline-end`` rather than ``left``/``right``.
    238   *Example:* Use ``margin-inline-start: 3px;`` instead of
    239   ``margin-left: 3px``.
    240 -  For RTL-aware positioning (left/right), use
    241   ``inset-inline-start``/``inset-inline-end``.
    242 -  For RTL-aware float layouts, ``float: inline-start|inline-end`` can
    243   be used instead of ``float: left|right``.
    244 -  The RTL-aware equivalents of
    245   ``border-{top/bottom}-{left/right}-radius`` are
    246   ``border-{start/end}-{start/end}-radius``
    247 -  When there is no special RTL-aware property available, use the pseudo
    248   ``:-moz-locale-dir(ltr|rtl)`` (for XUL files) or ``:dir(ltr|rtl)``
    249   (for HTML files).
    250 -  Remember that while a tab content's scrollbar still shows on the
    251   right in RTL, an overflow scrollbar will show on the left.
    252 -  Write ``padding: 0 3px 4px;`` instead of
    253   ``padding: 0 3px 4px 3px;``. This makes it more obvious that the
    254   padding is symmetrical (so RTL won't be an issue).
    255 
    256 .. note::
    257 
    258   See `CSS Logical Properties and
    259   Values <https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Logical_Properties>`__
    260   for more information.
    261 
    262 Writing cross-platform CSS
    263 --------------------------
    264 
    265 Firefox supports many different platforms and each of those platforms
    266 can contain many different configurations:
    267 
    268 -  Windows 7, 8 and 10
    269 
    270   -  Default theme
    271   -  Aero basic (Windows 7, 8)
    272   -  Windows classic (Windows 7)
    273   -  High contrast (All versions)
    274 
    275 -  Linux
    276 -  macOS
    277 
    278 File structure
    279 ~~~~~~~~~~~~~~
    280 
    281 -  The ``browser/`` directory contains styles specific to Firefox
    282 -  The ``toolkit/`` directory contains styles that are shared across all
    283   toolkit applications (Thunderbird and SeaMonkey)
    284 
    285 Under each of those two directories, there is a ``themes`` directory
    286 containing 4 sub-directories:
    287 
    288 -  ``shared``
    289 -  ``linux``
    290 -  ``osx``
    291 -  ``windows``
    292 
    293 The ``shared`` directories contain styles shared across all 3 platforms,
    294 while the other 3 directories contain styles respective to their
    295 platform.
    296 
    297 For new CSS, when possible try to privilege using the ``shared``
    298 directory, instead of writing the same CSS for the 3 platform specific
    299 directories, especially for large blocks of CSS.
    300 
    301 Content CSS vs. Theme CSS
    302 ^^^^^^^^^^^^^^^^^^^^^^^^^
    303 
    304 The following directories also contain CSS:
    305 
    306 -  ``browser/base/content/``
    307 -  ``toolkit/content/``
    308 
    309 These directories contain content CSS, that applies on all platforms,
    310 which is styling deemed to be essential for the browser to behave
    311 correctly. To determine whether some CSS is theme-side or content-side,
    312 it is useful to know that certain CSS properties are going to lean one
    313 way or the other: color - 99% of the time it will be theme CSS, overflow
    314 - 99% content.
    315 
    316 +-----------------+--------------+----------------+----------------+
    317 | 99% theme       | 70% theme    | 70% content    | 99% content    |
    318 +=================+==============+================+================+
    319 | font-\*, color, | line-height, | cursor, width, | overflow,      |
    320 | \*-color,       | padding,     | max-width,     | direction,     |
    321 | border-\*,      | margin       | top,           | display,       |
    322 | -moz-appearance |              | bottom [2]_,   | \*-align,      |
    323 | [1]_            |              | etc            | align-\*,      |
    324 |                 |              |                | \*-box-\*,     |
    325 |                 |              |                | flex-\*, order |
    326 +-----------------+--------------+----------------+----------------+
    327 
    328 If some CSS is layout or functionality related, then it is likely
    329 content CSS. If it is esthetics related, then it is likely theme CSS.
    330 
    331 When importing your stylesheets, it's best to import the content CSS
    332 before the theme CSS, that way the theme values get to override the
    333 content values (which is probably what you want), and you're going to
    334 want them both after the global values, so your imports will look like
    335 this:
    336 
    337 .. code:: html
    338 
    339   <?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
    340   <?xml-stylesheet href="chrome://browser/content/path/module.css" type="text/css"?>
    341   <?xml-stylesheet href="chrome://browser/skin/path/module.css" type="text/css"?>
    342 
    343 .. [1] -moz-appearance is tricky. Generally, when specifying
    344   -moz-appearance: foo; you're giving hints as to how something should
    345   act, however -moz-appearance: none; is probably saying 'ignore
    346   browser preconceptions - I want a blank sheet', so that's more
    347   visual. However -moz-appearance values aren't implemented and don't
    348   behave consistently across platforms, so idealism aside
    349   -moz-appearance should always be in theme CSS.
    350 
    351 .. [2] However there is probably a better way than using absolute
    352   positioning.
    353 
    354 Colors
    355 ~~~~~~
    356 
    357 For common areas of the Firefox interface (panels, toolbar buttons,
    358 etc.), mozilla-central often comes with some useful CSS variables that
    359 are adjusted with the correct values for different platform
    360 configurations, so using those CSS variables can definitively save some
    361 testing time, as you can assume they already work correctly.
    362 
    363 Using the ``currentcolor`` keyword or inheriting is also good practice,
    364 because sometimes the needed value is already in the color or on the
    365 parent element. This is especially useful in conjunction with icons
    366 using ``-moz-context-properties: fill;`` where the icon can adjust to
    367 the right platform color automatically from the text color. It is also
    368 possible to use ``currentcolor`` with other properties like
    369 ``opacity`` or ``fill-opacity`` to have different
    370 opacities of the platform color.
    371 
    372 High contrast mode
    373 ~~~~~~~~~~~~~~~~~~
    374 
    375 Content area
    376 ^^^^^^^^^^^^
    377 
    378 On Windows high contrast mode, in the content area, Gecko does some
    379 automatic color adjustments regarding page colors. Part of those
    380 adjustments include making all ``box-shadow`` invisible, so this is
    381 something to be aware of if you create a focus ring or a border using
    382 the ``box-shadow`` property: consider using a ``border`` or an
    383 ``outline`` if you want the border/focus ring to stay visible in
    384 high-contrast mode. An example of such bug is `bug
    385 1516767 <https://bugzilla.mozilla.org/show_bug.cgi?id=1516767>`__.
    386 
    387 Another adjustment to be aware of is that Gecko removes all the
    388 ``background-image`` when high contrast mode is enabled. Consider using
    389 an actual ``<img>`` tag (for HTML documents) or ``list-style-image``
    390 (for XUL documents) if rendering the image is important.
    391 
    392 If you are not using Windows, one way to test against those adjustments
    393 on other platforms is:
    394 
    395 -  Going to about:preferences
    396 -  Clicking on the "Colors..." button in the "Fonts & Colors"
    397   sub-section of the "Language and Appearance" section
    398 -  Under "Override the colors specified by the page with your selections
    399   above", select the "Always" option
    400 
    401 Chrome area
    402 ^^^^^^^^^^^
    403 
    404 The automatic adjustments previously mentioned only apply to pages
    405 rendered in the content area. The chrome area of Firefox uses colors as
    406 authored, which is why using pre-defined variables, ``currentcolor`` or
    407 inheritance is useful to integrate with the system theme with little
    408 hassle.
    409 
    410 If not, as a last resort, using `system
    411 colors <https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#system_colors>`__
    412 also works for non-default Windows themes or Linux. In general, the
    413 following colors are used:
    414 
    415 -  ``-moz-Field``: textbox or field background colors, also used as the
    416   background color of listboxes or trees.
    417 -  ``-moz-FieldText``: textbox or field text colors, also used as the
    418   text color of listboxes or trees.
    419 -  ``-moz-Dialog``: window or dialog background color.
    420 -  ``-moz-DialogText``: window or dialog text color.
    421 -  ``GrayText``: used on disabled items as text color. Do not use it on
    422   text that is not disabled to desemphsize text, because it does not
    423   guarantee a sufficient contrast ratio for non-disabled text.
    424 -  ``ThreeDShadow``: Used as border on elements.
    425 -  ``ThreeDLightShadow``: Used as light border on elements.
    426 
    427 Using the background/text pairs is especially important to ensure the
    428 contrast is respected in all situations. Never mix custom text colors
    429 with a system background color and vice-versa.
    430 
    431 Note that using system colors is only useful for the chrome area, since
    432 content area colors are overridden by Gecko anyway.
    433 
    434 Writing media queries
    435 ~~~~~~~~~~~~~~~~~~~~~
    436 
    437 Boolean media queries
    438 ^^^^^^^^^^^^^^^^^^^^^
    439 
    440 Do this:
    441 
    442 .. code:: css
    443 
    444   @media (-moz-mac-yosemite-theme: 0) {
    445 
    446 Not this:
    447 
    448 .. code:: css
    449 
    450   @media not all and (-moz-mac-yosemite-theme) {
    451 
    452 Privilege CSS for most common configuration
    453 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    454 
    455 It is better to put the most common configuration (latest version of an
    456 OS, or default theme for example) outside of the media query. In the
    457 following example, ``-moz-mac-yosemite-theme`` targets macOS 10.10 and
    458 higher, so it should be privileged over the styling for macOS 10.9.
    459 
    460 Do this:
    461 
    462 .. code:: css
    463 
    464   @media (-moz-mac-yosemite-theme: 0) {
    465     #placesList {
    466       box-shadow: inset -2px 0 0 hsla(0,0%,100%,.2);
    467     }
    468   }
    469 
    470 Not this:
    471 
    472 .. code:: css
    473 
    474   #placesList {
    475     box-shadow: inset -2px 0 0 hsla(0,0%,100%,.2);
    476   }
    477 
    478   @media (-moz-mac-yosemite-theme) {
    479     #placesList {
    480       box-shadow: none;
    481     }
    482   }
    483 
    484 Theme support
    485 -------------
    486 
    487 Firefox comes built-in with 3 themes: default, light and dark. The
    488 built-in light/dark themes are a bit special as they load the
    489 ``compacttheme.css`` stylesheet. In addition to this, Firefox supports a
    490 variety of WebExtension themes that can be installed from AMO. For
    491 testing purposes, `here is an example of a WebExtension
    492 theme. <https://addons.mozilla.org/en-US/firefox/addon/arc-dark-theme-we/>`__
    493 
    494 Writing theme-friendly CSS
    495 ~~~~~~~~~~~~~~~~~~~~~~~~~~
    496 
    497 -  Some CSS variables that are pre-adjusted for different platforms are
    498   also pre-adjusted for themes, so it's again a good idea to use them
    499   for theme support.
    500 -  The text color of elements often contains valuable information from
    501   the theme colors, so ``currentcolor``/inheritance is again a good
    502   idea for theme support.
    503 -  Never write CSS specially for the built-in light/dark theme in
    504   ``compacttheme.css`` unless that CSS isn't supposed to affect
    505   WebExtension themes.
    506 -  These selectors can be used to target themed areas, though in general it's
    507   recommended to try to avoid them and use ``light-dark()`` to get the right
    508   colors automatically:
    509 
    510   - ``:root[lwt-toolbar-field="light/dark"]``: explicitly light or dark address bar and
    511     searchbar.
    512   - ``:root[lwt-toolbar-field-focus="light/dark"]``: explicitly light or dark address bar and
    513     searchbar in the focused state.
    514   - ``:root[lwt-popup="light/dark"]``: explicitly light or dark arrow panels
    515     and autocomplete panels.
    516   - ``:root[lwt-sidebar="light/dark"]``: explicitly light or dark sidebars.
    517 
    518 -  If you'd like a different shade of a themed area and no CSS variable
    519   is adequate, using colors with alpha transparency is usually a good
    520   idea, as it will preserve the original theme author's color hue.
    521 
    522 Variables
    523 ~~~~~~~~~
    524 
    525 For clarity, CSS variables that are only used when a theme is enabled
    526 have the ``--lwt-`` prefix.
    527 
    528 Layout & performance
    529 --------------------
    530 
    531 Layout
    532 ~~~~~~
    533 
    534 Mixing XUL flexbox and HTML flexbox can lead to undefined behavior.
    535 
    536 CSS selectors
    537 ~~~~~~~~~~~~~
    538 
    539 When targeting the root element of a page, using ``:root`` is the most
    540 performant way of doing so.
    541 
    542 Reflows and style flushes
    543 ~~~~~~~~~~~~~~~~~~~~~~~~~
    544 
    545 See :ref:`Performance best practices for Firefox front-end engineers`
    546 for more information about this.
    547 
    548 Misc
    549 ----
    550 
    551 Text aliasing
    552 ~~~~~~~~~~~~~
    553 
    554 When convenient, avoid setting the ``opacity`` property on
    555 text as it will cause text to be aliased differently.
    556 
    557 HDPI support
    558 ~~~~~~~~~~~~
    559 
    560 It's recommended to use SVG since it keeps the CSS clean when supporting
    561 multiple resolutions. See the :ref:`SVG Guidelines` for more information
    562 on SVG usage.
    563 
    564 However, if only 1x and 2x PNG assets are available, you can use this
    565 ``@media`` query to target higher density displays (HDPI):
    566 
    567 .. code:: css
    568 
    569   @media (min-resolution: 1.1dppx)