• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Add-ons
  1. MDN
  2. Mozilla
  3. Add-ons
  4. Overlay extensions
  5. XUL School Tutorial
  6. Adding Toolbars and Toolbar Buttons

Adding Toolbars and Toolbar Buttons

In This Article
  1. Adding a new toolbar
  2. Toolbar buttons
    1. Toolbar button icons
  3. The Customize Toolbars Dialog
  4. Adding toolbar buttons to existing toolbars

Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use WebExtensions instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.

From Firefox 53 onwards, no new legacy add-ons will be accepted on addons.mozilla.org (AMO).

From Firefox 57 onwards, WebExtensions will be the only supported extension type, and Firefox will not load other types.

Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to WebExtensions if they can. See the "Compatibility Milestones" document for more.

A wiki page containing resources, migration paths, office hours, and more, is available to help developers transition to the new technologies.

« PreviousNext »

Adding a new toolbar

Adding new toolbars to Firefox is easy, but adding them the wrong way is very easy as well.

Toolbars in Firefox are very customizable. Some users don't like extra toolbars, or they want to rearrange toolbar buttons to their liking, possibly merging multiple toolbars in the process. Firefox allows all of this by default, and if you don't pay attention to the details we describe here, your toolbar may not be as easy to customize as the rest.

The first thing you need to do is add your buttons to the toolbar palette. The toolbarpalette is a collection of all toolbar buttons and toolbar items in Firefox, including those added by extensions. To add your buttons, all you need to do is overlay the palette in your main browser overlay.

<overlay id="xulschoolhello-browser-overlay"
  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <toolbarpalette id="BrowserToolbarPalette">
    <toolbarbutton id="xulschoolhello-hello-world-button"
      class="toolbarbutton-1 chromeclass-toolbar-additional" 
      label="&xulschoolhello.helloWorld.label;"
      tooltiptext="&xulschoolhello.helloWorld.tooltip;"
      oncommand="XULSchoolChrome.BrowserOverlay.doSomething(event);" />
    <!-- More buttons here. -->
  </toolbarpalette>
  <!-- More overlay stuff. -->
</overlay>

One detail that is easy to overlook is the fact that the toolbarpalette element is outside of the window element. If you put the toolbarpalette element inside the window element in your overlay, some weird errors will begin to happen.

Always set the label and tooltiptext attributes of a toolbarbutton. In the case of a toolbaritem element (discussed later), use the title attribute instead of label. Tooltips are very important for users that want to know what a button does before clicking it.

Setting the image for a toolbar button is done with CSS:

#xulschoolhello-hello-world-button {
  list-style-image: url("chrome://xulschoolhello/skin/hello-world.png");
}

It's not really that simple to set the image for a toolbar button, because we need to consider the appearance of the button on different systems, and also consider the different button states, but we'll get into that further ahead.

The CSS file with your toolbar styles needs to be included in the overlay file, as you would expect, but also in the chrome.manifest file. This is very important because the toolbar customization dialog won't work correctly without this. The way to include the file in the manifest is to add this line:

style chrome://global/content/customizeToolbar.xul chrome://xulschoolhello/skin/toolbar.css

If you are using XBL bindings (explained way ahead) for your toolbar items, you'll have to include the CSS files for those as well, each in a new line like the one above.

We now have code that adds one or more buttons to the toolbar palette. The user can now use the Customize Dialog to add the buttons to the current Firefox toolbars. In most cases this is not what you want as default behavior, because it would be very hard for the user to discover your buttons. Keep in mind most users don't know how to customize toolbars in Firefox.

Let's add our own toolbar. This is done in the overlay as well.

<window id="main-window">
  <toolbox id="navigator-toolbox">
    <toolbar id="xulschoolhello-toolbar" toolbarname="&xulschoolhello.toolbarName.label;"
      accesskey="&xulschoolhello.toolbar.accesskey;"
      customizable="true" mode="icons" context="toolbar-context-menu" 
      defaultset="xulschoolhello-hello-world-button"
      insertbefore="PersonalToolbar" />
  </toolbox>
</window>

(Note for Mac OS X: <window id="main-window">  and </window> are not required)

