16

Is there a way to set a different favicon for browsers that support theme-color, either via the meta tag or manifest.json? I have a jet black theme bar, but a mostly-black favicon for use on desktop browsers. I'd like to have an alternate white favicon for mobile browsers, but I don't want to make the assumption that mobile browser === theme-color support, as that's not always going to be the case.

Desktop favicon example:

Desktop favicon

Mobile favicon example: Mobile favicon

richardwestenra
  • 948
  • 2
  • 10
  • 16

2 Answers2

12

The browser's theme is accessible through the prefers-color-scheme media query. Unfortunately, as the favicon is not a page element, you cannot use the media query in a CSS file to, say, switch between two images.

The solution is to combine prefers-color-scheme with SVG, which can embed CSS. Declare an SVG favicon:

<link rel="icon" href="my_icon.svg">

And use the media query in the SVG itself:

<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <style>
    circle {
      fill: yellow;
      stroke: black;
      stroke-width: 3px;
    }
    @media (prefers-color-scheme: dark) {
      circle {
        fill: black;
        stroke: yellow;
      }
    }
  </style>
  <circle cx="50" cy="50" r="47"/>
</svg>

Source at tomoyac.com

SVG favicon is still an advanced feature. It is already supported by Firefox and by Chrome, but other browsers do not support it yet.

Michael
  • 8,362
  • 6
  • 61
  • 88
philippe_b
  • 38,730
  • 7
  • 57
  • 59
  • 6
    How about desktop browsers with dark theme? i.e.: dark mode in Firefox Developer, Chrome Canary, etc? – gedijedi Feb 15 '19 at 13:38
  • 2
    You mean having two icons, one for light themes and one for dark themes, and the right one is picked depending on the theme in use? – philippe_b Feb 15 '19 at 19:14
  • Yes, provided favicon is very dark, it would be nice to set it to a light version on dark themes, and vice versa. Looks like the only dark themed browser where logo appears semi-decently is Safari on Mojave with dark theme enabled. It surrounds the icon with a light grey rectangle. It doesn't look that well, but it works. – gedijedi Feb 18 '19 at 11:53
  • 1
    I see. This feature cannot be supported with plain HTML, which is the kind of material you expect when creating a favicon for a regular website. Having a mechanism based on user agent would not be enough, as themes are dynamic (ie. you cannot assume Chrome == light). So this would require JS. Why not? But that would be an extra feature which is out of scope at the moment. – philippe_b Feb 20 '19 at 11:00
  • @gedijedi A new trick based on SVG and prefers-color-scheme media query is changing the deal. I have rewritten the answer. – philippe_b Dec 13 '19 at 07:48
  • @philippe_b Can you revert the change and add a new answer with the new content? I feel odd about an edit that completely rewrites the approach. Neat tip, btw. I intend to upvote. – Michael Dec 16 '19 at 18:58
  • @Michael I understand your concern. The thing is: my previous answer was completely deprecated. It was a poor workaround and was recently downvoted (this is why I reviewed it and realized it needed to be rewritten). I would rather delete the previous answer than leaving it as it was for historical reasons, really. When I rewrote it, the answer had a score of zero, which makes me feel that the operation is somehow okay, as the new content is not affected by the previous one in terms of popularity, if you see what I mean. – philippe_b Dec 17 '19 at 11:44
  • 1
    Okay. I'm not going to make a big deal of it. You may want to add a caveat that this [only works](https://caniuse.com/#feat=link-icon-svg) in FF for now. (With Chrome expected [in v80](https://www.chromestatus.com/features/5180316371124224) in February.) – Michael Dec 17 '19 at 16:37
  • @Michael That's right! I've just added a note, thank you for the tip and links. – philippe_b Dec 20 '19 at 13:07
  • I didn't get the media query to work in Chrome v88. It uses the svg, but the media query does not work. It works fine in Firefox and Opera. Vivaldi seems to just use favicon.ico located on root, and totally ignoring any `` references. – awe Feb 02 '21 at 10:00
0

Hi @richardwestenra,

With PHP placed within the HTML part of a header.php file, to the best of my understanding, this could be done.

First I would assure the $_SERVER['HTTP_USER_AGENT'] is not null, and once it passed that , I would have a second IF for a word in the user_agent: ( strpos ($_SERVER['HTTP_SEC_CH_UA'], 'Google' ).

The below code is how I'm going to implement it, hoping for it to work:

<?php if($_SERVER['HTTP_USER_AGENT'] != null) : ?>

    <?php if (strlen(strstr($_SERVER['HTTP_USER_AGENT'],"Googlebot")) > 0 ) : ?> 
        <meta property="og:image" itemprop="image" content="https://currenge.com/wp-content/uploads/2019/10/favicon_512_512_png.png" />
        <meta property="og:image:width" content="512" />
        <meta property="og:image:height" content="512" />
        <meta property="og:image:type" content="image/png" />
        <meta property="og:image:secure_url" itemprop="image" content="https://currenge.com/wp-content/uploads/2019/10/favicon_512_512_png.png" />
        <meta property="og:image:secure_url:width" content="512" />
        <meta property="og:image:secure_url:height" content="512" />
        <meta property="og:image:secure_url:type" content="image/png" />
    
    <?php else : ?> 
        <meta property="og:image" itemprop="image" content="https://currenge.com/wp-content/uploads/2019/10/favicon_1200_628_png.png" />
        <meta property="og:image:width" content="1200" />
        <meta property="og:image:height" content="628" />
        <meta property="og:image:type" content="image/png" />
        <meta property="og:image:secure_url" itemprop="image" content="https://currenge.com/wp-content/uploads/2019/10/favicon_1200_628_png.png" />
        <meta property="og:image:secure_url:width" content="1200" />
        <meta property="og:image:secure_url:height" content="628" />    
        <meta property="og:image:secure_url:type" content="image/png" />
    
    <?php endif; ?> 
    
<?php endif; ?> 

May I ask , what would you guys say regarding the above possible solution?

ziegel
  • 9
  • 2