DevTools/CSSTips: Difference between revisions

(Updating page to be more accurate with latest code base)
 
(7 intermediate revisions by 3 users not shown)
Line 3: Line 3:
== Basics ==
== Basics ==


First, you can find existing DevTools CSS at https://dxr.mozilla.org/mozilla-central/source/browser/themes/shared.  Here are some basic tips that can optimize reviews if you are changing CSS.
First, you can find existing DevTools CSS at https://dxr.mozilla.org/mozilla-central/source/devtools/client/themes.  Here are some basic tips that can optimize reviews if you are changing CSS.


* Split your CSS into theme and content files (see below)
* Avoid <tt>!important</tt> but if you have to use it, make sure it's obvious why you're using it (maybe with a comment)
* Avoid <tt>!important</tt> but if you have to use it, make sure it's obvious why you're using it (maybe with a comment)
* Avoid magic numbers, prefer automatic sizing
* Avoid magic numbers, prefer automatic sizing
* Avoid platforms specific styles, put everything in the <tt>shared</tt> directory
* Avoid preprocessor variables, use CSS variables instead
* Avoid setting styles in JavaScript. It's generally better to set a class and then specify the styles in CSS
* Avoid setting styles in JavaScript. It's generally better to set a class and then specify the styles in CSS
* <tt>classList</tt> is generally better than <tt>className</tt>. There's less chance of over-writing an existing class
* <tt>classList</tt> is generally better than <tt>className</tt>. There's less chance of over-writing an existing class
Line 18: Line 19:


CSS changes to the toolbox should generally be similar across platforms since they used a shared implementation, but there can still be differences worth checking out.  Check major changes on Windows, OSX and Ubuntu.
CSS changes to the toolbox should generally be similar across platforms since they used a shared implementation, but there can still be differences worth checking out.  Check major changes on Windows, OSX and Ubuntu.


== Formatting ==
== Formatting ==
 
We use 2-spaces indentation for the CSS.
In general the formatting looks like this:
In general the formatting looks like this:
  selector,
  selector,
Line 33: Line 33:
** Example: Use <tt>margin: 0;</tt>, not <tt>margin: 0px;</tt>
** Example: Use <tt>margin: 0;</tt>, not <tt>margin: 0px;</tt>
* Add a space after each comma, '''except''' within color functions
* Add a space after each comma, '''except''' within color functions
** Example: <tt>-moz-linear-gradient(top, black 1px, rgba(255,255,255,0.2) 1px)</tt>
** Example: <tt>linear-gradient(to bottom, black 1px, rgba(255,255,255,0.2) 1px)</tt>
* Always add a space before <tt> !important</tt>
* Always add a space before <tt> !important</tt>
* Assume <tt>="true"</tt> in attribute selectors
* Assume <tt>="true"</tt> in attribute selectors
Line 43: Line 43:
* lower-case-with-dashes is the most common
* lower-case-with-dashes is the most common
* But camelCase is also used sometimes.  It makes sense to first try to fit in with code around, and if there is doubt or if isn't anything to fit in with to use lower-case-with-dashes.
* But camelCase is also used sometimes.  It makes sense to first try to fit in with code around, and if there is doubt or if isn't anything to fit in with to use lower-case-with-dashes.
== Light and Dark theme support ==
DevTools support 3 different themes : the dark theme, the light theme and the firebug theme. In order to support them, there are 3 class names available (theme-dark, theme-light and theme-firebug). Here are some common practices to follow :
* Use [https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors pre-defined CSS variables] instead of hardcoding colors when possible
* If you need to support themes and the pre-defined variables don't fit, define a variable with your custom colors at the beginning of the CSS file, this avoids selector duplication in the code.
Example :
.theme-light {
  --some-variable-name: <color-for-light-theme>;
}
.theme-dark {
  --some-variable-name: <color-for-dark-theme>;
}
.theme-firebug {
  --some-variable-name: <color-for-dark-theme>;
}
#myElement {
  background-color: var(--some-variable-name);
}
== HDPI support ==
In order to support retina displays and Windows DPI settings, it's recommended to use SVG since it keeps the CSS clean. However, if only 1x and 2x PNG assets are available, you can use this @media query to target HDPI : <tt>@media (min-resolution: 1.1dppx)</tt>