Our toolbar is added as a child of the toolbox element in the main browser window. The toolbox is the collection of toolbars in Firefox, including the main menu bar. Let's look at the attributes we used:

  • The toolbarname is the name that will appear on the View > Toolbars menulist. This menu allows hiding and showing any toolbar.
  • The customizable attribute determines if the user can customize the toolbar. You should normally set this to true, unless you have strong reasons not to want users changing your toolbar.
  • The mode attribute is set to icons, which is the usual value. This can be changed in the Customize dialog by the user.
  • The context attribute should also be set if you want a customizable toolbar. It points to the id of a popup element that holds the customization options that are displayed when the user right-clicks on the toolbar. This popup is already part of the main window, so it doesn't need to be implemented again.
  • The defaultset attribute lists the ids of the icons you want to include on your toolbar by default. It's a comma-separated list of ids, and it can also include other special values: spacer, separator and spring. spacer represents an empty button space, separator a vertical separation line and spring a flexible empty area that stretches.
  • Finally, the insertbefore attribute places our toolbar above the Bookmarks Toolbar. This is a matter of personal preference, but the Mac OS theme seems to be designed so that the Bookmarks Toolbar is always the last one (it has a lighter color than the rest). It also makes sense from a usability perspective, since bookmarks should be very easy to access for the user.

That's it for the basics. With this knowledge you should be able to create simple toolbars and toolbar buttons you can add to Firefox. Now we'll look deeper into the details of toolbars so that you can make great toolbars.

Toolbar buttons

There are several types of buttons and elements you can add to a toolbar depending on your needs. The toolbarbutton element has the type attribute that allows you to change the behavior of the button in many ways. The menu and menu-button types allow you to create buttons that open popup menus beneath them. See the Back/Forward buttons in the main Firefox toolbar for an example. Menu toolbar buttons are handy when you want to include many options in your toolbar and you don't want it to be too cluttered. The other types, checkbox and radio are useful when you have buttons that change state when the user clicks on them. Read more about this in the type attribute specification.

Keep in mind some users have small screens with low resolution. If you shrink the Firefox window, you'll notice that the content resizes until it reaches its minimum size and begin to be cropped (cut), making UI elements disappear. You should test that your toolbar resizes gracefully and doesn't force Firefox to crop content before it's strictly necessary.

When you need something more elaborate than a button in your toolbar, you can use the toolbaritem element instead. This element is nothing more than a wrapper, so you can have whatever XUL content you want in it. However, you should keep in mind that odd-looking toolbars are likely to confuse and annoy users. Use custom toolbar items sparingly.

Toolbar button icons

