Writing Skinnable XUL and CSS

The following document outlines rules that one must abide by when writing a skin. Mozilla can have any number of installed UI packages, from Navigator to Sidebar to Editor. Each package has its own skin, CSS files and images that determine the appearance of that package.

In our particular Mozilla skin, there is a special package called global. This package contains a special skin called the global skin. If you wish for your package to blend in with the other packages, then the skin for your package should inherit information from the global skin in order to reduce the amount of duplication across packages and in order to make the UI as a whole easier to skin.

Writing CSS files for a Package

  1. Learn CSS! This may seem obvious, but many of the nastiest problems we're seeing are being caused by people writing buggy or syntactically incorrect CSS. Read the spec! Study a book! Know it! Love it! Make it a part of you!
  2. Each skin has a master skin file. The skin for a package should always have a master skin file whose name corresponds to the name of the package. For example, the skin for the Navigator package should contain a file called <tt>navigator.css</tt> that determines the default look of all XUL windows posed from this package.
  3. If inheriting the global skin, a skin file must import the global skin explicitly. If your skin file wishes to inherit the global skin, then it should import the global skin explicitly. This is done using an <tt>@import</tt> directive placed at the top of the file.
    @import url(chrome://global/skin/)
    ... rest of skin file ...
    
  4. CSS files for a skin fall into two categories: base skin files and derived skin files. CSS files that import another skin file are called derived skin files. CSS files that don't import another skin file are called base skin files. There is one notable exception to this rule. Skin files that don't import any other skin files, but that are only intended to be used in the context of another component's skin are also considered derived skin files, since they are implicitly importing information from the other component's skin. These sorts of files are typically used with reusable overlayable widgets (e.g., the sidebar).
  5. Your CSS file should never import another skin file if your file is loaded by a XUL overlay. CSS files that are used by XUL overlays should never import the global skin (or any other skin for that matter). They are already derived skins and therefore should not inherit from global. They should instead rely on the context in which they will appear for color, font, and border information. For example, the sidebar should not import the global skin, since it could appear in Messenger and in Navigator (which could have two completely different color schemes). If it imported the global skin, then when it was overlayed into Navigator, it would potentially clash (if the user's current chosen Navigator skin were NOT inheriting from global).
  6. Derived skin files should not contain any font, color, or border information. This information should only be found in base skin files. The skin file should instead inherit from a base skin file to obtain the appropriate font, color, and border information. By obeying this restriction, your package will be almost entirely skinnable by changing only the global defaults. This rule also applies when designing a CSS file for a UI component that will be overlayed into other components. Below are examples for each case.
    Example 1: The Navigator package has a personal toolbar with popup menu buttons. The colors for the toolbar and buttons should be drawn from global by placing class attributes on the appropriate elements in the XUL. There should be no rules in navigator.css that attempt to define colors, fonts, etc. for either the personal toolbar headers or for the menu buttons' borders.
    Example 2: The Messenger package has a CSS file that describes the appearance of the Messenger button that appears on the taskbar used by all windows. The Messenger CSS file should not attempt to describe the borders or the colors for this button. It should only describe the icon. Because the button is used in the Navigator window (through overlays), the fonts/colors used should not be described by Messenger. This allows the button to blend in as much as possible regardless of where it is used.

    The importance of this rule cannot be overstated. Derived skin files should not contain any rules for colors, fonts, or borders. Exceptions to this rule must be approved in order to be allowed into the product. Note that in our current designed Mozilla skin (aside from global) every single CSS file is a derived skin file, so this applies to ALL OF YOU!!!

  7. Derived skin files should not attempt to change the default look for a widget. For example, there should never be any CSS rules of the form <tt>tagName {...};</tt> in a derived skin file. In doing so, you have redefined the default look for the widget, which will make the UI in your window different from others that properly inherit from the same base skin file you do.
  8. The descendant selector is forbidden. Never use the descendant selector without first getting usage of the rule approved. The matching for these rules (unless you're very careful) will be inefficient, and when only using generic tag names, can be positively grotesque. I'll show you the evil rule I put into the global skin a few months back that was making trees slow.
    treehead treerow treecell { BAD! EVIL! YUCK!
        ...
    }
    

    This evil rule caused the style system, for every treecell that wasn't in a treehead (which is practically every treecell in a typical tree), to crawl up the whole parent chain to the root of the document in order to determine that the style rule wasn't a match.

    I'm usually seeing this rule misused by people who really wanted to use the child selector instead. That was my mistake with the above rule. I should have used <tt>treehead > treerow > treecell</tt>. After all, that's what I meant anyway.

  9. Never use an attribute selector rule for the class attribute. This is inefficient and you should just use the class notation (the dot notation) instead.

Writing Skinnable XUL

  1. A XUL file that describes a window always imports the master skin file for its package. For example, all XUL files that describe windows in the Navigator package should contain a line explicitly importing <tt>navigator.css</tt>. XUL overlays, however, should not, since they will be used in the context of other skins.
  2. A XUL file NEVER imports skin files from outside its package. It is a flagrant and hideous violation (punishable by a public flogging in front of the Netscape fountain) to load a skin file from XUL that is not found in your package. For example, a Navigator XUL file should never load the global skin or a Sidebar skin.
  3. XUL files never explicitly load files from other packages unless the presence of the other packages can be guaranteed. For example, a Navigator XUL file can only load a Sidebar overlay explicitly if the Sidebar UI is always going to be installed with navigator. If it is possible that the sidebar is a separate component that could be installed or uninstalled, then the overlaying should not occur in the XUL file. It should instead take place through the chrome registry. Examples of overlays that should take place using the chrome registry include the security padlock icon and any Messenger UI in the Navigator window.
  4. style="..." is prohibited in XUL files without approval Any usages of inline style are extremely dangerous, since they are overriding the included skin, and must be approved before their usage will be allowed.
  5. Image chrome URLs should never occur in XUL. Any chrome URL that references an image in the skin is strictly forbidden in the XUL. If you find yourself needing to display an image from the skin, then use <titledbutton> and style it rather than using <html:img>. The problem here is that you'll end up placing a restriction on the skin, which will force the skin designer to supply an image with the exact name you've specified. This is not healthy. Note that some particularly evil people put images chrome URLs in DTDs. This is even worse, and it also is strictly forbidden.

Original Document Information

  • Author(s): David Hyatt
  • Last Updated Date: May 24, 2000
  • Copyright Information: Copyright (C) 1999-2000 David Hyatt

Document Tags and Contributors

Tags:
Contributors to this page: Andreas Wuest, Rbutler, Dria, Mgjbot
Last updated by: Mgjbot,