== Performance ==
== Performance ==
Line 52: Line 73:
** If possible find ways to use '''only''' id selectors, class selectors and selector groups
** If possible find ways to use '''only''' id selectors, class selectors and selector groups


== Content or Theme CSS ==
== Localization ==


We have 2 competing priorities - A desire to avoid repetition (aka [https://en.wikipedia.org/wiki/Don%27t_repeat_yourself DRY]), and the desire to allow Firefox to look different depending on your platform or your theme preferences. As a result we split our CSS into rules that are likely to change between themes (aka theme CSS) and those that are not (aka content CSS).
=== Text Direction ===
* For margins, padding and borders, use inline-start/inline-end rather than left/right
** Example: Use <tt>margin-inline-start: 3px;</tt> not <tt>margin-left: 3px</tt>
* For RTL-aware positioning (left/right), use <tt>offset-inline-start/end</tt>
* When there is no special RTL-aware property (eg. float: left|right) available, use the pseudo :-moz-locale-dir(ltr|rtl) (for XUL files) or :dir(ltr|rtl) (for HTML files)
* Remember that while a tab content's scrollbar still shows on the right in RTL, an overflow scrollbar will show on the left
* Write "padding: 0 3px 4px;" instead of "padding: 0 3px 4px 3px;". This makes it more obvious that the padding is symmetrical (so RTL won't be an issue)


There are stored:
=== RTL support for html modules ===
* content CSS files are stored in with your JS/HTML/etc
* theme CSS files are stored in the <tt>themes/(windows|osx|linux)</tt> directories


Typically certain CSS properties are going to lean one way or the other: color - 99% of the time it will be theme CSS, overflow - 99% content.
By default, new HTML modules support only left-to-right (LTR) and do not reuse the current direction of the browser.  


<table style="font-size: 90%; border: 1px solid #999;">
To enable right-to-left (RTL) support in a module, set the [dir] attribute on the document element of the module:
<tr>
* Example: <code><html xmlns="http://www.w3.org/1999/xhtml" dir=""></code>
<th> 99% theme
<th> 70% theme
<th> 70% content
<th> 99% content
<tr>
<td> <tt>font-*, color, *-color, border-*, -moz-appearance [1]</tt>
<td> <tt>line-height, padding, margin</tt>
<td> <tt>cursor, width, max-width, top, bottom [2], etc</tt>
<td> <tt>overflow, direction, display, *-align, *-box-*</tt>
</table>


If you're not sure then go for content CSS unless you can imagine the value changing on another platform.
The appropriate value for the dir attribute will then be set when the toolbox will load this module.


When importing your stylesheets, it's best to import the content CSS before the theme CSS, that way the theme values get to override the content values (which is probably what you want), and you're going to want them both before the global values, so your imports will look like this:
=== Testing ===
 
* The recommended workflow to test RTL on DevTools is to use the [https://addons.mozilla.org/en-US/firefox/addon/force-rtl/ Force RTL extension]. After changing the direction using Force RTL, you should restart the devtools to make sure all modules apply the new direction. A future version of Force RTL will be able to update dynamically all DevTools documents.
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
* Going to about:config and setting <tt>intl.uidirection.en</tt> to rtl is not recommended, and will always require to re-open devtools to have any impact.
<?xml-stylesheet href="chrome://browser/content/path/module.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/path/module.css" type="text/css"?>
 
For devtools CSS files then <tt>path</tt> is likely to be the string <tt>devtools</tt>.
 
[1] <tt>-moz-appearance</tt> is tricky. Generally, when specifying <tt>-moz-appearance: foo;</tt> you're giving hints as to how something should act, however <tt>-moz-appearance: none;</tt> is probably saying 'ignore browser preconceptions - I want a blank sheet', so that's more visual. However <tt>-moz-appearance</tt> values aren't implemented and don't behave consistently across platforms, so idealism aside <tt>-moz-appearance</tt> should always be in theme CSS.
 
[2] However there is probably a better way than using absolute positioning.
 
== Localization ==
 
Text Direction:
* For margins, padding and borders, use start/end rather than left/right
** Example: Use <tt>-moz-margin-start: 3px;</tt> not <tt>margin-left: 3px</tt>
* When there is no special RTL-aware property (eg. float: left|right) available, use the pseudo :-moz-locale-dir(ltr|rtl)
* Remember that while a tab content's scrollbar still shows on the right in RTL, an overflow scrollbar will show on the left
* Write "padding: 0 3px 4px;" instead of "padding: 0 3px 4px 3px;". This makes it more obvious that the padding is symmetrical (so RTL won't be an issue)
 
Testing:
* Use the [https://addons.mozilla.org/en-US/firefox/addon/force-rtl/ Force RTL extension]
* Or go to about:config and set <tt>intl.uidirection.en</tt> to rtl


== Toggles ==
== Toggles ==


Sometimes you have a style that you want to turn on and off. For example a tree twisty, a tab background, etc. The Mozilla way is to perform the toggle using an attribute rather than a class. So:
Sometimes you have a style that you want to turn on and off. For example a tree twisty, a tab background, etc. The Mozilla way is to perform the toggle using an attribute rather than a class. So:
  .tree-node[opened] {
.tree-node {
  background-image: url(right-arrow.png);
}
  .tree-node[open] {
   background-image: url(down-arrow.png);
   background-image: url(down-arrow.png);
  }
  }
.tree-node:not([opened]) {
  background-image: url(right-arrow.png);
}
== The Mozilla Environment ==
Pre-defined classes:
* Use <tt>plain</tt> in place of <tt>margin: 0</tt>
Theme values:
* Use them where possible
** Example: <tt>border-radius: @toolbarbuttonCornerRadius@</tt>, not <tt>border-radius: 3px</tt>
* Where a theme value doesn't fit, make sure you have buy-in from UX
Lists of theme values:
* [https://developer.mozilla.org/en/CSS/color_value#Mozilla_System_Color_Extensions System Colors]
* [https://developer.mozilla.org/en/CSS/font#Mozilla_Extensions System Fonts]
* [https://developer.mozilla.org/en/CSS_Reference/Mozilla_Extensions CSS Extensions]


== Tips ==
== Tips ==

Latest revision as of 07:37, 17 December 2016

This page is for information about CSS used by the DevTools toolbox. Wondering about the Dev Edition theme? See this page for more information about the Developer Edition theme

Basics

First, you can find existing DevTools CSS at https://dxr.mozilla.org/mozilla-central/source/devtools/client/themes. Here are some basic tips that can optimize reviews if you are changing CSS.

  • Avoid !important but if you have to use it, make sure it's obvious why you're using it (maybe with a comment)
  • Avoid magic numbers, prefer automatic sizing
  • Avoid platforms specific styles, put everything in the shared directory
  • Avoid preprocessor variables, use CSS variables instead
  • Avoid setting styles in JavaScript. It's generally better to set a class and then specify the styles in CSS
  • classList is generally better than className. There's less chance of over-writing an existing class

Boilerplate

Make sure each file starts with the standard copyright header (see License Boilerplate)

Testing

CSS changes to the toolbox should generally be similar across platforms since they used a shared implementation, but there can still be differences worth checking out. Check major changes on Windows, OSX and Ubuntu.

Formatting

We use 2-spaces indentation for the CSS. In general the formatting looks like this:

selector,
alternate-selector {
  property: value;
  other-property: other-value;
}

Also:

  • Omit units on 0 values
    • Example: Use margin: 0;, not margin: 0px;
  • Add a space after each comma, except within color functions
    • Example: linear-gradient(to bottom, black 1px, rgba(255,255,255,0.2) 1px)
  • Always add a space before !important
  • Assume ="true" in attribute selectors
    • Example: Use option[checked], not option[checked="true"]
  • Use longhand versions of properties so it's clear what you're changing.
    • Example: Use border-color: red, not border: red;

Naming Standards for class names:

  • lower-case-with-dashes is the most common
  • But camelCase is also used sometimes. It makes sense to first try to fit in with code around, and if there is doubt or if isn't anything to fit in with to use lower-case-with-dashes.

Light and Dark theme support

DevTools support 3 different themes : the dark theme, the light theme and the firebug theme. In order to support them, there are 3 class names available (theme-dark, theme-light and theme-firebug). Here are some common practices to follow :

  • Use pre-defined CSS variables instead of hardcoding colors when possible
  • If you need to support themes and the pre-defined variables don't fit, define a variable with your custom colors at the beginning of the CSS file, this avoids selector duplication in the code.

Example :

.theme-light {
  --some-variable-name: <color-for-light-theme>;
}
.theme-dark {
  --some-variable-name: <color-for-dark-theme>;
}
.theme-firebug {
  --some-variable-name: <color-for-dark-theme>;
}
#myElement {
  background-color: var(--some-variable-name);
}

HDPI support

In order to support retina displays and Windows DPI settings, it's recommended to use SVG since it keeps the CSS clean. However, if only 1x and 2x PNG assets are available, you can use this @media query to target HDPI : @media (min-resolution: 1.1dppx)

Performance

  • Read Writing Efficient CSS
  • Use an iframe where possible so your rules are scoped to the smallest possible set of nodes
  • If your CSS is used in browser.xul, you need to take special care to performance:
    • Descendent selector should be avoided
    • If possible find ways to use only id selectors, class selectors and selector groups

Localization

Text Direction

  • For margins, padding and borders, use inline-start/inline-end rather than left/right
    • Example: Use margin-inline-start: 3px; not margin-left: 3px
  • For RTL-aware positioning (left/right), use offset-inline-start/end
  • When there is no special RTL-aware property (eg. float: left|right) available, use the pseudo :-moz-locale-dir(ltr|rtl) (for XUL files) or :dir(ltr|rtl) (for HTML files)
  • Remember that while a tab content's scrollbar still shows on the right in RTL, an overflow scrollbar will show on the left
  • Write "padding: 0 3px 4px;" instead of "padding: 0 3px 4px 3px;". This makes it more obvious that the padding is symmetrical (so RTL won't be an issue)

RTL support for html modules

By default, new HTML modules support only left-to-right (LTR) and do not reuse the current direction of the browser.

To enable right-to-left (RTL) support in a module, set the [dir] attribute on the document element of the module:

The appropriate value for the dir attribute will then be set when the toolbox will load this module.

Testing

  • The recommended workflow to test RTL on DevTools is to use the Force RTL extension. After changing the direction using Force RTL, you should restart the devtools to make sure all modules apply the new direction. A future version of Force RTL will be able to update dynamically all DevTools documents.
  • Going to about:config and setting intl.uidirection.en to rtl is not recommended, and will always require to re-open devtools to have any impact.

Toggles

Sometimes you have a style that you want to turn on and off. For example a tree twisty, a tab background, etc. The Mozilla way is to perform the toggle using an attribute rather than a class. So:

.tree-node {
  background-image: url(right-arrow.png);
}
.tree-node[open] {
  background-image: url(down-arrow.png);
}

Tips

  • Use :empty to match a node that doesn't have children
  • Usually, if margin or padding has 4 values, something is wrong. If the left and right values are asymmetrical, you're supposed to use -start and -end. If the values are symmetrical, so use only 3 values (see localization section)