Firefox/CSS Tips

From MozillaWiki
Jump to: navigation, search

This page contains information about CSS used in the Firefox front end.

Basics

First, you can find the existing Firefox CSS at https://dxr.mozilla.org/mozilla-central/source/browser/themes. Here are some basic tips that can result in faster reviews if you are changing CSS.

  • Split your CSS into theme and content files (see below)
  • 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 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 frontend should generally be similar across platforms since they mostly use a shared implementation, but there can still be differences worth checking out. Ideally you should test major changes on all of Windows, OS X and Ubuntu in both light and dark themes.


Formatting

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: -moz-linear-gradient(top, 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.

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 of performance:
    • Descendant selectors should be avoided
    • If possible find ways to only use id selectors, class selectors and selector groups

Content or Theme CSS

We have 2 competing priorities - A desire to avoid repetition (aka 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).

There are stored:

  • content CSS files are stored along with your JS/HTML/etc.
  • theme CSS files are stored in the themes/(windows|osx|linux) directories
  • theme CSS that should look the same on all supported platforms are stored in the themes/shared directory

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.

99% theme 70% theme 70% content 99% content
font-*, color, *-color, border-*, -moz-appearance [1] line-height, padding, margin cursor, width, max-width, top, bottom [2], etc overflow, direction, display, *-align, align-*, *-box-*, flex-*, order

If you're not sure, then go for content CSS unless you can imagine the value changing on another platform.

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 after the global values, so your imports will look like this:

<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/content/path/module.css" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/path/module.css" type="text/css"?>

[1] -moz-appearance is tricky. Generally, when specifying -moz-appearance: foo; you're giving hints as to how something should act, however -moz-appearance: none; is probably saying 'ignore browser preconceptions - I want a blank sheet', so that's more visual. However -moz-appearance values aren't implemented and don't behave consistently across platforms, so idealism aside -moz-appearance 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 margin-inline-start: 3px; not margin-left: 3px
    • Tip: whenever you specify an unbalanced margin, padding or border style (i.e. the value for left is different from the value for right), think of using -end/ -start
  • 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:

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[opened] {
  background-image: url(down-arrow.png);
}
.tree-node:not([opened]) {
  background-image: url(right-arrow.png);
}

The Mozilla Environment

Pre-defined classes:

  • Use plain in place of margin: 0

Theme values:

  • Use them where possible
    • Example: border-radius: @toolbarbuttonCornerRadius@, not border-radius: 3px
  • Where a theme value doesn't fit, make sure you have buy-in from UX

Lists of theme values:

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)