Creating the icons for toolbar buttons is one of the most difficult tasks when making extensions. It is not too hard to come up with some graphics for the buttons, but it can be hard to make them blend in with Firefox on all operating systems. The way icons are handled in Firefox changed considerably after Firefox 4, so supporting older versions is not mentioned here (you can check this document's change history for older revisions, though).

These are the current icon sets for Firefox:

Windows

Toolbar-win.png

Mac OS X (Lion and above)

Toolbar-mac-lion.png

Mac OS X

Toolbar-mac.png

Linux (Gnome)

Toolbar-gnome.png

Toolbar-gnome-small.png

Note: the images above are probably not distributable under the same CC license, unlike the rest of this material.

Here are the key similarities and differences between the 3 themes:

  • All systems use small icons that are 16x16 pixels. Only the Gnome theme has a set of large icons that are 24x24 pixels.
  • Only a few icons have different states (rows). The disabled state for most buttons is handled with CSS.
  • The icon sets have different paddings for their icons. The one for Windows has 19x19 pixel frames, while the Mac OS ones are 20x20 pixels. This doesn't really matter as long as the contents are 16x16 and they are centered in the frame.
  • Mac OS X Lion has icons with a lighter shade.
  • On Linux, icons are 24x24 pixels by default. Since Firefox is a GTK application, it uses GTK icons whenever possible. The icons in the image are the ones that aren't provided by GTK. GTK icons are accessed using special URLs, like this one: moz-icon://stock/gtk-go-back?size=menu. You can enter this URL in Firefox on Linux, and the corresponding icon will be displayed. This is also the reason this is the only theme that still has colorful icons for its buttons.

Now let's look at the CSS work involved in a toolbar that works on the aforementioned systems. If you want your toolbar to look right on all systems, you should consider having different icon sets for each. You should also consider using a graphic designer for this work, as it takes a lot of attention to detail to make good icons.

You can have a different skin directory for each operating system using Manifest Flags in the chrome.manifest file:

skin xulschoolhello classic/1.0 skin/unix/ 
skin xulschoolhello classic/1.0 skin/win/    os=WINNT
skin xulschoolhello classic/1.0 skin/mac/    os=Darwin

The osversion flag can be used in case we wanted to have different icons for Mac OS X Lion and above, and others for older systems. In this example we won't bother.

There is a separate skin directory for each system, with the Unix theme as the default (as most other systems are Unix-based). This makes it easy to keep the themes separate and to make changes to one of them without having to worry about the rest. On the other hand, it is often the case that there are multiple images and CSS sheets that are the same for all systems. For example, your extension logo icon will probably be the same. Having multiple copies of these files can be wasteful, so you may want to have a "common" directory.

Image files use the most space in an extension package, by far. Most extensions are a few hundred kilobytes in size or smaller. If your file is getting too big, you should look into optimizing your images.

Given the way manifest files work, we have found that the best solution is to have a separate package name for OS-specific skin files.

skin xulschoolhello    classic/1.0 skin/all/
skin xulschoolhello-os classic/1.0 skin/unix/
skin xulschoolhello-os classic/1.0 skin/win/    os=WINNT
skin xulschoolhello-os classic/1.0 skin/mac/    os=Darwin

All we did here is add a new entry for "common" styles that points to the all directory. The OS-specific entries now use a different package name: xulschoolhello-os. Now you just need to be careful about when to use chrome://xulschoolhello/skin/ and when to use chrome://xulschoolhello-os/skin/. It's a bit hacky, but it works well.

As for the image files themselves, you may be wondering why it is that all icons are included in a single file instead of having one file for every icon. One reason is that it would be complicated to manage that many files, and it becomes more likely that changes made to some of the files lead to an inconsistent appearance that is not obvious by looking at the individual files. It is easier to be able to edit all icons in one go. There is also a performance gain from using a single file. To get the region that corresponds to a specific state of an icon, the -moz-image-region CSS property is used.

Here are some examples of how the CSS for a toolbarbutton would look like on the 3 major platforms. This assumes that you've set the class xs-hw-toolbarbutton to all of your buttons.

Windows:

/* The second and third selectors at the bottom are necessary to prevent 
   conflicts with installed themes. */
toolbarbutton.xulschoolhello-toolbarbutton,
window:not([active="true"]) toolbarbutton.xulschoolhello-toolbarbutton,
toolbar[iconsize="small"] toolbarbutton.xulschoolhello-toolbarbutton {
  list-style-image: url("chrome://xulschoolhello-os/skin/toolbar.png");
}
#xulschoolhello-hello-world-button {
  -moz-image-region: rect(0px, 16px, 16px, 0px);
}

Mac OS X:

/* The second and third selectors at the bottom are necessary to prevent
   conflicts with installed themes. */
toolbarbutton.xulschoolhello-toolbarbutton,
window:not([active="true"]) toolbarbutton.xulschoolhello-toolbarbutton,
toolbar[iconsize="small"] toolbarbutton.xulschoolhello-toolbarbutton {
  list-style-image: url("chrome://xulschoolhello-os/skin/toolbar.png");
}
#xulschoolhello-hello-world-button {
  -moz-image-region: rect(0px, 16px, 16px, 0px);
}

Linux:

/* The second and third selectors at the bottom are necessary to prevent
   conflicts with installed themes. */
toolbarbutton.xulschoolhello-toolbarbutton,
window:not([active="true"]) toolbarbutton.xulschoolhello-toolbarbutton {
  list-style-image: url("chrome://xulschoolhello-os/skin/toolbar-large.png");
}
#xulschoolhello-hello-world-button {
  -moz-image-region: rect(0px, 24px, 24px, 0px);
}
toolbar[iconsize="small"] #xulschoolhello-hello-world-button {
  list-style-image: url("chrome://xulschoolhello-os/skin/toolbar.png");
  -moz-image-region: rect(0px, 16px, 16px, 0px);
}

Several CSS rules apply by default to all toolbar buttons. These add the button-like look you want. If for some reason you want to override these styles (not recommended), you'll need the following rule:

