You are in a maze of twisty little tabs, all alike.

I had this idea for tweaking tabs floating around my head for a while, and last week I finally decided to implement it. The result is Chromatabs, and the UI aspects of it are discussed on today’s labs.mozilla.org posting.

I thought I’d write a bit more here about how it’s implemented, because it’s doing a few interesting things under the hood…

My first proof-of-concept at colorizing tabs was to just set a background color on the tab, and adjust the tab’s opacity to allow the color to show though. This early result was, well, crap:

Screenshot of an early attempt at colorizing tabs
The positioning of the elements that comprise the tab’s internal structure caused some white lines, the opacity affected the text and favicon (they got colorized too), and the background color was visible around the tab’s curved borders. I could probably have worked around the first few issues, but the tab’s curves were an interesting problem… In Firefox 2, the default theme uses chrome images to make the tabs look nice and stylish (curved ends, and a bit of a shiny vertical gradient). You can simulate coloring an image by lowering its opacity and allowing a background color to bleed-though — but if the image already has transparent regions the background color comes through at full-strength.

So, to make a colored tab look nice that approach won’t work. Drat. It would be really easy to colorize a tab with Photoshop, but you can’t do that in the browser. …or can you? The thought struck me that the <canvas> tag, which Firefox supports, gives you a pixel region upon which you can draw things, and it has a compositing mode that allows you to draw only on regions that already have content (ie, that are not transparent). So, that’s what Chromatabs is doing. It dynamically renders new colorized chrome images for each tab. First, it uses the tab’s original chrome image to produce solid-color version via compositing, and then blends it back into the original chrome image by overdrawing with reduced opacity (ie, partial transparency). And it’s all driven by Javascript!

This might also be an interesting technique for themes to use. Currently, if a theme wants to have versions with different colors, the author must create each as separate themes. If the theme could colorize itself at runtime, you’d just need one version of the theme. Plus, the user would be able to pick the exact shade of color they want. Everyone wins.

About Justin Dolske

Mostly harmless.
This entry was posted in Mozilla Labs, PlanetMozilla. Bookmark the permalink.

6 Responses to You are in a maze of twisty little tabs, all alike.

  1. Dao says:

    With the default Windows / Linux theme, it’s all dead easy. The images are semi-transparent, the borders are rounded. You can apply any color. That’s how I did it with Aging Tabs. If you could encourage that the Mac theme gets updated accordingly with 2.0.0.x, that would be great.

  2. Perry Lorier says:

    This also helps with phishing — different site, different colour!

  3. It sounds like you hit something like https://bugzilla.mozilla.org/show_bug.cgi?id=359568. Can you attach a testcase to that bug?

  4. onemen says:

    in allowed Chromatabs to work if tabmix installed replace colorizeTab function in chromatabs.js with this:

    colorizeTab : function (tab) {

    var doc, i, hashstring, hashvalue, node;

    var color = CHROMATABS.computeTabColor(tab);
    if (!color) { return; }

    doc = tab.ownerDocument;

    if (0) {
    tab.style.backgroundColor = color;

    node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-image-left tab-startcap tab-left tab-left-border”);
    node.style.opacity = 0.8;
    node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-middle box-inherit tab-image-middle tab-body”);
    node.style.opacity = 0.8;
    // node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-close-button”);
    // node.style.opacity = 0.8;
    node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-image-right tab-endcap tab-right tab-right-border”);
    node.style.opacity = 0.8;
    }

    if (1) {
    node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-image-left tab-startcap tab-left tab-left-border”);
    CHROMATABS.renderImage(tab, node, color, false);
    node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-middle box-inherit tab-image-middle tab-body”);
    CHROMATABS.renderImage(tab, node, color, false);
    // node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-close-button”);
    // CHROMATABS.renderImage(tab, node, color, false);
    node = doc.getAnonymousElementByAttribute(tab, “class”, “tab-image-right tab-endcap tab-right tab-right-border”);
    CHROMATABS.renderImage(tab, node, color, false);
    }

    },

  5. Simon says:

    Nice. The main problem is that it currently is difficult to tell what the currently selected tab is.

  6. jcelle says:

    This is really a brilliant idea !
    But I could not make it work with Tab Mix Plus, even with the suggested alternative colorizeTab function…
    Has anyone managed to have both working at the same time ?

Comments are closed.