Theme API Update

This article is written by Michael de Boer, Mozilla Engineering Manager working on the Firefox Frontend team. Mike has been actively involved in themes for a long time and is excited to share the improvements coming to the WebExtensions Theme API.

Last spring we announced our plans to improve themes in Firefox and today I’d like to share our progress and what you can expect in the next few releases!

We started off with laying the groundwork to get a new type of Theme supported; a new ‘theme’ WebExtension namespace was created and we made the Addon Manager aware of WebExtension Themes.

Our first milestone was to completely support the LightWeight Theme (LWT) features, because they’re so simple. This way we had our first new-style themes that are able to change the background image, background color and foreground text color working very quickly. We continued to implement more properties on top of this solid base and are moving toward Chrome compatibility at a good pace.

If you’ve created an extension before, writing your new Theme will be a walk in the park; you can use about:debugging and an extensive toolbox to load up and inspect your manifest-based theme or WebExtension that uses the ‘theme’ JavaScript API and has obtained the ‘theme’ permission.

What you can use today

Since Firefox 55, extension developers have been able to create extensions that can request permission to change the theme that’s currently active and use a number of JavaScript APIs provided by the `browser.theme` namespace.

We fondly call them ‘dynamic themes’, because you can mix and match WebExtension APIs to create wholly unique browser experiences that may reactively update parts of the browser theme.

In Firefox Quantum 57 you can use the following methods:

  • theme.update([windowId]), with which you can update the browser’s’ theme and optionally do that only for a specific window.
  • theme.reset([windowId]), which removes any theme updates made in a call to `theme.update()`. The optional windowId argument allows you to reset a specific window.

And in Firefox 58 you can use these:

As you might have noticed, the theme.update() method is where the magic happens. But it only does something pretty when you feed it a bag of properties that you want it to change.

These properties are defined in the schema and the current set is:

  • images
    • additional_backgrounds: This is a list (JavaScript Array) of image URLs that will be used as the background of a browser window. Each image will be tiled relative to its predecessor.
    • headerURL: Some of you might recognise this property from LWTs; it may be used to set the topmost background image of a browser window.
    • theme_frame: Alias for the ‘headerURL’ property, which is there for compatibility with Chrome themes.
  • colors
    • accentcolor: Use this property to change the background color of a browser window. Usually, this will be set to look pretty next to the ‘headerURL’ you provide. This is also a property that comes from LWTs.
    • tab_background_text: Alias for the ‘textcolor’ property, providing compatibility with Chrome Themes. (Since Firefox 59.)
    • bookmark_text: Alias for the ‘toolbartext’ property, providing compatibility with Chrome themes. (Since Firefox 58.)
    • frame: Alias for the ‘accentcolor’ property, providing compatibility with Chrome themes.
    • tab_text: Alias for the ‘textcolor’ property, providing compatibility with Chrome themes.
    • textcolor: Use this property to change the foreground color of a browser window and is used for the tab titles, for example. This is also a property the comes from LWTs.
    • toolbar: Change the background color of browser toolbars using this property. This property is also supported by Chrome themes.
    • toolbar_text: And this property can be used to change the foreground color inside browser toolbars, like button captions.
    • toolbar_field: Use this property to change the background color of the Awesomebar. This property is also supported by Chrome themes.
    • toolbar_field_text: Use this property to change the foreground color of the Awesomebar, thus the text you type in it. This property is also supported by Chrome themes.
    • toolbar_field_border: Use this property to change the color of border of textboxes other than the Awesomebar inside toolbars. (Since Firefox 59.)
    • toolbar_top_separator: Use this property to change the color of the top border of a toolbar that visually separates it from other toolbars above it. (Since Firefox 58.)
    • toolbar_bottom_separator: Use this property to change the color of the bottom border of a toolbar, that visually separates it from other toolbars below it. (Since Firefox 58.)
    • toolbar_vertical_separator: The color of the separator next to the application menu icon. (Since Firefox 58.)
    • toolbar_field_separator: The color of separators inside the URL bar.
  • properties
    • additional_backgrounds_alignment: Paired with the ‘additional_backgrounds’ property, you can specify the preferred position for each of the images you specified, in a JavaScript Array.
    • additional_backgrounds_tiling: Paired with the ‘addition_backgrounds’ property, you can specify the preferred tiling mode for each of the images you specified, in a JavaScript Array.