-moz-appearance: none;

-moz-appearance can be used in many cases where you want to strip the native look out of an element. This will save you a lot of time trying to remove all the CSS rules that give the buttons a native look. You'll probably still need to override a couple other CSS rules to get a completely plain look.

The Customize Toolbars Dialog

Firefox has the option to customize its toolbars. We've already mentioned this before, and if you follow our recommendations, then you shouldn't have many problems making your toolbar compatible with the Customize Toolbars dialog. The dialog can be opened from View > Toolbars > Customize..., or by right-clicking on the main toolbar (or any toolbar with the correct context attribute value) and clicking on the Customize option.

Other than what we have stated before, you should take into account the controls at the bottom of the Customize Toolbars dialog. You should test your toolbar buttons and items under all combinations of Icons / Icons and text / Text, Use Small Icons, and having your icons in different toolbars. You should also test that the Reset to Defaults button works correctly. Adding elements to your toolbar that are not toolbarbutton or toolbaritem will cause it to fail. Make sure your icons look OK while the Customize Dialog is open, and after clicking on the OK button. If you use XBL bindings, make sure everything works normally after customizing toolbars. All of this is very important to test because, when the dialog is opened, Firefox changes the DOM of the toolbar, adding wrapper elements that allow the customization. This tends to break very specific CSS, and XBL bindings lose their internal state when moved around the DOM.

Adding toolbar buttons to existing toolbars

Finally, there is the very common case where you just want to add one button to the main toolbar. In this case you still need to add the button to the palette using an overlay. In order to add your button to the main toolbar on first run, you'll have to use Javascript code. Keep in mind that you shouldn't assume anything about the location (or presence!) of any specific buttons; remember users could have moved them or removed them altogether. The Toolbar Code Snippets page has a code sample you can use to do this.

Remember to validate if your button is already present, to prevent duplicates. It's also a good idea to set a preference that indicates that you added your button already, so that it can be removed permanently if the user chooses to. Another option is to use FUEL's firstRun property, which also relies on a preference.

Firefox 3

let extension = Application.extensions.get(YOUR_EXTENSION_ID);
if (extension.firstRun) {
  // add button here.
}

Firefox 4

Application.getExtensions(function (extensions) {
    let extension = extensions.get(YOUR_EXTENSION_ID);
    if (extension.firstRun) {
      // add button here.
    }
})

Both

function firstRun(extensions) {
    let extension = extensions.get(YOUR_EXTENSION_ID);
    if (extension.firstRun) {
      // add button here.
    }
}
if (Application.extensions)
    firstRun(Application.extensions);
else
    Application.getExtensions(firstRun);

The FUEL library currently only works on Firefox 3 and above.

« PreviousNext »

This tutorial was kindly donated to Mozilla by Appcoast.

Document Tags and Contributors

Tags: 
  • Toolbars
  • XUL
 Contributors to this page: wbamberg, mconley, jukbot, ethertank, Null, teoli, pablog, Jorge.villalobos, gianni.net, kmaglione
 Last updated by: wbamberg, Jul 4, 2016, 1:40:48 PM
