5

Pages offer icons for the browser either via favicon.ico or via various <link> tags like

<link rel='icon' type='image/png' href='icon.png'>

The problem is if the icon is the same color as the browser's tabs then you can't see it.

chrome with custom theme

safari

firefox

There are some semi-obvious solutions

(1) as a user, pick theme whose tabs are not pure white or pure black (and pray the sites don't choose the same color)

(2) as a developer, pick an icon color that's not pure white or pure black (and pray it doesn't match the user's theme) or add a frame to the icon.

But, just curious, as a developer, is there a way to tell the browser to use one icon if the tab is dark and a different icon if the tab is light? SVG CSS for example? Different <link> tags?

PS: Yes, I get that the theme above is gaudy. It's "green for google" vs other profiles I use to separate accounts. That way it's easy for me to know which account each browser window is using. I have 7+ profiles, each with a different and very distinct theme

gman
  • 100,619
  • 31
  • 269
  • 393

2 Answers2

2

You're talking about two possible things:

  1. Browser theme
  2. OS color scheme

Your screenshot depicts the first. Chrome does not expose a user's chosen theme to its Javascript APIs. Nor does any other browser to my knowledge. That's probably a good thing: it would be extremely unique – therefore a way to fingerprint users.

But the second, OS color scheme, is exposed to browsers! This is usually only either one of dark or light. Not every operating system supports color schemes, but the ones that do typically use terms like "Dark Mode" when they talk about it. Apple has some documentation on how to use Dark Mode on macOS, for example.

If an OS supports color schemes, they're exposed to the browser through CSS media queries: @media ( prefers-color-scheme: dark ). It's a feature with >91% global browser support.

The nice thing about it being in CSS is that you can thus serve an SVG for your favico that has that media query in it, and your users will automatically get the right one.

Thomas Steiner popularized this technique in this 2019 post. An example of that:

<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">
  <style>
    path {
      fill: black;
    }

    @media (prefers-color-scheme: dark) {
      path {
        fill: white;
      }
    }
  </style>
  <path d="....." />
</svg>

Back to your post, though: a user could potentially have a dark color scheme, and a (say) gaudy green browser theme, so the favico would possibly look bad either way. No avoiding it.

The easiest solution, then?

Put a background color on your favico. A solution as old as time!

Leland
  • 2,019
  • 17
  • 28
  • did you actually test this and see it works because AFAIK it does not. I tried it before I posted. Note, we're talking about the icon in the tabs not the svg in page. – gman Oct 11 '21 at 21:07
  • 1
    "the icon in the tabs" - yep! That's the favico I'm talking about :) Here's a demo page – note that you'll need to refresh after changing your system's Dark Mode setting! https://dark-mode-favicon.glitch.me/ – Leland Oct 11 '21 at 21:09
  • I guess it fails with themes. It would certainly be possible for the browser to use some heuristic to figure out if the theme is displaying a tab in light or dark colors and choose to use the dark or light version of the icon for that tab. – gman Oct 11 '21 at 21:10
  • 1
    That's the first part of my answer :) "Chrome does not expose a user's chosen theme to its Javascript APIs" – it very intentionally is impossible to detect things like tab color from inside the browser! Javascript has no way of knowing things about the surrounding UI. – Leland Oct 11 '21 at 21:13
  • 1
    So sadly *no*, no heuristic exists that Javascript, CSS, or anything else could use to dynamically change a page off of the application's styles. Chrome Extensions *can* send JS to a page, though, so for completeness's sake you could write a very fancy theme that talks to specific sites to say "hey, switch the favico if this theme in installed." That would only work for sites that you control – you'd need to write the Javascript on both sides. – Leland Oct 11 '21 at 21:15
  • The browser has to render the tab. It can certainly look at what colors are being rendered for its heuristic. – gman Oct 11 '21 at 21:16
  • 1
    Definitely true. So more precisely: no APIs are exposed that would allow you to build this, as you are a third party developer. – Leland Oct 11 '21 at 21:24
  • I didn't ask about APIs – gman Oct 11 '21 at 21:25
0

This appears to be non-standard? as I have not yet found docs but I found a site doing this

<link rel="shortcut icon" href="favicon_white.ico" 
      media="(prefers-color-scheme: dark)"/>
<link rel="shortcut icon" href="favicon.ico"
      media="(prefers-color-scheme: light)" />

And checking it is picking the correct one in Chrome, at least related to the user's preferred color scheme.

Certainly the media attribute applies to rel="stylesheet" so maybe it applies to any <link>?

gman
  • 100,619
  • 31
  • 269
  • 393
  • It is standard: https://html.spec.whatwg.org/multipage/semantics.html#processing-the-media-attribute:attr-link-media and it applies to all link types, even though it has a real effect only on external resources. – Kaiido Nov 10 '21 at 07:06