Adding Style Sheets
Style sheets may be used both for creating themes, as well as tailoring elements for a more precise user interfaces. XUL uses CSS (Cascading Style Sheets) for this.
Style Sheets
A style sheet is a file which contains style information for elements. It was originally designed for HTML elements but can be applied to XUL elements also, or to any XML for that matter. The style sheet contains information such as the fonts, colors, borders, and size of elements.
Mozilla applies a default style sheet to each XUL window. The user's default theme is applied using the style sheet reference we have seen in a number of examples:
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
This line indicates that we want to use the style provided by chrome://global/skin/. In Mozilla, this will be translated as the file global.css, which contains default style information for XUL elements. If you leave the line out, the elements will still work, however they will look fairly plain. The style sheet applies theme-specific fonts, colors and borders to make the elements look more suitable.
Creating themes is not described in detail in this tutorial, however, if you wish to create a theme, you would create a style sheet, or set of style sheets for all the XUL elements, and include any images necessary. CSS selectors would be used to match particular elements.
Mozilla browsers all provide a standard theme that uses the platform's native appearance to determine how to draw the widgets. A special CSS property, -moz-appearance, may be used to specify that a widget should take on the appearance necessary for the user's platform. In this case, other CSS properties that define colors, fonts and sizes may be ignored because the platform defines these characteristics. For other themes, the -moz-appearance property is not usually used and the theme must define all of the appearance characteristics in the style sheets.
It is recommended that you do not change the appearance of any widget unless you are creating a theme, or in particular circumstances where such a change is needed to convey a specific meaning. Some CSS properties do not affect the appearance of a widget, such as those that change the size or margins. In XUL, flexible boxes should be used instead of using specific sizes, or for listboxes or trees, the rows attribute may be used to specify the number of rows to appear. However, there are often cases where a hardcoded size is useful, for instance to indicate the default size of a window.
Built-in Style Classes
The margin and other spacing properties are often used to adjust the position of elements as needed. Often, however, other elements or attributes may be used instead of this. For example, if you need to place a small gap in-between several elements, use the separator element. The separator includes a number of built-in classes, listed in the element reference, that may be used to alter the separator's appearance. For instance, the following creates a separator with a grooved line:
<separator class="groove">
Some of the other elements have other built-in classes that may be used. For instance, a label using the class small-margin creates a label with a smaller margin around it than normal. A box using the outset class will be displayed with an outset border. The element reference lists all of the classes available. Some of these classes may be applied to any element.
One common class to use is the plain class, which causes an element to appear without any borders, margins or other style information. Typically, this is used to create textboxes that blend into the background, like a label. If the textbox is also readonly, then you can create text that appears like a label, however, the text may be still be selected, and a context menu still applies.
Example 10.1.1: Source View<textbox class="plain" readonly="true">
Adding a style sheet
Applications will often need a style sheet. In general, you will associate a single style sheet with each XUL file, in addition to the global style sheet. You can place a style sheet anywhere you wish. If your XUL file is stored remotely and accessed via an HTTP URL, you can store the style sheet remotely as well. If you are creating a XUL package to be installed as part of the chrome system, you have two choices. First, you could store the style sheet in the same directory as the XUL file. This method has the disadvantage that your application will not be themeable. A better method involves placing your files as part of a theme.
Let's assume that we are building the find files dialog for themeability, because the find files dialog can be referred to with the URL chrome://findfile/content/findfile.xul so the style sheet file will be stored in chrome://findfile/skin/findfile.css.
Changing the Styles
However, there will be times when the default look of elements will not give the look that is desired. For this, we will need to add a style sheet of our own. So far, we have been applying styles using the style attribute on elements. Although this works, it is not really the best thing to do. It is much better to create a separate style sheet. The reason is so that different looks, or skins, can be applied easily.
There may be certain cases where the style attribute is acceptable. An example would be when a script changes the style, or where a difference in layout might change the meaning of the element. However you should avoid this as much as possible.
For installed files, you'll have to create or modify a manifest file and install the skin.
Let's modify the find files dialog so that its style comes from a separate style file. First, the modifed lines of findfile.xul:
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> <?xml-stylesheet href="findfile.css" type="text/css"?> ... <spacer class="titlespace"/> <groupbox orient="horizontal"> <caption label="Search Criteria"/> <menulist id="searchtype"> <menupopup> <menuitem label="Name"/> <menuitem label="Size"/> <menuitem label="Date Modified"/> </menupopup> </menulist> <spacer class="springspace"/> <menulist id="searchmode"> <menupopup> <menuitem label="Is"/> <menuitem label="Is Not"/> </menupopup> </menulist> <spacer class="springspace"/> <menulist id="find-text" flex="1" editable="true" datasources="file:///mozilla/recents.rdf" ref="http://www.xulplanet.com/rdf/recent/all"/> ... <spacer class="titlespace"/> <hbox> <progressmeter id="progmeter" value="50%" style="display:none;"/>
The new xml-stylesheet line is used to import the style sheet. It will contain the styles instead of having them directly in the XUL file. You can include any number of style sheets in a similar way. Here the style sheet is placed in the same directory as findfile.xul.
Some of the styles in the code above have been removed. One that wasn't was the display property on the progressmeter. This will be changed by a script so it was left in, as it doesn't really make sense to have the progress bar visible initially. You could still put this in a separate style sheet if you really wanted to. A class was added to the spacers so that they can be referred to.
A style sheet also needs to be created. Create a file findfile.css in the same directory as the XUL file. (It would normally be put into a separate skin). In this file, we'll add the style declarations, as shown below:
#find-text { min-width: 15em; } #progmeter { margin: 4px; } .springspace { width: 10px; } .titlespace { height: 10px; }
Notice how these styles are equivalent to the styles we had before. However, it is much easier for someone to change the look of the find files dialog now because they could add or modify the style declarations by either modifying the file or by changing the skin. If the user changes the interface skin, the files in a directory other than default will be applied.
Importing Style Sheets
We've already seen how to import style sheets for use. An example is shown below:
<?xml-stylesheet href="chrome://bookmarks/skin/" type="text/css"?>
This might be the first lines of a bookmarks window. It imports the bookmarks style sheet, which is bookmarks.css. Mozilla's skin system is smart enough to figure out which style sheet to use, because the specific filename was not indicated here. We have done a similar thing with the global style sheet file (chrome://global/skin).
A style sheet may import styles from another style sheet using the import directive. Normally, you will only import one style sheet from each XUL file. The global style sheet can be imported from within the style sheet associated with the XUL file. This can be done with the code below, allowing you to remove the import from the XUL file:
Style import from XUL: <?xml-stylesheet href="chrome://global/skin/" type="text/css"?> Style import from CSS: @import url(chrome://global/skin/);
The second syntax is preferred because it reduces the number of dependencies within the XUL file itself.
Remove the global style sheet import from findfile.xul and add the import to findfile.css.
All elements can be styled using CSS. You can use selectors to select the element that you wish to have styled. (The selector is the part before the curly brace in a style rule). The following table summarizes some of the selectors available:
button | Matches all button tags |
#special-button | Matches the element with an id of special-button |
.bigbuttons | Matches all elements with a class of bigbuttons |
button.bigbuttons | Matches all button elements with a class of bigbuttons |
toolbar > button | Matches all buttons that are directly inside toolbar elements. |
toolbar > button.bigbuttons | Matches all button elements with a class of bigbuttons that are directly inside toolbar elements. |
button.bugbuttons:hover | Matches all button elements with a class of bigbuttons but only while the mouse is over them. |
button#special-button:active | Matches all button elements with an id of special-button but only while they are active (being clicked on). |
box[orient="horizontal"] | Matches all box elements that have an orient attribute that is set to horizontal. |
You can combine these rules in any way that you wish. It is always a good idea to be as precise as possible when specifying what gets styled. It is more efficient and it also reduces the likelihood that you'll style the wrong thing.
(Next) In the next section, we will look at how to apply styles to trees.
Examples: 10.1.1