Visit Mozilla.org

Using the Stylesheet Service

From MDC


Contents

[edit] Introduction

In Firefox 1.5, an API was added allowing extensions to manage user and UA stylesheets without having to touch userContent.css or userChrome.css files. The API is defined in nsIStyleSheetService.idl.

In Firefox 1.5 and 2, adding and removing such style sheets takes effect upon the next load of a page. In Firefox 3, the changes take effect immediately, though some declarations (especially those affecting XUL) won't work until a reload.

Registered style sheets are not remembered across restarts.

Stylesheets added using this service get applied to both chrome and content documents. Remember to declare the correct namespace if you want to apply stylesheets to XUL documents.

The examples in this document are all written in JavaScript using XPCOM.

[edit] Using the API

The string "chrome://myext/content/myext.css" in the examples below is just an example. Replace it with the URL of the CSS file you want to load.

You can replace USER_SHEET with AGENT_SHEET, depending where in the CSS Cascade you want the sheet to be placed. See the CSS Specification for more details.

[edit] Adding a stylesheet

To use the stylesheet service, you get a reference to the service, create a URI and pass the URI to the stylesheet service's loadAndRegisterSheet method.

var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
var uri = ios.newURI("chrome://myext/content/myext.css", null, null);
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
Note: loadAndRegisterSheet will load the stylesheet synchronously, so you should only call this method using local URIs.

[edit] Determining whether a sheet has been loaded

If you are writing an extension and adding your stylesheet in an onload handler, you'll want to see if your sheet has already been added. If you don't check, you will wind up adding your sheet once per window load.

var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
var uri = ios.newURI("chrome://myext/content/myext.css", null, null);
if(!sss.sheetRegistered(uri, sss.USER_SHEET))
  sss.loadAndRegisterSheet(uri, sss.USER_SHEET);

[edit] Removing a previously registered stylesheet

If you wish to remove a stylesheet that you previously registered, simply use the unregisterSheet method.

var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"]
                    .getService(Components.interfaces.nsIIOService);
var u = ios.newURI("chrome://myext/content/myext.css", null, null);
if(sss.sheetRegistered(u, sss.USER_SHEET))
  sss.unregisterSheet(u, sss.USER_SHEET);

[edit] Backwards compatibility

You can check for the availability and the functionality of the stylesheet service:

if("@mozilla.org/content/style-sheet-service;1" in Components.classes)
{
  if(Components.ID('{41d979dc-ea03-4235-86ff-1e3c090c5630}')
               .equals(Components.interfaces.nsIStyleSheetService))
  {
    // stylesheet service is available, but changes won't apply until reload
    // (Firefox 1.5 and 2 behaviour)
  }
  else
  {
    // stylesheet service is available and changes will apply immediately
    // (Firefox 3 behaviour)
  }
}
else
{
  // stylesheet service is not available (pre-Firefox 1.5 behaviour)
}