This page discusses various topics relating to theme development in general. This page answers many questions that arise during development of a theme for the first time.
Setting Up for Theme Development
If you're getting ready to work on a theme, you'll want to do a few things to make sure your computer is ready. First of all:
- Make sure you have all the tools you need.
- Pick a directory on your hard drive to use as your work area (c:\themes, for example, or any directory you like)
- In your work directory, create three new subdirectories called "default_chrome", "default_theme", and "new_theme"
- Unpack copies of Firefox's seven "chrome" jar files, to use as reference, into the directory "default_chrome" in your work directory.
- Unpack a copy of classic.jar, the Firefox default theme, to use as reference, into the directory "default_theme" in your work directory. (Yes, this would be a duplicate of one of the files from the previous step.)
- Unpack yet another copy of classic.jar, the Firefox default theme, to use as the basis for your new theme, into the directory "new_theme" in your work directory. The files extracted in this step will be the ones that you modify to make your theme.
- Modify the directory structure within "new_theme" to be suitable for an add-on theme, as described in this tutorial.
- Add install.rdf and contents.rdf to the "new_theme" directory by downloading the templates from here and here. (Warning: if you try to display these files in your browser, they won't look right. Instead, right-click on each link and select "Save link as ...", "Save target as ...", or "Save as ..." to save the file to your hard drive.)
- Get a new GUID from a provider such as this for use in your install.rdf. (You can read more about GUIDs here.)
- Edit the contents of the downloaded install.rdf as needed for your theme, according to the instructions provided here.
- Edit the contents of the downloaded contents.rdf as needed for your theme, according to the instructions provided here.
- Tell Firefox to use the version of the theme located in your work directory, discussed in the following section.
Let's say you're using the directory c:\themes as your work directory. If you performed the steps above, you would end up with a directory structure that looked like this:
C:\
themes\
default_chrome\
browser\
... subdirectories ...
classic\
... subdirectories ...
comm\
... subdirectories ...
en-US\
... subdirectories ...
pippki\
... subdirectories ...
reporter\
... subdirectories ...
toolkit\
... subdirectories ...
default_theme\
classic\
skin\
classic\
browser\
... subdirectories ...
communicator\
global\
... subdirectories ...
help\
mozapps\
... subdirectories ...
new_theme\
browser\
... subdirectories ...
communicator\
global\
... subdirectories ...
help\
mozapps\
... subdirectories ...
In the contents shown for default_chrome and default_theme, it shows that, for each unzipped jar, the zip program created a directory named after the jar file it was unzipping. Your zip program may work differently. The exact directory names don't matter, since you're only using default_chrome and default_theme as a reference. All that matters is that you know where to find it.
Why make three copies of classic.jar? The first copy, in the "default_chrome" directory, gives you an easy way to search through all seven Firefox jar files at once, allowing you to look at the DOM elements in the Firefox UI whenever you need to. The second copy, in directory "default_theme", gives you an easy way to search through just the default theme, and not through all seven jar files. You save this as a reference so that, as you make changes, you can compare it with how it used to be. The third copy, of course, is the one that you will change.
If you were to decide to base your theme on some theme other than the Firefox default theme, then that is what you would unpack into the "new_theme" directory. You might in that case want to save copies of both the Firefox default theme, unpacked, and an unpacked version of the original of whatever theme you're using as your model.
Making Firefox Use Your Work Directory
As you develop your theme, you'll almost certainly want to set up Firefox to read your theme in unpacked form directly from the hard drive. You already know that you can install a theme by clicking on a web page containing a specially programmed hyperlink (such as the "Install Now" link on this page) if you're using Firefox, or by dragging and dropping the theme's jar file onto the open Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0). You can also set up Firefox to read a theme in unpacked form directly from your work directory on your hard drive. This would save you the time and tedium of zipping up your theme and reinstalling it every time you're ready to test your changes; instead, all you'll need to do is restart Firefox, and it will automatically read the latest version of your theme from the work directory on your hard drive.
Here's how you do it.
- Start by making a zipped-up, installable version of your theme. Refer to instructions in the section "Part Two: Theme Packaging and Installation".
- Install your theme in the usual way.
- Use a text editor to open the chrome.manifest file that results from installing your theme. This file has the exact name chrome.manifest, and is located in the directory having a name that's the same as the GUID of your theme, located in the extensions directory, which is located in the profile directory for whatever profile was selected at the time when you installed theme.
- In your text editor, modify each line of the open chrome.manifest to tell Firefox to look on your hard drive instead of in the jar containing your installed theme. (An example is given immediatety following this checklist.) This is a simple matter of replacing the part of the line for each package that starts from the word "jar:" and replacing it with the equivalent path to a location on your hard drive, beginning with the word "file:".
- Save your changes to chrome.manifest.
- Restart Firefox.
Here's a quick example. The first listing shows a chrome.manifest before you edit it. This is the one that's created when you install the theme. The second listing shows how that same manifest file should look after you edit it to point to the unpacked files in the work area of your hard drive.
| 001: | skin browser Test_Theme jar:chrome/Test_Theme_7.7.3.jar!/browser/ | |
| 002: | skin communicator Test_Theme jar:chrome/Test_Theme_7.7.3.jar!/communicator/ | |
| 003: | skin help Test_Theme jar:chrome/Test_Theme_7.7.3.jar!/help/ | |
| 004: | skin global Test_Theme jar:chrome/Test_Theme_7.7.3.jar!/global/ | |
| 005: | skin mozapps Test_Theme jar:chrome/Test_Theme_7.7.3.jar!/mozapps/ |
Here is the equivalent chrome.manifest after editing.
| 001: | skin browser Test_Theme file:///D:/MCD/dvl/moztheme/Test_Theme/unpacked/browser/ | |
| 002: | skin communicator Test_Theme file:///D:/MCD/dvl/moztheme/Test_Theme/unpacked/communicator/ | |
| 003: | skin help Test_Theme file:///D:/MCD/dvl/moztheme/Test_Theme/unpacked/help/ | |
| 004: | skin global Test_Theme file:///D:/MCD/dvl/moztheme/Test_Theme/unpacked/global/ | |
| 005: | skin mozapps Test_Theme file:///D:/MCD/dvl/moztheme/Test_Theme/unpacked/mozapps/ |
In the first listing, the highlighting shows the parts that get replaced by the corresponding highlighted parts in the second listing. Just be sure to use whatever path points to the location of your theme in the work directory on your hard drive. (The internal_name for your theme should already be in this file as a result of installing the theme.)
On a related note, it appears that if you install the Extension Developer's Extension, you can use it to reload the Firefox user interface without having to completely restart Firefox. It's not instantaneous, but it is faster than restarting every time you want to test your changes.
Unused Files in the Firefox 1.5 Default Theme
There is some uncertainty about this, but the consensus is that the entire contents of these directories in the default theme for Firefox 1.5 is not used at all.
- chrome://mozapps/skin/pref/
- chrome://communicator/skin/
Organization of Files and Directories in classic.jar
Previously, we discussed how, inside the jar file for the default theme, files are grouped into five major directories. We now go into more detail about the contents of the default theme. Below, we discuss the directory structure of add-on themes (such as yours), which is different from the structure of the default theme.
Here again is the top-level directory structure of the default theme, from the root of the jar's internal directory structure down to the top five major directories.
/ (the jar's root directory)
skin/
classic/
browser/
communicator/
global/
help/
mozapps/
Here's what you'll see if you open classic.jar in a zip program (ALZip in this case):

Figure 1: The Firefox Default Theme (classic.jar), Opened in a Zip Program
The five major directories, as shown in the list above, are:
| Directory | Description | |
| browser/ | Contains files specific to the main browser window. | |
| communicator/ | Not used by Firefox. Left over from the days of Netscape Communicator. | |
| global/ | Contains files which are shared throughout all parts of the application. These tend to be files associated with smaller general-purpose user interface widgets (checkbox, listbox, button, etc.) rather than with any particular window. | |
| help/ | Contains files specific to the help window. | |
| mozapps/ | Contains files specific to the various "Manager" type windows, including the Downloads Manager, Updates Manager, Plugins Manager, Themes Manager, Extensions Manager, Profile Manager and so on (but not including the Bookmarks Manager). | |
There are several other directories worth noting.
| Directory | Description | |
| /skin/classic/browser/bookmarks | This directory contains files and images specific to the Bookmarks Manager. | |
| /skin/classic/browser/preferences | This directory contains files and images specific to the Firefox Options window. In older versions of the Netscape browser, this window was called "Preferences", hence the name of the directory. Note that there's also a file global/preferences.css which also applies to the Options window. Note also that there's a directory mozapps/pref, which we're all pretty sure isn't used any more. | |
| /skin/classic/mozapps/downloads | This directory contains files and images specific to the Downloads Manager. | |
| /skin/classic/mozapps/extensions | This directory contains files and images specific to the Themes Manager and the Extensions Manager. They are grouped together because they are both based on the same underlying code, and are, for the most part, two instances of the same window that differ in name only. | |
| /skin/classic/mozapps/plugins | This directory contains files and images specific to the Plugin Finder. | |
| /skin/classic/mozapps/profile | This directory contains files and images specific to the Firefox Profile Manager. (See "Themes and the Profile Manager".) | |
| /skin/classic/mozapps/shared | This directory contains a few files and images shared among the various manager windows that present information as a list of complex items, also known as a "rich list", in Firefox lingo, as opposed a simple list of text items. The Downloads Manager, the Themes Manager, and the Extensions Manager all present items as a rich list. See this article on XULPlanet for more about rich list box. | |
| /skin/classic/mozapps/update | This directory contains files and images specific to the Software Update Wizard and the Extensions Autoupdate Wizard. | |
| /skin/classic/mozapps/xpinstall | This directory contains files and images specific to the Software Installation window. | |
The global directory contains files that define the appearance of widgets as general classes, regardless of where they actually appear in the Firefox user interface. The kinds of things defined there are all widgets that make up the UI. In general, this is organized with one CSS file per type of widget, with the CSS file residing in the global directory itself, and with any supporting images for each widget in a subdirectory under global having the name of the widget. For example, you'll see the file global/tree.css and the directory global/tree, containing images used in rendering trees (such as the list of bookmarks in the Bookmarks Manager) in the UI. Similarly, there's a file global/checkbox.css and a directory global/checkbox. As usual, there are lots of exceptions, and you'll just have to browse through and look for yourself.
Worth noting are the two files in the root directory of the jar, icon.png and preview.png. The first is the icon which is shown in the Themes Manager's list of installed themes to represent the Firefox default theme, and the second is shown as the theme's preview image when it is selected in the Themes Manager. Unlike the other contents of the jar, these two files are not accessible via chrome URL.
Keep in mind that the directory structure for the default theme is not the same as for add-on themes. See topic "Differences Between Directory Structures for Default and Add-on Themes".
General Organization of CSS Files
In general, the CSS files in the jar are organized along these lines:
- one window-specific CSS file per window, for the windows that Firefox only has one of
- for each general class of window, one general CSS file all windows of that class
- one CSS file for each kind of user interface widget (widget being something like a button, a menu, a listbox, or any of the different kinds of widgets that make up the user interface)
- and then some other files as well.
Here's some examples. The main browser window includes both browser/browser.css and global/browser.css, with browser/browser.css containing rules specific to the one main browser window, and global/browser.css containing rules which apply to browser windows in general (which includes popped-up windows which don't necessarily have a toolbar set across the top).
As another example, the Options window is implemented as an instance of a DOM element of type prefwindow. The Options window can itself open lots of child windows also made up of, in general, elements of type prefwindow. Further, several extensions (see topic "What is an Extension") use prefwindows to have Options windows of their own, allowing users to change settings for those extensions. Underlying this are two CSS files specific to prefwindows: browser/preferences/preferences.css, and global/preferences.css. The first one contains rules specific to the one main Options window for Firefox, while the second contains rules that apply to all prefwindows everywhere (assuming that they are constructed along the same lines as the Firefox Options window, which is not true for some extensions).
The file global/global.css deserves special mention. This file defines rules that are global in nature for the Firefox UI and all of its related windows. As with all the files that are contained in the global directory, the rules established by global/global.css are general in nature, defining the look and behavior of generic user interface widgets, regardless of where in the Firefox UI they are actually used. global/global.css has the special property that the code for almost every window and dialog box uses it. It's not that there's anything that guarantees this; it's just that the code for almost every window is written this way.
These are general rules only, and there are lots of exceptions. That's because this is code with a history, with different parts owned by different module owners, having been resurrected from the ashes of the dead Netscape Corporation, evolving over time to accommodate an evolving Internet. In the end, you may have to examine each window, one at a time, to see which CSS files it includes and in what order.
It's also true that many extensions use global/global.css. For more about this, see topic "Themes and Extensions".
Directory Structure Of Add-On Themes
This reference provides the recommended complete directory structure of add-on themes. The structure is the same as for the default theme, except that the five major directories have been promoted from subdirectories of /skin/classic/, as they are in the default theme, to positions at the top of the directory structure for an add-on theme. Other than that move, the rest of the directories remain in the same relation to one another as they were in the default theme.
Most of the directory structure is mandatory, because parts of the rest of Firefox look for files in those specific directories. It's beyond the scope of this web site to identify which are mandatory and which are not. Therefore, the recommendation for theme developers is that they simply start with the same directory structure as in default theme, but move the five major directories to the top of the structure, rather than leaving them as subdirectories under /skin/classic/, as they are in the default theme. This results in the structure provided as a reference above. After that, you can add directories if you want, but don't remove any.
Here are some images comparing the top-level directory structures of the default theme with two different add-on themes. Note that each of the two add-on themes, Noia and Pimpzilla, have added several directories to the basic structure which they duplicated from the default theme. The addition of directories is up to each theme developer.

Screenshot showing the directory structure of classic.jar, containing the default theme for Firefox.

Screenshot showing the directory structure of the jar file containing the add-on theme "Noia Extreme".

Screenshot showing the directory structure of the jar file containing the add-on theme "Pimpzilla".
Where Should the CSS Rule Go
As you develop your theme, you'll be modifying existing CSS rules and adding new ones. You'll naturally wonder: does it matter where the CSS rule goes? If so, where should the rule go? It turns out that it does matter, for at least a couple reasons:
- Different windows in Firefox use different CSS files. Put another way, the XUL source code for different windows imports different CSS files. This is true as well for extensions. You have to make sure your rule is in the CSS included by a window's source code if you want your rule to apply to that window.
- The order of rules in a CSS file determines which rule takes precedence, in the case of competition between two rules of equal specificity. Remember that for rules of equal specificity, the rule that comes last in the CSS file is the rule that takes precedence.
- The order of rules in imported CSS files determines which rule takes precedence, in the case of competition between two rules of equal specificity. Rules read from imported files are ordered as if they were found in the importing file at the line containing the import statement. You can think of it as if the contents of the imported file were simply placed in the importing file at the line containing the import statement.
- The contents of the CSS files are organized to make it as easy as possible to maintain, and you want to preserve that organization to keep it easy to maintain.
Keeping these reasons in mind, here are some guidelines that you can use to decide where to put your CSS rules.
- If you're modifying an existing rule that was present in the default theme, then leave it where it is.
- If the rule applies to a fundamental DOM element type (along the lines of menus, buttons, menuitems, listboxes, etc.), and it applies to all elements of that type, and not just elements having a certain specific ID, then it should go in a CSS file under the global directory having a name that is the same as the DOM element (e.g. global/button.css or global/listbox.css).
- If the rule is specific to a certain window, then it should go in a CSS file included by the window to which it applies (see How To Find Out Which CSS Files Apply To a Window)
- If the rule is part of a set of rules that apply to related parts of the user interface, then the rule should be grouped with the other rules in the set.
- If you're not sure where the rule should go, then, as a last resort, if the rule is not window-specific, if there's no window-specific CSS file, or if the rule needs to apply to extensions as well as the standard Firefox, then it's nearly a sure thing to place the rule in global/global.css.
Sometimes you find cases where despite your best efforts and against all logic, your rule is apparently ignored in whatever CSS file you've chosen for it. You've already made sure that the CSS file is included by your target window, and that your rule wins the specificity competition. What can you do at that point? Try putting it in different files (move it from global.css to button.css, or vice versa). Try putting it it global/browser.css or browser/browser.css. Try putting !important on it (but see this caution about using !important). Try temporarily adding it to userChrome.css. Eventually you will find a way, even if it doesn't make sense.
Remember that if you create a new CSS file that wasn't part of the default theme, then none of the windows in Firefox will be written to use it, and you'll have to import it into a CSS file that is used by Firefox (e.g. global.css or browser.css).
On a related note: it's probably an error in your theme if you have two rules of equal specificity competing to set different values for the exact same element. If this is the case, then your code expresses a theme design which can never occur, and probably doesn't reflect what you really want to happen.
How To Find Out Which CSS Files Apply To a Window
Reading the XUL source for a Firefox window is a good start but is not itself enough because CSS files are applied with several methods, many of which you wouldn't see by examining any single XUL file.
- XUL source can contain an explicit xml-stylesheet reference
- XUL source can contain an explicit xml-overlay command, with the overlay containing an explicit xml-stylesheet reference
- CSS files can import other CSS files
- manifest files used in the default Firefox user interface can contain overlay instructions, adding XUL from a source file which can contain an explicit xml-stylesheet reference
- manifest files used in the default Firefox user interface can contain style instructions, applying a CSS file to the XUL for a window as if the XUL source file for the window had used an explicit xml-stylesheet reference
- XBL bindings can specify stylesheets (see for example the <stylesheet> directive in the source for tree.xml, which defines common bindings used in Firefox 2.0)
Extensions present another possible complication. Extensions can add CSS through their own "style" and "overlay" manifest instructions in their manifest files. They can also tell Firefox to use an XUL file provided by the extension, rather than the one provided by Firefox, with an "override" manifest instruction.
A better approach than scouring the source code is probably to use DOM Inspector to examine each window, individually, whenever you need to know which CSS files apply to the window. If you inspect the Javascript Object which represents the document containing the window, you'll see a property "styleSheets"; expanding it will list each and every stylesheet which applies. (How does it represent stylesheet imported by other stylesheets? That's an open question, but it seems at this time that they do not show up in DOM Inspector's list.) The following image shows the document for the Bookmarks Manager window, with the Javascript Object view selected and the styleSheets property expanded. You can see that four stylesheets apply to this window. Only the first of four has been expanded, showing that the stylesheet is global.css. You would need to expand each of the other three items to see which stylesheet each item represents.

Image showing the use of DOM Inspector to see which stylesheets apply to a Firefox window.
Ignoring the issue of changes made by extensions, it would be possible to determine the set of CSS files which apply to each Firefox window for a default Firefox installation. For any given Firefox version, the set of CSS files used by each window is fixed. It is determined by Firefox itself, as it was released by the Mozilla Corporation. Computation is left as an exercise for the reader. This would make a valuable reference; send email if you get this completed. In the end, it would probably be so time-consuming and require an understanding of so much of the internals of Firefox and related technologies that the fastest and safest bet is to use DOM Inspector to see which CSS files are actually included by a window, whenever you need to know this.
Required Files in Themes
Most of the directories and files in the default theme are mandatory and need to be present in add-on themes, or Firefox won't work right.
Stated generally, a file in an add-on theme is mandatory if somewhere in the source code for the Firefox user interface (other than in your theme) a chrome URL exists that refers to that file. For example, if the Firefox user interface is looking for (which it is) a file chrome://browser/skin/preferences/preferences.css (to define part of the layout of the Options window), then the jar needs to contain a file preferences.css in a preferences directory. The same goes for all the other CSS files in the default theme.
There is more leeway with the image and XML files, because references to these items occur within the CSS files of the theme itself. The theme developer can use whatever images and XML files he or she wants, as long as the CSS files in the theme are rewritten to refer to the new items. Similarly, theme developers are free to add any files or directories that they want, beyond the mandatory files.
It's important to note that, while the presence of certain files is mandatory, the contents of those files are up to the theme developer. This is, of course, how theme developers define the styles that are unique to their themes: by changing the contents of CSS and image files.
In practice, all of the five main directories, all of their subdirectories, and all of the CSS files that are present in the default theme need to be present in an add-on theme as well. References to those items are hard-coded in the Firefox source code and are beyond the control of the theme developer; Firefox will be looking for these files in whichever theme is active. Also, since Firefox is looking for CSS files in certain directories, it follows that those directories need to be present in the jar as well.
Firefox 2.0 adds the requirement that certain images exist in your theme for use on the help page "Using Mozilla Firefox". This help page is displayed by clicking the "Help" menu, then selecting "Help Contents", then selecting the topic "Using Mozilla Firefox" from the topic list in the Help Window. The specific chrome URLs that your theme must provide are:
- chrome://global/skin/arrow/arrow-rit-sharp.gif (Jar Item Details)
- chrome://global/skin/arrow/arrow-rit-sharp-end.gif (Jar Item Details)
- chrome://global/skin/arrow/arrow-lft-sharp.gif (Jar Item Details)
- chrome://global/skin/arrow/arrow-lft-sharp-end.gif (Jar Item Details)
- chrome://global/skin/icons/Portrait.png (Jar Item Details)
- chrome://global/skin/icons/Landscape.png (Jar Item Details)
It's worth reemphasizing that most of the files in the default theme are mandatory for inclusion in add-on themes. Firefox depends on these files to define its user interface, and it won't work without them. It wouldn't crash, but it would be missing major chunks of its user interface. Leave out the CSS file that defines the main toolbar buttons, and there simply wouldn't be any toolbar buttons. Similarly, if, during development, you make an error such that the theme fails to load entirely, you'll see a Firefox completely devoid of user interface. It's not pretty.
See related topic "Unused Files in the Firefox 1.5 Default Theme".
Looking Under the Hood: Examining the Underlying Structure of the DOM Elements to Which Your Theme Applies
We've described the Firefox user interface as the structure or scaffolding over which your theme is draped. This underlying structure of the user interface is represented as a set of DOM elements in a DOM tree, which are defined by the source code in XUL files.
To write CSS rules for your theme, you will at times need to know which specific DOM nodes make up the part of the user interface that you're interested in. At first, as you begin to build out your theme, you may be able to get by simply by modifying the rules in the default theme. However, you will quickly reach the point where you need to know the details of this underlying structure as you expand beyond the default theme. Here's a few cases in which you'll need to know the underlying DOM structure.
- You may want to style an element that isn't styled in the default theme, meaning that you won't have an example to work from. Instead, you'll have to determine the element types, element IDs, and class IDs of the DOM nodes that represent what you want to style, then write a CSS selector that matches those specific nodes.
- You may be writing your theme to apply to an extension, which means that, again, the default theme may not have rules for you to modify. Instead, you'll need to determine the DOM elements that make up the part of the extension's user interface that you want to style.
- You may be writing your theme to work with multiple browsers or multiple browser versions, which means you'll have to write selectors that correctly work for all of the cases you'll encounter in the multiple browsers.
For example, suppose you want to change the background color or image of the list of themes in the Themes Manager. Looking at the XUL DOM elements will tell you that the list of themes in the Themes Manager is in a DOM element of type "richlistbox", having the element ID "#extensionsView", and if you want to change the background color or image in this list then your CSS rule needs to select for "#extensionsView".
You have two basic tools for looking at DOM structure.
- DOM Inspector.
- XUL source code.
DOM Inspector is a Firefox extension that lets you view the DOM tree for windows that are part of Firefox, including the main browser window. DOM Inspector is an essential tool for theme developers. More information about using DOM Inspector is available below.
The other source of information about the DOM elements that make up the Firefox user interface is in the source code itself. This source code is in XUL files contained in the seven default jar files. You'll want to unpack these jar files (instructions are available here) so that the XUL source is available for you to read. Keep in mind that much of the Firefox UI is built by using XBL bindings to add DOM elements to the DOM elements that are explicitly defined in the XUL source, meaning that the DOM elements that your theme applies to come from a combination of
- the XUL source
- the CSS files that apply XBL bindings to DOM elements
- and the XBL files within which the bound (the added) elements are defined
DOM Inspector
As mentioned above, DOM Inspector is a Firefox extension that lets you view the DOM tree for windows that are part of Firefox, including the main browser window and all of the supporting windows. DOM Inspector also works with Thunderbird and many of the other members of the Mozilla software family.
DOM Inspector can be installed when you install Firefox from scratch (by checking "yes" when asked if you want to install developer tools) or when you rerun the Firefox installer. At the time of this writing, there's no way to add DOM Inspector as an extension to Firefox through the normal extension installation method; all you can do is rerun the installer for Firefox if you didn't install DOM Inspector when you first installed Firefox. For Thunderbird, DOM Inspector can be added as an extension to an existing Thunderbird installation.
DOM Inspector is an essential tool for theme developers. More information about using DOM Inspector is available here. I'm not yet aware of a good tutorial for using DOM Inspector. At this time, you'll have to learn it the same way that theme developers before you have learned it: by using it.
Support for Multiple Applications in a Single Theme
install.rdf allows you to say which applications your theme will work with. You could, for example, choose to create a theme that works only with Firefox, only with Thunderbird, with Firefox plus Thunderbird plus Seamonkey, or with any combination of applications from the Mozilla software family. install.rdf is completely flexible in this way; choosing applications is entirely up to you, and you can specify the range of supported versions separately for each application. See topic "install.rdf in Detail" for more.
Forwards and Backwards Compatibility
For simplicity's sake, most theme developers prefer to package a theme and deliver it as a single jar file that works for all applications and all application versions. Some developers prefer to deliver separate jar files for each application. The approach you choose is up to you; the only restriction is that if you plan to submit your theme to AMO, then you will need to package your theme as a single jar file that works with all supported versions, because this is the only approach that AMO supports.
At the time of this writing, Firefox 2.0 is weeks away from release as a finished application. Firefox 3.0 is still in alpha versions. To date, it is entirely possible, with very few exceptions, to write a single integrated CSS ruleset which works for Firefox 1.5, Firefox 2.0, and Firefox 3.0, packaged as a single jar file which works with all of these versions. The sole exception is a minor one: the Options window requires a different height for 1.5 than for 2.0, because there's more content in the General tab in one than in the other, and there's no way to write a version-specific CSS selector for this. See this document for a discussion of browser changes in Firefox 2.0, this thread for a discussion of theme changes between 1.5 and 2.0, and this thread for a discussion of theme changes between 1.5 and 3.0.
Many themes continue to work with Firefox versions older than 1.5. This page provides download links for all previous and current versions of Firefox official releases. These would come in handy if you choose to develop your theme to work with previous versions.
Whether it will remain possible for a single jar file to provide a theme for Firefox 1.5, 2.0 and 3.0, as Firefox 2.0 and 3.0 continue to evolve, remains to be seen. This proposed enhancement suggests a way for this to work in the future; if this is something you care about as a theme developer, then consider signing up for a Bugzilla account (it's free, and takes just two or three minutes) and voting for the enhancement.
A related topic is the way that AMO enforces an upper limit on the range of versions supported by your theme, as indicated in your install.rdf. See topic "Submitting a Theme to AMO" for more.
Testing Your Theme
Before you submit your theme to AMO, and before you publish it to the world at large, you'll want to test it to make sure it works. This isn't rocket science and no one dies if you get it wrong, but you don't want to inconvenience or even alienate your users with a theme that doesn't work.
Testing a theme basically means running Firefox with it under a variety of conditions to make sure it works right, however you define "works right" as the developer of the theme. It should look the way you want. It should be usable. All interactive objects like buttons and menus should work the way that buttons and menus are supposed to work. It should allow the end user to set system text sizes other than the default. Since the toolbar can operate in a variety of modes, with various icon sizes and active toolbars, the theme should work with the toolbar in each of those modes. If your theme is represented as working on Mac, Windows, and Linux, then it should actually work on Mac, Windows and Linux.
There are several degrees of testing. First, you could simply install it in Firefox and make sure nothing breaks in the first couple minutes. That's not much of a test, but it's a start.
Second, you could just test the parts that you know have changed. For example, maybe you have an existing theme and you've only worked on the Options window, so you might choose to test only the Options window. This isn't the best way, though. Software quality professionals would tell you that this is a way to let bugs creep in. The problem is that changes in one part of the theme have effects in other parts of the theme. For example, global.css is used by almost every window in Firefox, so any change there could have a wide impact. Also, all of the rules from all of the CSS files that are loaded for each window all go into one big collection of rules, where they all compete to define the way the window looks, and if you change a couple rules in one CSS file it still may change the outcome of the competition to decide which rules will apply.
Third, a more thorough test would look at each of the major windows and most of the supporting windows. This is starting to be a lot of work, taking a lot of time, but if you really want to be sure then there's no substitute for taking the time to see for yourself.
Fourth, you could do a complete and thorough test of all the windows, all the supporting windows, and all the user interface widgets. Trees open and closed. All button states, all toolbarbutton states, all toolbar states. Listboxes with zero items, one item, and many items. Sidebars open, sidebars closed. In a variety of languages, with a variety of system desktop settings for colors, fonts, and font sizes. With no extensions, with various extensions installed. This kind of testing sounds great (great to have done by someone else, not so great to do for yourself), but in practice this level of effort is beyond the resources of any individual theme developer, especially when you consider multiplying this effort for one theme with one application on one platform by the number of potential applications and platforms.
magneto> hi, i'm trying to improve my testing process for Firefox extensions and themes.
can anyone suggest tools to automate the process? for example, an extension that
would go through a list of views and save snapshots to disk, or some open source
tool ($FREE) that would record and play back a sequence of UI gestures. any ideas?
with over 100 windows and views it kind of sux to have to go through all of them
one by one ...
magneto> /me hears only empty channel noise ...
There are multiple commercial applications that would automate the walkthrough and capture of screenshots from the Firefox user interface in support of testing themes. The license fees, unfortunately, place these beyond the reach of most theme developers.
The Selenium extension for Firefox is a powerful testing tool for testing web pages and web applications. It does not, however, provide any features that make it suitable for testing the Firefox user interface. You can read more about Selenium here to satisfy your curiosity, but the bottom line is, it won't help with theme development.
AutoIt, a free automation tool for the Windows GUI, shows promise as a way of automating the process of walking through all the windows of Firefox to verify the proper function of your theme. One member of the Firefox QA team reported good results, while also pointing out that it would not address testing needs on platforms other than Windows.
The XUL Periodic Table provides a very useful resource. The linked page contains live XUL code which allows you to view each kind of XUL user interface widget in a variety of states and modes (button normal, button disabled, button mouseover, button click, and so on), rendered as directed by the currently-selected theme. It is also packaged for downloading, so you might consider grabbing it while it's available.
It appears that the Extension Developer's Extension allows you to reload the Firefox user interface without having to completely restart Firefox. It's not instantaneous, but it is faster than restarting every time you want to test your changes. Under the Firefox "Tools" menu, pick Extension Developer > Reload all Chrome.
Some theme authors have a long-established template that they use for all their themes (long-established, meaning years). This doesn't do away with the need for testing, but by using code that they know well, it does make it harder to make mistakes, and by using the same code for all their themes, it reduces the amount of testing required.
In the end, as a theme developer, you'll have to decide how much effort to invest in testing. Most theme developers test it semi-thoroughly on the systems available to them, rely on online friends and other theme authors to test on systems not available to the developer, and fix any bugs found by their users after the theme is published. As a practical matter, this seems to work OK.
Submitting a Theme to AMO
AMO is short for "addons.mozilla.org", the web address of the site that hosts the official themes and extensions available for Firefox and the other members of the Mozilla software family.
If you have a theme that you'd like to be available on AMO, then you submit the theme for approval, after which it is listed with all the other available themes. Start by creating an account on AMO here. Submitting your theme is then a matter of packaging your theme as a valid jar containing all the required components, uploading the jar to AMO, and providing some required information and preview images. All of the actions involved in submitting your theme begin with your Developer Control Panel, which is where you will start each time you log in to AMO.
The submission and approval process actually consists of two steps. The first step takes place within seconds of submitting your theme to AMO, providing an initial sanity check of the format and contents of your jar, making sure that it is installable and contains correct values for application GUIDs and versions. The second step takes place after AMO forwards your submission to an individual reviewer, who gives your theme a more in-depth examination and workout. When the second step is complete, you'll receive an email telling you the outcome.
A frequent question is how long the second step takes. The answer is, it depends on the reviewer: some will review and reply within hours, while others take longer. If you haven't heard back within three days, at the most, you should go online with Chatzilla and visit the #amo channel on irc://moznet/. Just wait for a pause in the conversation, say hi, and then mention that it's been a while since your submission and you wonder if they could nudge your reviewer.
The theme and extension submission front end for AMO, while recognized and valued as an essential part of the theme and extension mechanism for Firefox, is generally known to need some polish. In particular, the interface is on the terse side, and provides little or no feedback on the reason for a rejected submission. This is expected to improve in the near future: work is underway on a new and improved AMO. You can read more here.
At some point in development you'll want to submit a theme to see how AMO and the submission process works. The only problem is, there's no way to mark a theme as "test only" or "not for public release"; if you submit to AMO, and the submission is approved, then your theme will be available for download. The thing to do then is simply to go back to the Developer Control Panel and delete your submission.
When is a theme good enough to submit to AMO? The only guidance here is that it should at least be functional, if not yet beautiful, and if your theme is an alpha or beta version, not ready for prime time, then say so in the "Developer Comments" for the submitted theme, and also on the "About Theme" dialog.
Many developers with web sites of their own choose not to host their theme on AMO. There are several good reasons for this choice:
- You are no longer subject to the schedule imposed by your reviewer. When you update your theme, you can make it available to your users almost immediately. This can be important if you are keeping up to date with nightly changes in development versions of Firefox like Bon Echo and Minefield.
- AMO restricts you to a single jar for each theme, which must contain all code for all supported browsers within the one jar. If you'd rather have different jars for different browsers, you won't be able to host on AMO.
- Some theme developers set up a Paypal link on their sites. You wouldn't be able to do this with AMO.
- Your users can be assured that your theme has been officially reviewed under the auspices of the Mozilla Corporation. This is admittedly more important with extensions and their associated security implications than with themes.
- Firefox users won't have to go looking to find your theme. When they click "Get More Themes" on the Themes Manager (Firefox 1.5) or Add-ons Manager (Firefox 2.0), they'll be taken to AMO, where your theme will be listed.
Note that AMO requires that your install.rdf NOT contain an <em:updateURL> property. (The updateURL property tells Firefox where to check to see if an update for your theme is available when the end user clicks "Find Updates" on the Themes Manager or Add-ons Manager window.) This will be inserted into your install.rdf by AMO after you submit your theme, so that it will point to the correct location on the AMO site.
Themes and the Profile Manager
Recall that Firefox uses profiles to represent a collection of settings for a particular user, and that the Profile Manager is the Firefox window that allows the user to select the active profile for Firefox. As a theme developer, you need to know that the Profile Manager is not subject to the style defined by any theme other than the Firefox default theme. In other words, it's not possible to write style rules in an add-on theme that apply to the Profile Manager.
This is true because the only theme that Firefox will have loaded at the time when the Profile Manager runs (right at the start of launching Firefox) will be the default theme. The set of installed themes is associated with a particular profile (each profile having its own list of installed themes), and when the Profile Manager runs you don't yet know which profile is going to be selected. For this reason, the styling of the Profile Manager UI is always determined by the Firefox default theme, which will always have been loaded at the time the Profile Manager runs.
This means also that you can't uninstall the default Firefox theme, even if you never use it any more, unless you want to suffer the loss of style definitions for the Profile Manager. That can't be a good thing.
magneto> hi, are the "Firefox Safe Mode" and "Profile Manager" dialogs skinnable? i'm assuming not,
so i guess i'm asking also about what happens during that part of startup,
are they part of the same executable or a separate one, etc.
mao> magneto: they're part of the same executable, but are executed before the profile is set,
so there's no way to access user preferences, extensions and themes
magneto: (because you don't really know "who" the user is)
magneto> doh of course. so i guess the firefox default theme is in effect at that point. ?
mao> magneto: yes, because it is stored in the installation path, rather than inside the profile
Themes and Extensions
You probably already know that extensions are downloadable modules that add features and user interface to the default Firefox browser. How does your theme interact with extensions? In general, themes apply to extensions the same way themes apply to the basic Firefox, as if the extensions were just another part of the Firefox UI. CSS rules in your theme that apply to the default Firefox user interface also apply, in general, to the user interface of extensions. More about this in a moment.
You could choose to simply ignore extensions in your theme (many themes do), in which case the user interface of extensions will look however it looks with whatever icons and style rules they use. Most of the rules for generic objects will find their way into any user interface elements added by extensions.
However, theme authors frequently find that
- their themes require special handling for extensions to make sure that their appearance matches the rest of the Firefox UI
- the same obsessive-compulsive instincts that led them to think they could do better than the default theme leave little tolerance for the rough edges of a mismatch between extensions and the rest of Firefox, especially since many extensions make their presence felt in the main browser window, and not just off in some little-used dialogs, and
- there are so many extensions that they have to pick and choose which ones to support.
There's an additional complication in that not every extension uses the same CSS files from the current theme. CSS rules from the current theme don't automagically make their way to UI elements added by an extension; they apply to them when the extension is programmed to specifically use CSS files from the current theme. You may have to do some detective work to figure out which CSS files are used by an extension to know where your extension-specific rules should go. In general, most extensions include chrome://global/skin/global.css, so this is a good place to start when you are thinking about writing extension-specific rules. It's not that there's anything that guarantees this; it's just that the code for almost all windows and extensions is written to use this CSS file.
How do the CSS rules from your theme make their way to the UI elements of an extension? Four ways:
- For UI elements added by an extension to the main browser window, such as menus, sidebars, or toolbar buttons, the style rules imported by the main browser window will still be in effect.
- For individual windows and dialogs added by an extension, these will have whatever style rules are defined by whatever CSS files those windows and dialogs choose to import. This is entirely up to the author of the individual extension. In practice, most, but by no means all, windows in an extension will include chrome://global/skin/global.css.
- Through Firefox's default XBL bindings. The UI code for Firefox uses XBL to replace individual DOM nodes with nested DOM nodes performing the same function. (For example, when the <BUTTON> element is encountered in XUL source code, it is replaced by a set of hboxen and vboxen nested inside of the button.) The default XBL bindings specify which CSS files get included for bound elements. The CSS files specified in this way will resolve to some of the mandatory CSS files in your theme (e.g. button.css). (This description takes for granted a lot of knowledge on the part of the reader; to see past some of the hand-waving, read topic "XBL and the Firefox UI" for a more thorough description.)
- Individual Firefox users can choose to include rules from your theme (by copying and pasting) in their userChrome.css.
Keep in mind that extensions usually have their own CSS style rules, specified either within the source code for the extension UI or as an overlay in the extension's chrome.manifest (or even, for the bad actors of the extension world, as explicit <style="whatever"> statements within the XUL source). This means that your rules may be competing with rules from the extension itself. In this case, you have recourse to four options:
- Try your rules as you wrote them; they may be specific enough to take precedence over any rules defined by the extension.
- Increase the specificity of your selectors, so that in case of a contest your rule wins.
- Use !important on your rule, further increasing its chances of winning in case of a contest (but see topic "Using !important with CSS Rules" for cautions).
- For the very baddest of bad actors of the extension world, completely incorporate their CSS rules into your theme, and add an entry to your contents.rdf/chrome.manifest to shortcircuit their style rules entirely. You can do this because it's open source. You don't want to do this because it's pointless extra work. Sometimes you have no other choice.
My chosen approach has been to handle the following:
- Tab Mix Plus, TabX, and Tabbrowser Preferences, because these all impact the look of the browser tabs, which are front and center in the end user's experience. (I lost patience with this before SuperT came out. Hopefully they're not doing anything too wierd.)
- Sage, Chatzilla, MTLI, ForecastFox, FireFTP, and Webdeveloper, because I use them all the time
- Splash, because I made the icons for it and I want it to look good with my theme
- AIOS, UI Tweaker, and FEBE, because these all use a prefwindow-based Options window, and my rules for the main Firefox Options window have so heavily customized it that I have to write rules specific to other prefwindows for them not to look funny
- and a few others for which I created a toolbarbutton that would match the look of the rest of the main toolbar buttons.
Do Themes Represent a Security Hole
How safe are themes? The only potential security hole I've seen is in the "aboutURL" element of install.rdf. The aboutURL element lets you say that the "About Theme" pop-up will be defined by some XUL within your theme, which XUL can then execute the Javascript code of your choice in your theme, which is the potential problem. I've never seen anyone else mention this so perhaps the Javascript which can be run in this way is somehow limited to a safe sandbox.
Theme Development: Conclusion
This concludes the part of the article which focuses on theme development. Armed with what you've learned in this section, this might be a good time to review the pitfalls of theme development discussed in topic "Hidden Traps of Theme Development", or read on for a discussion of Part Four: Theme Technologies.
