Dynamic Favicons for WordPress | CSS-Tricks

Typically, a single favicon is used across a whole domain. But there are times you wanna step it up with different favicons depending on context. A website might change the favicon to match the content being viewed. Or a site might allow users to personalize their theme colors, and those preferences are reflected in the favicon. Maybe you’ve seen favicons that attempt to alert the user of some event.
Multiple favicons can technically be managed by hand — Chris has shown us how he uses two different favicons for development and production. But when you reach the scale of dozens or hundreds of variations, it’s time to dynamically generate them.

This was the situation I encountered on a recent WordPress project for a directory of colleges and universities. (I previously wrote about querying nearby locations for the same project.) When viewing a school’s profile, we wanted the favicon to use a school’s colors rather than our default blue, to give it that extra touch.
With over 200 schools in the directory and climbing, we needed to go dynamic. Fortunately, we already had custom meta fields storing data on each school’s visual identity. This included school colors, which were being used in the stylesheet. We just needed a way to apply these custom meta colors to a dynamic favicon.
In this article, I’ll walk you through our approach and some things to watch out for. You can see the results in action by viewing different schools.
Each favicon is a different color in the tabs based on the school that is selected.SVG is key
Thanks to improved browser support for SVG favicons, implementing dynamic favicons is much easier than days past. In contrast to PNG (or the antiquated ICO format), SVG relies on markup to define vector shapes. This makes them lightweight, scaleable, and best of all, receptive to all kinds of fun.
The first step is to create your favicon in SVG format. It doesn’t hurt to also run it through an SVG optimizer to get rid of the cruft afterwards. This is what we used in the school directory:
CodePen Embed Fallback
Hooking into WordPress
Next, we want to add the favicon link markup in the HTML head. How to do this is totally up to you. In the case of WordPress, it could be added it to the header template of a child theme or echo’d through a wp_head() action.
function ca_favicon() {
if ( is_singular( ‘school’ ) ) {
$post_id = get_the_ID();
$color = get_post_meta( $post_id, ‘color’, true );

if ( isset( $color ) ) {
$color = ltrim( $color, ‘#’ ); // remove the hash
echo ‘‘;
add_filter( ‘wp_head’ , ‘ca_favicon’ );
Here we’re checking that the post type is school, and grabbing the school’s color metadata we’ve previously stored using get_post_meta(). If we do have a color, we pass it into favicon.php through the query string.
From PHP to SVG
In a favicon.php file, we start by setting the content type to SVG. Next, we save the color value that’s been passed in, or use the default color if there isn’t one.
Then we echo the large, multiline chunk of SVG markup using PHP’s heredoc syntax (useful for templating). Variables such as $color are expanded when using this syntax.
Finally, we make a couple modifications to the SVG markup. First, classes are assigned to the color-changing elements. Second, a style element is added just inside the SVG element, declaring the appropriate CSS rules and echo-ing the $color.
Instead of a

With that, you’ve got a dynamic favicon working on your site.
Security considerations
Of course, blindly echo-ing URL parameters opens you up to hacks. To mitigate these, we should sanitize all of our inputs.
In this case, we‘re only interested in values that match the 3-digit or 6-digit hex color format. We can include a function like WordPress’s own sanitize_hex_color_no_hash() to ensure only colors are passed in.
function sanitize_hex_color( $color ) {
if ( '' === $color ) {
return '';

// 3 or 6 hex digits, or the empty string.
if ( preg_match( '|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) {
return $color;

function sanitize_hex_color_no_hash( $color ) {
$color = ltrim( $color, '#' );

if ( '' === $color ) {
return '';

return sanitize_hex_color( '#' . $color ) ? $color : null;
You’ll want to add your own checks based on the values you want passed in.
Caching for better performance
Browsers cache SVGs, but this benefit is lost for PHP files by default. This means each time the favicon is loaded, your server’s being hit.
To reduce server strain and improve performance, it’s essential that you explicitly cache this file. You can configure your server, set up a page rule through your CDN, or add a cache control header to the very top of favicon.php like so:
header( 'Cache-Control: public, max-age=604800' ); // 604,800 seconds or 1 week
In our tests, with no caching, our 1.5 KB SVG file took about 300 milliseconds to process on the first load, and about 100 milliseconds on subsequent loads. That’s pretty lousy. But with caching, we brought this down to 25 ms from CDN on first load, and 1 ms from browser cache on later loads — as good as a plain old SVG.
Browser support
If we were done there, this wouldn’t be web development. We still have to talk browser support.
As mentioned before, modern browser support for SVG favicons is solid, and fully-supported in current versions of Chrome, Firefox, and Edge.
SVG favicons have arrived… except in Safari.One caveat is that Firefox requires the attribute type="image/svg+xml" in the favicon declaration for it to work. The other browsers are more forgiving, but it‘s just good practice. You should include sizes="any" while you’re at it. Safari
Safari doesn‘t support SVG favicons as of yet, outside of the mask icon feature intended for pinned tabs. In my experimentation, this was buggy and inconsistent. It didn’t handle complex shapes or colors well, and cached the same icon across the whole domain. Ultimately we decided not to bother and just use a fallback with the default blue fill until Safari improves support.
As solid as SVG favicon support is, it‘s still not 100%. So be sure to add fallbacks. We can set an additional favicon for when SVG icons aren’t supported with the rel="alternative icon" attribute: To make the site even more bulletproof, you can also drop the eternal favicon.ico in your root.
Going further
We took a relatively simple favicon and swapped one color for another. But taking this dynamic approach opens the door to so much more: modifying multiple colors, other properties like position, entirely different shapes, and animations.
For instance, here’s a demo I’ve dubbed Favicoin. It plots cryptocurrency prices in the favicon as a sparkline.
Implementing dynamic favicons like this isn’t limited to WordPress or PHP; whatever your stack, the same principles apply. Heck, you could even achieve this client-side with data URLs and JavaScript… not that I recommend it for production.
But one thing‘s for sure: we’re bound to see creative applications of SVG favicons in the future. Have you seen or created your own dynamic favicons? Do you have any tips or tricks to share?

Typed at

Share your love


  1. Ӏ absolutely love yߋur blog and find the majority of your post’s to be what precisely
    I’m looking for. can you offer guest writers to write ϲontent avaіlable for yoᥙ?

    I wouldn’t mind producing a post or elaborating on a lot of the suЬjects you write
    about here. Again, awesome site!

  2. Thanks to my father who told me concerning this website, this
    blog is really awesome.

  3. tour wayne newton home
    tour wayne newton home

    In order to earn with weblog you be compelled to find a topic you enjoy first.
    Doing this you has the capability find the web pages where veggies place a back one-way link.

  4. Very great post. I just stumbled upon your blog and wished to mention that I have truly enjoyed surfing around
    your weblog posts. After all I’ll be subscribing on your rss feed and I hope you write again soon!

  5. You need to be a part of a contest for one
    of the finest websites on the net. I most certainly will recommend this blog!

  6. สมัคร ufabet
    สมัคร ufabet

    วิธีจัดการเรื่องสมัคร ufabetใน 17 ขั้นตอนง่ายๆ

  7. Hi there, just wanted to mention, I liked this post.

    It was inspiring. Keep on posting!

  8. Great info. Lucky me I discovered your site by accident (stumbleupon).

    I’ve saved as a favorite for later!

  9. Good day! This is my 1st comment here so I just wanted to give a quick shout out and say I genuinely enjoy reading through your posts.
    Can you recommend any other blogs/websites/forums that cover the
    same subjects? Thanks a lot!

  10. https://sites.google.com/site/221ntmk/thuoc-tang-chieu-cao

    I like reading through an article that can make men and women think.
    Also, thanks for allowing for me to comment!

  11. https://cuocsongquanhta.webflow.io/posts/serum-tri-tham-mun

    With havin so much content do you ever run into any problems of plagorism or copyright violation? My blog has a lot
    of unique content I’ve either authored myself or outsourced but
    it appears a lot of it is popping it up all over the web without my permission. Do you know any techniques
    to help protect against content from being ripped off?

    I’d certainly appreciate it.

  12. I’ve been browsing on-line more than 3 hours lately, but I by no means discovered any attention-grabbing article like
    yours. It’s pretty worth sufficient for me.
    Personally, if all website owners and bloggers made
    just right content as you did, the web will likely be much more
    helpful than ever before.

  13. https://sites.google.com/site/221ntmk/serum-tri-mun

    Hey There. I found your blog the use of msn. This is an extremely smartly written article.
    I will make sure to bookmark it and come back to read more of your helpful info.
    Thanks for the post. I will certainly return.

  14. Assorted Team Colors
    Assorted Team Colors

    Good way of telling, and nice paragraph to take information regarding my
    presentation subject, which i am going to present in school.

  15. ดูหนัง

    What’s up mates, its wonderful piece of writing concerning cultureand fully defined,
    keep it up all the time.

Leave a Reply