Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I set an SVG element to my page's favicon?

Tags:

favicon

svg

I have an SVG element on my page. I want to use it as the page's favicon. How do I do this in JavaScript?

like image 714
Stuart P. Bentley Avatar asked Nov 27 '13 02:11

Stuart P. Bentley


1 Answers

Doing this is astoundingly convoluted. You can see my solution in action here: the methodology is described below (getting the HTML elements, by ID or otherwise, is left as an exercise for the reader).

In the HTML

  1. Make sure your SVG element includes the attribute xmlns="http://www.w3.org/2000/svg", as you're going to need to take the source of the element as its own file, and the XMLNS declaration is required for standalone SVG files. (Also note that this means your SVG will need to be self-contained and can't refer to elements in its parent document with something like <use>.)
  2. Optionally, wrap the element in a <div> or <span>, which you may use to get the content of the <svg> element using .innerHTML. (Neither the innerHTML nor the outerHTML attributes are present on SVG elements in the current HTML standard.)
  3. Include a <link rel="icon"> in your page's <head>.

In JavaScript

  1. Get the source of the SVG element you want to set as your favicon by getting the innerHTML attribute of the HTML element you've wrapped it in, or by calling new XMLSerializer().serializeToString() on the SVG element.
  2. Create a DataURL for this element as a document by prepending the string "data:image/svg+xml," to the source. (If most browsers supported SVGs for favicons, we'd be done here, but since, at time of writing, they don't, we must go deeper.)
  3. Create an <img> element that you'll be routing the image through, add an event listener to it for the load event that will draw the image once control returns to the event loop (as spec-compliant browsers won't let you read the image synchronously - see this crbug), and set the DataURL of your SVG source as its src attribute. (The steps between this and step 8 can happen either in sync now, or as part of the listener callback; they just need to happen before you draw the image.)
  4. Decide what resolution you want to render your favicon to - My examples will use 64x64, for compatibility with high-DPI (Retina and Super Retina) displays.
  5. Create a <canvas> element (heretofore referred to as canvasElement) and set its dimensions (by setting canvasElement.width = 64 and canvasElement.height = 64).
  6. Create a drawing context for the canvas using canvasElement.getContext('2d') (heretofore referred to as ctx).
  7. If you're re-using a canvas you've created beforehand, set ctx.globalCompositeOperation = "copy", or clear it with ctx.clearRect(0, 0, 64, 64).
  8. Somewhere in the execution sequence following from the load listener you added to the <img> element you created in step 3, draw the image onto the canvas using ctx.drawImage(svgImg, 0, 0, 64, 64) (where svgImg is the <img> element you set the src to the SVG DataURL).
  9. Create a PNG DataURL from the canvas using canvasElement.toDataURL(), and set that to the href attribute of the <link rel="icon"> element in your HTML.
like image 159
Stuart P. Bentley Avatar answered Oct 07 '22 21:10

Stuart P. Bentley