Favicons

Favicons are a PITA but hopefully if you follow these clear and concise instructions you will be faviconing like a mofo in no time.


https://realfavicongenerator.net/ is your best friend. Whoever maintains it does a good job of keeping abreast of the current best practices for new devices and adjusts it's output accordingly. All you have to do is upload an image of at least 260px X 260px and it will output a folder of specifically sized images you can use. For best results I recommend using an svg so it will scale nicely.

After uploading you will be prompted to choose some options for iOS, Android, Windows, and Safari for Mac. If you plan on using the code generated by realfavicongenerator in a static web page like Kalastatic et. al. then go a head and fill out these options. If, however you are generating favicons for Drupal then you can largely ignore this because we are going to be using php to generate all the link and meta tags which I will get to further down. There is also an option at the bottom of the page to supply a path to where the icons will live. It's recommended that you place them in the root of your site but if you choose you can supply a custom path. Again this only applies if you're using these in a static situation. When it comes to Drupal we will supply a custom path in code.

Click the 'generate' button and you will then be prompted to download your favicon package. You will also be presented with some html you can copy/paste into your <head> tag if you are building a static site.


Once you have downloaded your icons, place them in the root of the site, or in your custom path if you specified one and you should be GTG. Note that favicon browser cache is notoriously sticky so if you find nothing is changing, try using a different browser or forcefully clearing your cache. If your site is live somewhere you can use https://realfavicongenerator.net/favicon_checker to check.


K but wat abut teh Derpals

Techincally we could paste the link/meta tags that https://realfavicongenerator.net gave us into the page template and it SHOULD work. However, Drupal is doing it's own thing with favicons so it's better to implement things on the back end to ensure we override what Drupal is doing. This also has the added benefit of other code being able to adjust things before we hit the template which can help with extensibility sometimes.


First thing we want to do is unset Drupal's core favicon functionality. Sometimes Drupal's favicon ends up printing out after our custom ones, dependant on where in the process our page_attachments_alter() gets called. Sometimes this gives us unpredictable results. This code removes it altogether so there's no more funny business:

/**
 * Implements hook_page_attachments_alter().
 */
function MODULE_OR_THEME_page_attachments_alter(array &$page) {
  // Unset Drupals default favicon.
  $links = $page['#attached']['html_head_link'];
  foreach ($links as $key => $link) {
    if ($link[0]['href'] == '/core/misc/favicon.ico') {
      unset($page['#attached']['html_head_link'][$key]);
    }
  }


  // Handle custom favicons.
  _favicon_head_tags($page);
}


We then call a custom function _favicon_head_tags() and pass it the page array. You can call this function whatever you want or stick it's code directly into the page_attachments_alter() but it's quite long as you will see so this keeps it clean:

/**
 * Add tags to the header, mainly for favicons.
 */
function _favicon_add_head_tags(array &$page) {
  $apple_touch_icon = [
    '#type' => 'html_tag',
    '#tag' => 'link',
    '#attributes' => [
      'href' => '/kalastatic/images/favicon/apple-touch-icon.png',
      'rel' => 'apple-touch-icon',
      'sizes' => '180x180',
    ],
  ];
  $page['#attached']['html_head'][] = [$apple_touch_icon, 'apple_touch_icon'];

  $favicon_32x32 = [
    '#type' => 'html_tag',
    '#tag' => 'link',
    '#attributes' => [
      'href' => '/kalastatic/images/favicon/favicon-32x32.png',
      'rel' => 'icon',
      'sizes' => '32x32',
      'type' => 'image/png',
    ],
  ];
  $page['#attached']['html_head'][] = [$favicon_32x32, 'favicon_32x32'];

  $favicon_16x16 = [
    '#type' => 'html_tag',
    '#tag' => 'link',
    '#attributes' => [
      'href' => '/kalastatic/images/favicon/favicon-16x16.png',
      'rel' => 'icon',
      'sizes' => '16x16',
      'type' => 'image/png',
    ],
  ];
  $page['#attached']['html_head'][] = [$favicon_16x16, 'favicon_16x16'];

  $manifest = [
    '#type' => 'html_tag',
    '#tag' => 'link',
    '#attributes' => [
      'href' => '/kalastatic/images/favicon/manifest.json',
      'rel' => 'manifest',
    ],
  ];
  $page['#attached']['html_head'][] = [$manifest, 'manifest'];

  $mask_icon = [
    '#type' => 'html_tag',
    '#tag' => 'link',
    '#attributes' => [
      'href' => '/kalastatic/images/favicon/safari-pinned-tab.svg',
      'rel' => 'mask-icon',
      'color' => '#058488',
    ],
  ];
  $page['#attached']['html_head'][] = [$mask_icon, 'mask-icon'];

  $shortcut_icon = [
    '#type' => 'html_tag',
    '#tag' => 'link',
    '#attributes' => [
      'href' => '/kalastatic/images/favicon/favicon.ico',
      'rel' => 'shortcut icon',
    ],
  ];
  $page['#attached']['html_head'][] = [$shortcut_icon, 'shortcut icon'];

  $msapplication_config = [
    '#type' => 'html_tag',
    '#tag' => 'meta',
    '#attributes' => [
      'href' => '/kalastatic/images/favicon/browserconfig.xml',
      'name' => 'msapplication-config',
    ],
  ];
  $page['#attached']['html_head'][] = [$msapplication_config, 'msapplication_config'];

  $theme_color = [
    '#type' => 'html_tag',
    '#tag' => 'meta',
    '#attributes' => [
      'content' => '#058488',
      'name' => 'theme-color',
    ],
  ];
  $page['#attached']['html_head'][] = [$theme_color, 'theme_color'];
}



A few things to note: 

  • the href of each tag needs to point to the correct location. The example has the favicons inside Kalastatic but your site might differ.
  • There are a few color values that are set—one for Windows Metro tiles and one is for Safari pinned tabs/TouchBar. You should set this to the primary brand color of your site. 

As you can see this is quite verbose but it maps correctly to the output of favicons from https://realfavicongenerator.net/ as of 15th September 2017. At any point this could change—new devices get released, OSs get updated and the requirements of favicons will change. It's helpful to know this could be out of date but please let Josh know if it is.


https://realfavicongenerator.net/ also has a node module that lets us automatically generate favicons from a source file on build. I'm going to look at integrating this into Kalastatic at some point so and hopefully make this page redundant.