This tutorial will take you through the steps required to build a very basic theme - one which updates the background color of the toolbars in Firefox.
Note: This tutorial is about building themes for Firefox 29 and later. Other tutorials exist for building themes for earlier versions of Firefox. For an older tutorial, see Creating a Skin for Firefox.
Note: Firefox for Mac OS X has changed some directories so the guide may be obsolete.
Themes and extensions are packaged and distributed in ZIP files or Bundles, with the XPI
(pronounced “zippy”) file extension.
An example of the content within a typical XPI file for a theme:
example.xpi: /install.rdf /chrome.manifest /preview.png /icon.png /chrome/ browser/ communicator/ global/ mozapps/
We'll want to create a file structure similar to the one above for our tutorial, so let's begin by creating a folder for your theme somewhere on your hard disk (e.g. C:\themes\my_theme\
or ~/themes/my_theme/
). Inside your new theme folder, create two new empty text files, one called chrome.manifest
and the other called install.rdf
. The file preview.png
is shown as a preview of the theme in the themes panel of the add-ons window. The file icon.png
is used as an icon in the same panel. We'll leave both of them out for now, unless you have something picked out that you want to use.
The remaining directories will be extracted from the default theme. First, you'll want to create a directory somewhere. Copy your Firefox installation's omni.ja
into this directory. The location differs by operating system:
Linux: /usr/lib/MozillaFirefox/chrome/classic.ja
or /usr/lib/firefox-*.*.*/omni.ja
Windows: \Program Files\Mozilla Firefox\omni.ja
Mac OS X: /Applications/Firefox.app/Contents/MacOS/omni.ja
Now, open (or unzip) this file into the directory you created. It contains several folders, modules
, jssubloader
and others. The files we will be needing are located under the chrome\toolkit\skin\classic
folder.
Create a folder called chrome
in your theme's folder. Next, the contents of the following directories to their respective folders into the folder.
global
to chrome/global
mozapps
to chrome/mozapps
Now that you've copied the global
and mozapps
folders, a handful of other folders from the browser/omni.ja
archive are required. It is located in the browser folder in the location mentioned above. The files we will be needing from the browser/omni.ja archive are located under chrome/browser/skin/classic
.
Copy the contents of the following directories to their respective folders. This gives us a base set of styles to work with.
browser
to chrome/browser/
communicator
to chrome/communicator/
You should end up with this directory structure:
<ext path>/ /install.rdf /chrome.manifest /chrome/ browser/ communicator/ global/ mozapps/
After this, it would be a good idea to read the article Setting up extension development environment and follow the directions there. It's especially important to install the DOM Inspector, which we'll be using in later steps.
Open the file called install.rdf
that you created at the top of your extension's folder hierarchy and put this inside:
<?xml version="1.0"?> <RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> <Description about="urn:mozilla:install-manifest"> <em:id>sample@example.net</em:id> <em:version>1.0</em:version> <em:type>4</em:type> <!-- Target Application this theme can install into, with minimum and maximum supported versions. --> <em:targetApplication> <Description> <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <em:minVersion>29.0</em:minVersion> <em:maxVersion>39.*</em:maxVersion> </Description> </em:targetApplication> <!-- Front End MetaData --> <em:name>My Theme</em:name> <em:internalName>sample</em:internalName> <em:description>A test extension</em:description> <em:creator>Your Name Here</em:creator> <em:homepageURL>http://www.example.com/</em:homepageURL> </Description> </RDF>
If you get a message that the install.rdf is malformed, it is helpful to load it into firefox using the File->Open File command and it will report XML errors to you.
See Install Manifests for a complete listing of the required and optional properties.
Save the file.
Firefox's user interface is written in XUL and JavaScript. XUL is an XML grammar that provides user interface widgets like buttons, menus, toolbars, trees, etc. User actions are bound to functionality using JavaScript. These XUL elements are styled using CSS. If you don't know CSS, it's going to be a steep learning curve, and you may want to try some HTML-based tutorials to start with.
The browser UI has absolutely no styling on its own - if you try to start up with an empty theme, Firefox will be unusable, as the button elements will be drawn as plain text. This is why we copied the default styles in the setup step.
When writing a theme, the easiest way to determine what CSS selectors you need to write is to use the DOM Inspector which you should have installed in the setup step. You can use this to inspect any element in a web page or an XUL document, which makes it invaluable for themes.
Note In Firefox 4.0 and up, the highlight feature of DOM Inspector is broken. To workaround this, disable Hardware Acceleration in Firefox' Options.
Open up the DOM Inspector now (located under the "Tools" menu), and go to "File->Inspect Chrome Document". This will be a menu containing all the XUL documents currently open in Firefox.
Pick the first document with a web page title, like "Firefox Start Page" and select it.
For this tutorial, we're going to update the background color of the toolbars. Select the node finding tool (the arrow-plus-box in the top-left corner of the DOM Inspector), and click on any unused space on a toolbar. This should select a node of type "xul:toolbar" in the DOM Inspector.
From here, you can play around with various different stylings for the toolbar and associated elements. By default, the right pane should show the DOM node, which has useful styling information like the CSS class and node id. The element itself is of id navigator-toolbox
, with no idea. To change its style within our theme, we need to write a selector rule to select this class.
Open up the file chrome/browser/browser.css
in your theme. Search this file for the #navigator-toolbox
selector, and add a background: orange;
rule to it.
Save the file.
Next, we have to tell Firefox where to find the theme files for your theme. CSS, XUL, and other files are part of "Chrome Packages" - bundles of user interface components which are loaded via chrome://
URIs. Rather than load the browser from disk using a file://
URI (since the location of Firefox on the system can change from platform to platform and system to system), Mozilla developers came up with a solution for creating URIs to content that the installed add-on knows about.
The browser window is: chrome://browser/content/browser.xul
. Try typing this URL into the location bar in Firefox!
Chrome URIs consist of several components:
chrome
) which tells Firefox's networking library that this is a Chrome URI. It indicates that the content of the URI should be handled as a (chrome
). Compare (chrome
) to (http
) which tells Firefox to treat the URI as a web page.browser
) which identifies the bundle of user interface components.content
(XUL, JavaScript, XBL bindings, etc. that form the structure and behavior of an application UI), locale
(DTD, .properties files etc that contain strings for the UI's localization), and skin
(CSS and images that form the theme of the UI)So, chrome://foo/skin/bar.png
loads the file bar.png
from the foo
theme's skin
section.
When you load content using a Chrome URI, Firefox uses the Chrome Registry to translate these URIs into the actual source files on disk (or in JAR packages).
The Chrome Manifest is the file that maps these Chrome URIs to your theme's files. For more information on Chrome Manifests and the properties they support, see the Chrome Manifest Reference.
Open the file called chrome.manifest that you created alongside the chrome
directory at the root of your extension's source folder hierarchy.
Add in this code:
skin browser sample chrome/browser/ skin communicator sample chrome/communicator/ skin global sample chrome/global/ skin mozapps sample chrome/mozapps/
Don't forget the trailing slash, "/
"! Without it, the package won't be registered. The third column needs to match your theme's internalName value from the install manifest above.
This maps skin directories to locations within your theme. For example, the line skin browser sample skin/browser/
means "when the user has the sample
theme selected, use the directory browser/
to look up skins for the browser
package." More concisely, this means that the URL chrome://browser/skin/some/path/file.css will look for a file browser/some/path/file.css
in your theme's root directory.
Save the file.
First, we need to tell Firefox about your theme. During the development phase for Firefox versions 2.0 and higher, you can point Firefox to the folder where you are developing the theme, and it'll load it up every time you restart Firefox.
Firefox/Profiles/<profile_id>.default/
).extensions/
folder, creating it if need be.C:\themes\my_theme\
or ~/themes/my_theme/)
. Windows users should retain the OS' slash direction, and everyone should remember to include a closing slash and remove any trailing spaces.sample@example.net
). No file extension.Now you should be ready to test your theme!
Start Firefox. Firefox will detect the text link to your theme directory and install the theme. Your theme will not be active the first time you install, and you will need to click "Enable" and restart before you can see your change. After it restarts this second time, you should see the background color of the toolbars is displayed in orange now.
You can now go back and make additional changes to your css files, close and restart Firefox, and see the updates.
Now that your theme works, you can package it for deployment and installation.
Zip up the contents of your theme's folder (not the theme folder itself), and rename the zip file to have a .xpi extension. In Windows, you can do this easily by selecting all the files and subfolders in your extension folder, right click and choose "Send To -> Compressed (Zipped) Folder". A .zip file will be created for you. Just rename it and you're done!
On Mac OS or Linux, you can use the command-line zip tool:
zip -r my_theme.xpi install.rdf chrome.manifest browser communicator global mozapps
Or, if you have 7-Zip installed, you can use that for zipping it up:
7z a -tzip my_theme.xpi chrome chrome.manifest
Note: The command-line tool will update an existing zip file, not replace it - so if you have files you've deleted from your theme, be sure to remove the .xpi
file before running the zip command again.
Now upload the .xpi file to your server, making sure it's served as application/x-xpinstall
. You can link to it and allow people to download and install it. For the purposes of just testing our .xpi file we can just drag it into the Add-ons Manager via "Tools -> Add-ons Manager", or open it using "File -> Open File...".
There are a variety of ways you can install extensions from web pages, including direct linking to the XPI files and using the InstallTrigger object. Extension and web authors are encouraged to use the InstallTrigger method to install XPIs, as it provides the best experience to users.
Mozilla Add-ons is a distribution site where you can host your theme for free. Your theme will be hosted on Mozilla's mirror network to guarantee your download even though it might be very popular. Mozilla's site also provides users easier installation, and will automatically make your newer versions available to users of your existing versions when you upload them. In addition, Mozilla Add-ons allows users to comment and provide feedback on your theme. It is highly recommended that you use Mozilla Add-ons to distribute your themes!
Visit https://addons.mozilla.org/developers/ to create an account and begin distributing your themes!
Note: Your theme will be passed faster and downloaded more if you have a good description and some screenshots of the theme in action.
______________________________