Use of CSS <content: url("filename.png")> in an addon

I have an addon that uses some CSS to insert a lock symbol via background.js via unicode and this works fine.

content: “:lock:”;

I can also change this to use a live URL for a different lock and this also works fine, but I would prefer not to rely on a live link.

content: url(URL to a Lock);

I was wondering if I can add a PNG file as part of the addon and just reference it.

content: url(“lock.png”);

When I do this the graphic never displays. The usage of url() seems to indicate this should work, but I am wondering if within the addon context it shouldn’t.

Thanks in advance for any ideas or feedback.


Few things to note (and try):

  1. If you want to display your PNG on normal web-pages, you should define it in your manifest file:
  "web_accessible_resources": [
  1. you need to use full path:
// returns: moz-extension://45f6509e-5d13-4cbe-8a4c-7da36439910f/lock.png
  1. alternatively you can encode your PNG to base64 string and then display is as dataURL. But this may be less performant, so I would recommend using methods above.

Thank you @juraj.masiar, this definitely gets this issue further along. I made the change to the manfiest, got the runtime URL, and used that URL directly and it worked!

Obviously, the UUID of the extension will change per install so passing the direct URL will not work. I figured getting the URL at runtime and passing it to “content: url()” would work, but it doesn’t.

var myURL = browser.runtime.getURL(’/lock.png’);
console.log("Lock Url = " + myURL); /* Gives proper URL */

content: url(myURL);


content: url(browser.runtime.getURL(’/lock.png’));

Yes, I’ve been thinking about that as well.
They are mentioning it in the docs (that it will work in Chrome because the ID is fixed there).

But I remember reading something about this…
I thinks this is it:

This part:


The extension’s internally-generated UUID. You might use this string to construct URLs for resources inside the extension. Even unlocalized extensions can use this message.

So in your case something like this should work (I think :slight_smile: ):

content: url(moz-extension://__MSG_@@extension_id__/lock.png);
1 Like

@juraj.masiar thanks again for the insight and guidance. I tried out some new ideas based on the MDN Web Docs, but was not able to get it to work.

The additional complexity with this is that this CSS information is getting passed over to another Firefox addon. I am basically passing some custom CSS via a sendMessage, so unless the i18n is resolved to a fully qualified URL text BEFORE sending the message, I doubt the other addon would be able to use it. This might make sense as to why the fully qualified URL with the UUID in the string works, but the i18n version doesn’t.

I may have to stick with the Unicode solution (limited choices) or an external URL (would hate to hit someone’s posted PNG or figure somewhere to host it myself). I really thought stuffing the proper URL at runtime into a variable and passing it into url() would have worked. [“myURL” option below]

browser.runtime.sendMessage(ID, {
style: `
   conditions item-to-style::after {
        /* Works */
        /* content: url(""); */
        /* content: url(""); */
        /* content: url("moz-extension://32b76189-c6cf-43d0-af5c-e10691134da7/lock.png"); */

        /* Doesn't work */
        /* content: url(myURL); */
        /* content: url(browser.runtime.getURL('/lock.png')); */
        /* content: url(moz-extension://__MSG_@@extension_id__/lock.png); */
        /* content: url(lock.png); */
        /* content: url('/lock.png'); */

        content: url("");

OK so I’m pretty sure you can’t load another addon resource in your addon :slight_smile:. Even if you have full correct URL.

But you can still send the whole PNG there as Blob.
First load the blob:

const blob = await (await fetch('/lock.png')).blob();

Then send it to the other addon (this will work only in Firefox, Chrome cannot serialize blobs).
Then load the blob:

const lockIconURL = URL.createObjectURL(blob);

Then use the URL - now to get it to the CSS will be tricky, you will probably have to modify CSS from javascript.

… but you can “reference” a resource if it is exposed outside of the addon. Passing content: url(“moz-extension://32b76189-c6cf-43d0-af5c-e10691134da7/lock.png”); to the other addon works fine as this URL will simply load on the URL bar by itself and the other addon doesn’t have to know where it is located or do anything special with it.

I think I had also tried (may try again) to encode the PNG as base64 and pass that into the other addon as the content. [I don’t own the other addon to make any changes to how this is handled]

Interesting, you are right, the content seems to be accessible across addons once it’s exposed through manifest/web_accessible_resources.

So now what’s the issue?
You can either use full URL to your PNG or you can use Data URL (the base64 string with “data:” scheme):

1 Like

Thank you @juraj.masiar for your time and your feedback on this issue.

Given using the hard-coded URL won’t work because of the UUID, I was able to get it work be encoding and passing the PNG via base64. (Yeah!)

One other quick question from a passing thought … is there a way to specify the UUID of an addon via the manifest.json such that each install of an addon would have the same UUID? (If this was possible, I could go back to using the URL of the PNG in the addon)

No, that is not possible for privacy reasons. However if this is a string that you can generate I really do not understand why runtime.getURL is not working for you.