Icon sizes with SVG

Hi all. I’m brand new to Extension development and I’m trying to get some of the foundational steps clarified.

What is the canonical way to set an Extension icon?

I want to use two SVG’s as icon - one each for light/dark theme. But according to the specifications there are multiple ways to set an icon and while I feel I’ve tried a lot of ways, the icon does not always show up.
I found this old thread but frankly, it just confuses me even more.

My icon shows up in the Extension list page but not in the Extensions pop-out, as shown in the screenshots below:

In my manifest.json I have defined the icon as many places as I’ve seen the various documentation, using "manifest_version": 3.

{
	"manifest_version": 3,
	"icons": {
		"16": "icons/icon_dark.svg",
		"32": "icons/icon_dark.svg",
		"48": "icons/icon_dark.svg",
		"64": "icons/icon_dark.svg",
		"96": "icons/icon_dark.svg",
		"128": "icons/icon_dark.svg"
	},
	"action": {
		"browser_style": true,
		"default_icon": {
			"16": "icons/icon_dark.svg",
			"32": "icons/icon_dark.svg",
			"48": "icons/icon_dark.svg",
			"64": "icons/icon_dark.svg",
			"96": "icons/icon_dark.svg",
			"128": "icons/icon_dark.svg"
		},
		"theme_icons": [{
			"dark": "icon_dark.svg",
			"light": "icon_light.svg",
			"size": 64
		}, {
			"dark": "icon_dark.svg",
			"light": "icon_light.svg",
			"size": 48
		}, {
			"dark": "icon_dark.svg",
			"light": "icon_light.svg",
			"size": 32
		}, {
			"dark": "icon_dark.svg",
			"light": "icon_light.svg",
			"size": 16
		}]
	}
}

JSON is simplified for brevity.

My SVG icon has a viewBox that correspond to the coordinate system used in the SVG and I have experimented with setting the width/height attributes but they do not seem to make any difference. The only difference between icon_dark.svg and icon_light.svg is the fill attribute color on the two paths in the SVG.

What is the canonical way to set an Extension icon?

I am thinking that it is way overkill to have this many ways to set an icon but I also understand how tech debt works and that it is probably for backwards compatibility.

Thanks in advance for clarification!

Cheers, Jon

Firefox: 109.0b9 (64-bit)

1 Like

I made a mistake with the paths for the action -> theme_icons, which was missing the path to my icons folder.
From that I can deduce that theme_icons is used for the Extension pop-out and that either icons or action -> default_icon is used on the about:debugging page. For the about:addons page, it seems that action -> theme_icons is used.

I only set the top-level “icons” in my manifest.json. And it seems to cover all mentioned places (the new extension pop-out, about:debugging and about:addons).

My guess is that the other places you can define icons are only optionally to override the icons set in the top-level “icons”.

I don’t use SVG, but I assume that is irrelevant for where to put them in manifest. I think the sizes you choose to offer, is just to make scaling nicer. If no size fits exactly the way Firefox wants to display it, I assume Firefox just chooses the closest (larger?) and scale it accordingly. I define my icons like this:

  "icons": {
    "24": "icons/xIFr-24.png",
    "32": "icons/xIFr-32.png",
    "48": "icons/xIFr-48.png",
    "64": "icons/xIFr-64.png",
    "96": "icons/xIFr-96.png",
    "128": "icons/xIFr-128.png",
    "256": "icons/xIFr-256.png",
    "512": "icons/xIFr-512.png"
  },

So if you use an SVG icon, you would ideally think you only needed to set one “one size fits all” icon in your manifest. However it apparently ain’t that simple in reality:

EDIT: Sorry, I missed your point about dark/light theme… As I understand it, it is only action icons that can be overridden by “themed icons”. And you do that using action->theme_icons. “Action icons” are icons placed in browser toolbar including the new pop-out.
Originally missing your point about dark/light theme, I’m not sure I was able to bring much clarification (I’m not sure about further details either)?

