Set favicons with JavaScript

A super simple approach for JavaScript newcomers


Spemer's favicon

When you publish a website, you usually need to set a favicon-and in practice, a modern site ships more than one: a favicon.ico fallback, a high-resolution SVG favicon, an Apple touch icon for iOS home screens, and Android shortcut icons for PWAs. If your site has lots of HTML files, even a tiny change to any of these can become tedious. In this article I'll show you how to inject favicon <link> tags into the <head> with JavaScript, so one script handles every page-without touching every HTML file.

The basic way to set a favicon in HTML

<link rel="shortcut icon" href="../images/favicon.png" />

We'll port this plain HTML into JavaScript that injects a <link rel="icon"> tag into <head> at runtime. It's pretty simple if you only need one favicon for the browser, no mobile or Apple touch icons. Note: rel="shortcut icon" is a legacy keyword kept for old browsers-modern browsers only need rel="icon", but leaving both costs nothing.

In JavaScript

function setFavicons(favImg){
    let headTitle = document.querySelector('head');
    let setFavicon = document.createElement('link');
    setFavicon.setAttribute('rel','shortcut icon');
    setFavicon.setAttribute('href',favImg);
    headTitle.appendChild(setFavicon);
}
setFavicons('https://spemer.com/img/favicon/favicon.png');

You've now set the favicon without writing per-file HTML. You can extend this approach to set other favicons or shortcut icons using JavaScript arrays.

Add an array for favicons

let favIcons = [
    { rel: 'apple-touch-icon' },
    { rel: 'apple-touch-startup-image' },
    { rel: 'shortcut icon' }
]

We'll iterate over this array with a for loop (or forEach/for...of in modern JavaScript) and apply each entry to the code above.

function setFavicons(favImg){
    let headTitle = document.querySelector('head');
    
    let favIcons = [
        { rel: 'apple-touch-icon' },
        { rel: 'apple-touch-startup-image' },
        { rel: 'shortcut icon' }
    ]
    
    favIcons.forEach(function(favIcon){
        let setFavicon = document.createElement('link');
        setFavicon.setAttribute('rel', favIcon.rel);
        setFavicon.setAttribute('href', favImg);
        headTitle.appendChild(setFavicon);
    });
}
setFavicons('https://spemer.com/img/favicon/favicon.png');

That's it. The same pattern handles Android shortcut icons and Apple touch icons for iPhone and iPad.

Set another array and function

function setAppleFavicons(){
    let headTitle = document.querySelector('head');
    
    let appleFavIcons = [
        { sizes:'152x152', href: '../touch-icon-ipad.png' },
        { sizes:'180x180', href: '../touch-icon-iphone-retina.png' },
        { sizes:'167x167', href: '../touch-icon-ipad-retina.png' }
    ]
    
    appleFavIcons.forEach(function(appleFavIcon){
        let setAFavicon= document.createElement('link');
        setAFavicon.setAttribute('rel','apple-touch-icon');
        setAFavicon.setAttribute('sizes',appleFavIcon.sizes);
        setAFavicon.setAttribute('href',appleFavIcon.href);
        headTitle.appendChild(setAFavicon);
    });
}
setAppleFavicons();

The snippet above sets up touch icons for iOS.

My .js code How I apply favicons on this website

What's next?

You can also set Android shortcut icons via JavaScript instead of HTML:

<link rel="icon" href="../favicon-16.png" sizes="16x16" type="../favicon-16.png" />
<link rel="icon" href="../favicon-32.png" sizes="32x32" type="../favicon-32.png" />
<link rel="icon" href="../favicon-48.png" sizes="48x48" type="../favicon-48.png" />
<link rel="icon" href="../favicon-62.png" sizes="62x62" type="../favicon-62.png" />
<link rel="icon" href="../favicon-192.png" sizes="192x192" type="../favicon-192.png" />

You no longer need to worry about updating every HTML file for small favicon changes-editing one or two lines of JavaScript applies the change everywhere.

Going further, you can use a dynamic parameter in the function to update the favicon dynamically (e.g., a notification badge, a build-status indicator, or a "live" dot).

A few modern tips

A quick checklist for favicons in 2025-and-beyond, beyond the classic .ico:

  • Always keep /favicon.ico at the site root. Browsers request it automatically as a fallback even if your <link> tag is missing or fails to load.
  • Ship an SVG favicon. One crisp file for every size: <link rel="icon" type="image/svg+xml" href="/favicon.svg">. Supported in all modern browsers.
  • Dark-mode favicons. Inside the SVG, use @media (prefers-color-scheme: dark) to swap colors automatically.
  • iOS home screen. A single 180×180 apple-touch-icon.png covers iPhone and iPad.
  • Android / PWA. Provide icons via manifest.json (icons[] with 192×192 and 512×512) instead of individual <link> tags-Chrome and the install prompt read from the manifest.
  • Cache busting. When you ship a new favicon, append a version query (/favicon.svg?v=2) so browsers-and Google's search results-pick up the new image quickly.

You can check the live site. Thanks for reading!

Title : Set favicons with JavaScript
Date : January 3, 2018
Writer : Hyouk Seo (Spemer)