See also
  1. WebExtensions
  2. Getting started
    1. What are WebExtensions?
    2. Your first WebExtension
    3. Your second WebExtension
    4. Anatomy of a WebExtension
    5. Example WebExtensions
  3. How to
    1. Intercept HTTP requests
    2. Modify a web page
    3. Add a button to the toolbar
    4. Implement a settings page
  4. Concepts
    1. Using the JavaScript APIs
    2. User interface components
    3. Content scripts
    4. Match patterns
    5. Internationalization
    6. Content Security Policy
    7. Native messaging
  5. Porting
    1. Porting a Google Chrome extension
    2. Porting a legacy Firefox add-on
    3. Embedded WebExtensions
    4. Comparison with the Add-on SDK
    5. Comparison with XUL/XPCOM extensions
    6. Chrome incompatibilities
  6. Firefox workflow
    1. Temporary Installation in Firefox
    2. Debugging
    3. Getting started with web-ext
    4. web-ext command reference
    5. WebExtensions and the Add-on ID
    6. Publishing your WebExtension
  7. JavaScript APIs
    1. Browser support for JavaScript APIs
    2. alarms
    3. bookmarks
    4. browserAction
    5. browsingData
    6. commands
    7. contextMenus
    8. contextualIdentities
    9. cookies
    10. downloads
    11. events
    12. extension
    13. extensionTypes
    14. history
    15. i18n
    16. identity
    17. idle
    18. management
    19. notifications
    20. omnibox
    21. pageAction
    22. runtime
    23. sessions
    24. sidebarAction
    25. storage
    26. tabs
    27. topSites
    28. webNavigation
    29. webRequest
    30. windows
  8. Manifest keys
    1. applications
    2. author
    3. background
    4. browser_action
    5. chrome_url_overrides
    6. commands
    7. content_scripts
    8. content_security_policy
    9. default_locale
    10. description
    11. developer
    12. homepage_url
    13. icons
    14. manifest_version
    15. name
    16. omnibox
    17. options_ui
    18. page_action
    19. permissions
    20. short_name
    21. sidebar_action
    22. version
    23. web_accessible_resources
  9. Add-on SDK
  10. Getting started
    1. Installation
    2. Getting started
    3. Troubleshooting
  11. High-Level APIs
    1. addon-page
    2. base64
    3. clipboard
    4. context-menu
    5. hotkeys
    6. indexed-db
    7. l10n
    8. notifications
    9. page-mod
    10. page-worker
    11. panel
    12. passwords
    13. private-browsing
    14. querystring
    15. request
    16. selection
    17. self
    18. simple-prefs
    19. simple-storage
    20. system
    21. tabs
    22. timers
    23. ui
    24. url
    25. webextension
    26. widget
    27. windows
  12. Low-Level APIs
    1. /loader
    2. chrome
    3. console/plain-text
    4. console/traceback
    5. content/content
    6. content/loader
    7. content/mod
    8. content/symbiont
    9. content/worker
    10. core/heritage
    11. core/namespace
    12. core/promise
    13. dev/panel
    14. event/core
    15. event/target
    16. frame/hidden-frame
    17. frame/utils
    18. fs/path
    19. io/byte-streams
    20. io/file
    21. io/text-streams
    22. lang/functional
    23. lang/type
    24. loader/cuddlefish
    25. loader/sandbox
    26. net/url
    27. net/xhr
    28. places/bookmarks
    29. places/favicon
    30. places/history
    31. platform/xpcom
    32. preferences/event-target
    33. preferences/service
    34. remote/child
    35. remote/parent
    36. stylesheet/style
    37. stylesheet/utils
    38. system/child_process
    39. system/environment
    40. system/events
    41. system/runtime
    42. system/unload
    43. system/xul-app
    44. tabs/utils
    45. test/assert
    46. test/harness
    47. test/httpd
    48. test/runner
    49. test/utils
    50. ui/button/action
    51. ui/button/toggle
    52. ui/frame
    53. ui/id
    54. ui/sidebar
    55. ui/toolbar
    56. util/array
    57. util/collection
    58. util/deprecate
    59. util/list
    60. util/match-pattern
    61. util/object
    62. util/uuid
    63. window/utils
  13. Firefox for Android
  14. Getting started
    1. Walkthrough
    2. Debugging
    3. Code snippets
  15. APIs
    1. Accounts.jsm
    2. BrowserApp
    3. HelperApps.jsm
    4. Home.jsm
    5. HomeProvider.jsm
    6. JavaAddonManager.jsm
    7. NativeWindow
    8. Notifications.jsm
    9. PageActions.jsm
    10. Prompt.jsm
    11. RuntimePermissions.jsm
    12. Snackbars.jsm
    13. Sound.jsm
    14. Tab
  16. Legacy
  17. Restartless extensions
    1. Overview
  18. Overlay extensions
    1. Overview
  19. Themes
  20. Lightweight themes
    1. Overview
  21. Complete themes
    1. Overview
  22. Publishing add-ons
  23. Guides
    1. Signing and distribution overview
    2. Submit an add-on
    3. Review policies
    4. Developer agreement
    5. Featured add-ons
    6. Contact addons.mozilla.org
  24. Community and support
  25. Channels
    1. Add-ons blog
    2. Add-on forums
    3. Stack Overflow
    4. Development newsgroup
    5. IRC Channel