Browsers Demand a Favicon

We enjoy experimenting with lightweight html5 programs served locally as static pages. Unless otherwise directed, browsers insist on requesting favicon.ico files. Tired of ignoring this noise, we explore giving the browsers what they want.

https://wiki.dbbs.co/assets/pages/js-snippet-template/esm.html HEIGHT 310 Refresh this frame to generate more random icons. Click to copy a <link> tag to the clipboard.

Those who don't care about Safari can also use an SVG for their favicon. Perhaps this:

/* (hiding this html inside a javascript comment) <link rel="icon" type="image/svg+xml" href='data:image/svg+xml,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 10 10"><circle r="5" fill="lightblue"></circle></svg>'> */

.

// Code that does it. export async function emit(el) { const icons = document.createElement('p') icons.setAttribute('id', 'icons') icons.style.display = 'block' const check = document.createElement('textarea') Object.assign(check.style, { display: 'block', boxSizing: 'border-box', width: '100%', height: '4rem', margin: '5px 0' }) check.setAttribute('id', 'check') const refresh = document.createElement('button') refresh.setAttribute('id', 'refresh') refresh.innerText = 'Generate New Icons' for (let i=0; i<18; i++) { icons.appendChild(randomFavicon()) } el.appendChild(icons) el.appendChild(refresh) el.appendChild(check) } export async function bind(el) { window.icons.onclick = copyToClipboard window.refresh.onclick = () => location.reload() }

copyToClipboard() encodes the trick that gives the browser a favicon. A <link rel="icon"> tag is generated with a data url and copied to the clipboard.

The interested author can paste this <link> into their script, for example inside the <head> tag, to meet the browsers' need for a favicon.

function copyToClipboard(event) { const {target} = event event.preventDefault() if (target.tagName == "CANVAS") { const html = `<link rel="icon" type="image/png" href="${target.toDataURL("image/png")}">` if (navigator.clipboard) { navigator.clipboard.writeText(html) window.check.value = `Copied to clipboard. You can paste into this text area to double-check.` } else { window.check.value = `<!-- Clipboard is not available in http. You'll have to copy the old fashioned way. --> ${html}` } } }

For more info about clipboard.writeText(), see mdn

Note: clipboard is only available in https. Therefore we have explicitly specified an HTTPS url for the frame above.

Our randomFavicon() uses <canvas> to generate a circle with a gradient similar to wiki flags. We choose circles for our script favicons so they can be easily distinguished from wikis when the tabs get crowded.

function randomFavicon() { const rads = () => `${Math.random()*Math.PI*2}rad` const canvas = document.createElement('canvas') canvas.width = canvas.height = 64 const ctx = canvas.getContext('2d') const tilt = Math.round(Math.random()*64) const gradient = ctx.createLinearGradient( tilt,0, (64-tilt),64) const a = 50 - Math.round(45*Math.random()*Math.random()) const b = 50 + Math.round(45*Math.random()*Math.random()) gradient .addColorStop(0, `hsl(${rads()} 78% ${a}%)`) gradient .addColorStop(1, `hsl(${rads()} 78% ${b}%)`) ctx.fillStyle = gradient ctx.arc(32, 32, 32, 0, Math.PI*2, true) ctx.fill() return canvas }

For more info about createLinearGradient(), see mdn

For more info about hsl(), see mdn

For more about Favicon, see wikipedia

We can ignore the ICO image format and just use PNGs. See wikipedia .

.

SVG Flagmatic. observable