You can find a fantastic primer on browser themes and plenty of examples on MDN and https://github.com/mdn/webextensions-examples/tree/master/themes.

I would like to highlight the VivaldiFox extension in particular, created by Tim Nguyen; he not only worked on this extension but also stepped up to implement some of the missing properties that he needed! Also read his excellent Mozilla Hacks article.

Do you want a more playful introduction to all this tech talk and wish you could fiddle with these properties interactively? Your wish may be granted by our very own John Gruen:

What you can use in the future

Static themes, which only contain a manifest and image resources, will be supported on addons.mozilla.org (AMO) early this year. These will replace LightWeight Themes in a backward and forward compatible way. Until that time comes you will be able to experiment locally using about:debugging and by submitting dynamic themes that use the JavaScript API as explained above.

At this moment of writing, we’ve implemented most of the properties that Chrome supports to theme the browser. Going beyond that, we’re looking to add support for about:home custom themes and possibly for other in-content pages as well.

A group of students from Michigan State University (MSU) will be working on adding the remainder of Chrome properties and more.

One of the most exciting things to come in the near future is the ‘Theme Experiments’ API: on the Nightly channel, you can write an extension that is able to style a part of the browser UI that we haven’t implemented yet, using CSS selectors to make up your properties for it. This way it’s possible to propose new manifest properties to be added to the current set and have them become a part of Firefox, so every theme author can use it and every user may enjoy it!

Our hope is that with this in place the Theming API will evolve continuously to adapt to your needs, because we know that a good API is never ‘done’.

Get involved

If you want to help us out – yes please! – the easiest thing to start with is file bug reports with the things you think are missing today, blocking this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=themingapi.

Don’t worry about duplicate bug reports too much, we’re actively pruning the list and rather have too many than an incomplete API.

If you want to implement the next property or API method yourself, please join us on IRC in the #webextensions channel or send a message to the dev-addons mailing list!

6 comments on “Theme API Update”

  1. Stefan wrote on

    Hi there,

    That’s great. And in my Turn Off the Lights Browser extension I use the Theme API. https://addons.mozilla.org/en-US/firefox/addon/turn-off-the-lights/

    But, some web browsers doesn’t support this API. And I use this permission check in my Options page. The function works in Firefox, but this error is always visible in the ‘browser console’ window:
    “browser.theme is undefined options.js:1523”
    (I can only use this “browser.theme.update”, because the other doesn’t work -> “browser.theme”)

    // that code in line 1523
    // function available
    if(typeof browser !== ‘undefined’){
    var qtest = browser.theme.update;
    if(typeof qtest !== ‘undefined’){
    $(‘brotheme’).style.display = “block”;
    }else{
    $(‘brotheme’).style.display = “none”;
    }
    }else{
    $(‘brotheme’).style.display = “none”;
    }
    }

  2. Aleix wrote on

    Well, since you removed the compatibility with legacy extensions the only I can say is Goodbye Firefox, was great but it’s time to give a chance to other Browser that doesn’t remove functionallities that are essencial for my work suddently.

    1. Ethan wrote on

      And… how exactly does that make Firefox worse than other browsers with less extension API support?

  3. K3N wrote on

    Nice. This looks interesting, I’m gonna explore this further.

    In the future, will it be possible to say render text and bg for tabs to a canvas and use that as the tab (a property taking an image/canvas as background+text instead of colors)? I imagine a lot of special effects (glow, animated blur etc.) to be possible (or CSS but will be more limited for sfx).

    In any case, good job.

    1. Tim Nguyen wrote on

      It’s already possible, see this example: https://github.com/nt1m/theming-api-content-blurring

  4. Not Firefox Anymore wrote on

    What does it matter if it supports more than other browsers. No one is developing for Firefox anymore. The API capabilities are negligibly more powerful, certainly NOWHERE near what proper extensions could do. You have more and more powerful extensions in Chrome and Chromium-based browsers simply because there are more developers there.

    And of course you have Chromium-based browsers that put customization and user experience above everything else, unlike Mozilla.