After experimenting a little, I have removed the "action": { "default_icon": since they appear to do nothing.

The root "icons": { seems to be used for the Add-ons Manager page (about:addons) and the Extension page (about:debugging#/runtime/this-firefox), and does not have any way to define different icons based on light/dark theme.

@stig according to https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action#choosing_icon_sizes, then Firefox will “will pick the smallest icon specified that’s bigger than the ideal size.”.

If Firefox can’t find an exact match for the size it wants, then it will pick the smallest icon specified that’s bigger than the ideal size. If all icons are smaller than the ideal size, it will pick the biggest icon specified.

To clarify my two icons, I have renamed them to black/white - where black has the fill color set to #000 and white to #fff.

"icons": {
	"16": "icons/icon-black.svg",
	"32": "icons/icon-black.svg"
},
"action": {
	"theme_icons": [{
		"dark": "icons/icon-black.svg",
		"light": "icons/icon-white.svg",
		"size": 64
	}, {
		"dark": "icons/icon-black.svg",
		"light": "icons/icon-white.svg",
		"size": 48
	}, {
		"dark": "icons/icon-black.svg",
		"light": "icons/icon-white.svg",
		"size": 32
	}, {
		"dark": "icons/icon-black.svg",
		"light": "icons/icon-white.svg",
		"size": 16
	}],

The size attribute is nonsense for SVG but as you, @stig, point out, it might still be necessary for historical reasons. I will need to experiment a little more with that. See below:

@NilkasG says in How to correctly design/color icon to be visible across themes?, that one could use the "1" key and indeed that appears to work in Firefox 109.0b9.

So it appears that setting the “Website appearance” to light/dark does not influence which icon is being used while choosing a dark/light add-on theme does.

Below is screen shots where I have chosen the Light Theme in about:addons and “Website appearance” set to Light:

Below is screen shots where I have chosen the Light Theme in about:addons and “Website appearance” set to Dark:

Below is screen shots where I have chosen the Dark Theme in about:addons and “Website appearance” set to Light:

Below is screen shots where I have chosen the Dark Theme in about:addons and “Website appearance” set to Dark:

Here is the relevant part of my manifest.json:

"icons": {
	"1": "icons/icon-black.svg"
},
"action": {
	"theme_icons": [{
		"dark": "icons/icon-black.svg",
		"light": "icons/icon-white.svg",
		"size": 1
	}],

My Conclusion

The icon used for the Extension on the about:addons page is defined in "icons": { and it is only possible to define icons with varying sizes. Since I use SVG, I can use "1" as key and scaling works fine. The same icon will always be used no matter what theme is used.

The icon used in the pop-out is defined in "action": { "theme_icons": [{ and you can specify different icons based on size and dark/light theme. The icon is not chosen based on “Website appearance” or OS appearance (the Automatic option use the OS level appearance preference). In Firefox, the icon is chosen solely on the browser theme (I assume the browser themes has meta data that says weather it is a light or dark theme).

While it is nice that one does not have to redundantly define difference sizes when using vector graphic, the consideration that went into the currently implementation is still less than desirable. Never use a white icon in the "icons: [{" section because if the browser theme is light, the icon will disappear on the white background. A black icon is very difficult to see on dark background but at least it is still visible.
In my opinion, there should only be the "icons" property but with the option to define both light and dark themed icons.

It also seems that the extension documentation is outdated. E.g. https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/icons#svg says:

Even though you can use one file, you still need to specify various size of the icon in your manifest.

That is simply not true as I have just shown. You can use "1" as size key and it will work fine - apparently since at least April 2018.

If anything, there is too much documentation for Extensions. What is needed, is way less, way more concise and up to date information.

I hope this helps everyone as confused as me :slight_smile:

PS. thank you for reading through all of this @stig

EDIT: I found a discussion on the WebExtension API github account about this, where @carlosjeurissen talk about this and how it can be improved for Manifest v4: https://github.com/w3c/webextensions/issues/229#issuecomment-1177729868

1 Like