Chapter 5: Skinning the Toolbar

A "skin" is a collection of styling rules (specified with CSS) and images that get used to change the appearance of chrome (in our case, the toolbar we are building). Keep in mind that although skinning is entirely optional, it can greatly improve the quality of your extension. After all, a user’s first impression of your toolbar will be its appearance, not its functionality. However, if you are comfortable using only text labels for your toolbar buttons (or your extension doesn’t make use of a chrome overlay at all), you can skip this step.

Updating the File Structure

The first step in creating a skin for our toolbar is to create the folder that will hold all of our skin files. Create a folder named skin inside of the chrome folder. The resulting file structure should look like the following:

+- TutToolbar/
   +- install.rdf
   +- chrome.manifest
   +- chrome/
      +- content/
         +- tuttoolbar.xul
      +- skin/

Now that we have a place to store our skin’s files, we need to register this location with our chrome.

Updating the Chrome Manifest

Remember the chrome manifest file we created in chapter 2? We need to add a line of code to that file which will register our skin. Let’s take a look at the line of code that is necessary (it has been highlighted below):

content tuttoolbar chrome/content/
overlay chrome://browser/content/browser.xul chrome://tuttoolbar/content/tuttoolbar.xul
skin tuttoolbar classic/1.0 chrome/skin/

This additional line of code is quite simple, and has only four parts. The first part, which is simply the word "skin", states that what follows is the skin’s registration information. Next up is the package name which, in this tutorial, is tuttoolbar. The third part indicates the name of an installed skin which we will be extending. The value shown (classic/1.0) is the value you should always use for Firefox extensions. Finally comes the most important part: the relative path name to the folder that contains our skin’s files. This path is always relative to the chrome directory. It is very important that you note the trailing slash (/) in the given path above. That slash is required, so make sure you include it.

Creating the Image Files

To keep things simple for this tutorial, we will be using one image for each toolbar button. Note that this is neither the most efficient nor elegant way of skinning a toolbar, but it makes things incredibly easier to understand. For those that are curious, image sheets are the best way to skin an extension, but they are outside the scope of this tutorial.

We need a total of five images for our toolbar as it is currently designed: one for our "main menu" (the menu button), one for the combined search button, one for our web search button, one for the resizing gripper, and one for the image search menu item in the combined search menu. The following list shows each of the five images I have chosen to use for our extension. Note that these images are in a transparent PNG format, so if you are using Internet Explorer 6 or earlier to view this tutorial, the images will not be displayed properly.

Let’s save these images to our skin folder that we created moments ago. Our resulting file structure will look like this:

+- TutToolbar/
   +- install.rdf
   +- chrome.manifest
   +- chrome/
      +- content/
         +- tuttoolbar.xul
      +- skin/
         +- combined.png
         +- gripper.png
         +- images.png
         +- main.png
         +- web.png

Applying the Images With CSS

Now that we have some images to use, and our skin directory has been registered, we can begin applying the images to our toolbar buttons. We will do so through the use of a Cascading Style Sheet (CSS). As I mentioned at the beginning of this tutorial, W3Schools has an excellent CSS tutorial if you are unfamiliar with how style sheets work.

Let’s create our CSS file, naming it tuttoolbar.css and placing it inside of the skin folder, along with our images. Here is the resulting file structure:

+- TutToolbar/
   +- install.rdf
   +- chrome.manifest
   +- chrome/
      +- content/
         +- tuttoolbar.xul
      +- skin/
         +- combined.png
         +- gripper.png
         +- images.png
         +- main.png
         +- web.png
         +- tuttoolbar.css

Let’s take a look at the contents of our style sheet before we go into any detail:

#TutTB-MainMenu {
    list-style-image: url("chrome://tuttoolbar/skin/main.png");
}

#TutTB-Combined-Button {
    list-style-image: url("chrome://tuttoolbar/skin/combined.png");
}

#TutTB-Combined-Button > .toolbarbutton-menubutton-button {
    -moz-box-orient: horizontal;
}

#TutTB-Web-Button,
#TutTB-Combined-Web {
    list-style-image: url("chrome://tuttoolbar/skin/web.png");
}

#TutTB-Combined-Image {
    list-style-image: url("chrome://tuttoolbar/skin/images.png");
}

#TutTB-ResizeBar {
    background-image: url("chrome://tuttoolbar/skin/gripper.png");
    min-height: 22px;
    min-width: 3px;
}

#TutTB-ResizeSplitter {
    background: transparent;
    border: none !important;
}

The first rule shown specifies the image to be used for the "main menu" button. Back in chapter 3, we gave that button an ID value of TutTB-MainMenu, and we use that ID here to set up the rule. The preceding hash mark (#) is called the ID selector, and is how one specifies rules in CSS for elements with a particular ID value. For toolbar buttons, we make use of the list-style-image CSS property to specify the image to be displayed. You will note that the path we use is a chrome path; that is, the path to the image within your extension’s file structure. The general format for these paths is as follows:

chrome://<packagename>/skin/<image_file_name>

For our example, the package name is tuttoolbar and the image we want to use for the main menu is named main.png. As you can see, we use similar rules for all of the toolbar buttons, as well as our menu items in our combined search button’s menu. There’s one caveat to handling menu item icons, however. If you recall, we made use of a special class value for the menu items in our combined search menu. That special class was menuitem-iconic, and it is a built-in class provided by Firefox. In a sense it "enables" icon support for each menu item that uses it.

You undoubtedly also noticed the special rule for the combined search button:

#TutTB-Combined-Button > .toolbarbutton-menubutton-button {
    -moz-box-orient: horizontal;
}

The special CSS property used here (-moz-box-orient) specifies how the label for our button should appear: aligned vertically or horizontally. By default, toolbar button labels are aligned vertically, meaning that the label shows up underneath the icon. We don’t want that in this case, so we use the horizontal value to force the label to show up after the icon.

There are two rules in our style sheet that deal with the resizing gripper. Remember that vbox element that we placed inside of our splitter element? We use the ID of that vbox to display a background image for our gripper. This time we use the background-image property. We also must provide a minimum height and width (using the min-height and min-width properties), so that our gripper shows up. By default, the vbox and hbox elements size to the smallest value possible for their content. Since our vbox is empty, it sizes to a default of 0, which prevents us from seeing the background image.

We also provide a rule for the splitter element itself. We tell the background to become transparent (so that we can see the vbox image), and we tell it to not use a border (by default, all splitter elements have a border). Now that our CSS file is complete, we need to tell our overlay how to use it.

Using the Style Sheet

Only one line of code needs to be added to our XUL overlay to enable the style sheet we just created. It must be placed underneath the XML directive at the top of the file, but before the actual overlay element. Below I show the first few lines of our XUL overlay file, highlighting the line we need to add:

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://tuttoolbar/skin/tuttoolbar.css"
                 type="text/css"?>

<overlay id="TutTB-Overlay"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

(... rest of XUL overlay file ...)

Like we saw with the images in the style sheet, a chrome path gets used to specify the location to the style sheet. The type attribute simply tells the parser that the file being referenced is a CSS file. And that’s all there is to it! Let’s take a look at the entire XUL overlay file as it appears with this additional line: [View XUL Overlay Revision 6].

And don’t forget to test it out! Open the Firefox instance that includes your dynamic extension installation (which we discussed in the previous chapter), and see what the extension looks like. Next up, we’ll be bringing the toolbar to life.