Search code examples
javascriptemoji

Javascript detect if native emoji is supported


I would like to detect if native emoji is supported.
Only if it does not, I will then load emoji font to save bandwidth and also make the application look more native.

However, as I search through the Internet, I only found someone using userAgent to check if emoji is supported or not.
For example, the below code is from https://github.com/github/g-emoji-element/blob/master/emoji-detection.js,

export function isEmojiSupported(): boolean {
  const onWindows7 = /\bWindows NT 6.1\b/.test(navigator.userAgent)
  const onWindows8 = /\bWindows NT 6.2\b/.test(navigator.userAgent)
  const onWindows81 = /\bWindows NT 6.3\b/.test(navigator.userAgent)
  const onFreeBSD = /\bFreeBSD\b/.test(navigator.userAgent)
  const onLinux = /\bLinux\b/.test(navigator.userAgent)

  return !(onWindows7 || onWindows8 || onWindows81 || onLinux || onFreeBSD)
}

Though the regular expression may not be perfect, as Firefox in Windows 7 does support Emoji as from http://caniemoji.com/.

However, as different browser or libraries may have different set of emoji, some emoji may render perfectly in one browser, and some just not render very well.

So is there a better method other than using userAgent to check if Emoji is supported?


Solution

  • There used to be a technique to measure the width of an element containing text in 2 different fonts to see if a font is supported by seeing if a fallback font was used.

    A similar technique can be used with emojis by taking advantage of emoji sequences that collapse onto a single emoji.

    If a browser supports emojis it will render 1 glyph for emojis that are made up of 2 sequences. If it doesn't, it will render 2 glyphs.

    var trinidad = String.fromCodePoint(0x1F1F9, 0x1F1F9);
    var hammerpick = String.fromCodePoint(0x2692);
    
    function getWidth(s) {
      var n = document.body.appendChild(document.createElement("span"));
      n.appendChild(document.createTextNode(s));
      var w = n.offsetWidth;
      n.parentNode.removeChild(n);
      return w;
    }
    
    console.log(getWidth(trinidad) === getWidth(hammerpick) ? "supported": "not supported");