How To Use System Emoji With Webfonts?


tl;dr - If a mobile web browser recognises an Emoji, it should display it natively. If not, it should fall back to a supplied web font. Is this possible?

When Android and iOS find Emoji in text, rather than display them as black-and-white fonts, they show them off in gorgeous colour.

For example, the unicode smilie is ☺. Depending on your system, it will look something like this:

From  Tim Whitlock
From Tim Whitlock

So far, so nifty! But here we hit a snag. Not every computer has a font which contains all the characters we want.

Consider this problem: I want to replace some of the links on my web page with symbols.
I've chosen:🏠✉ 🔍♻⚙ℹ

If your system supports all those characters, you should see symbols for home, mail, search, recycle, settings cog, & information.

On Android 4.4, the above look like:
Android Emoticon Fonts-fs8

Android Lollipop improves things somewhat - although the mail and recycle symbols both take a retrograde step:
Android Lolipop Emoticon Fonts-fs8

Good enough for what I want to do - but what happens when we look at it on a desktop?
Desktop Emoticon Fonts-fs8
The plain nature of the fonts I can live with - the broken characters I cannot.

Fine - let's find a font which has all those symbols. Alexander Lange maintains the excellent Quivira Font, the latest version (4.1) contains 11,053 characters - including all the ones I want. The font is 1.5MB - which is too large for most uses, and particularly unsuitable for mobile. It's possible to subset the font so that it only contains the needed characters.

That gives us this set of symbols:
Quivira Symbols-fs8

Ok, not the prettiest pig in the pen - but at least they're fairly consistent.

Here's where I hit my snag. I want devices which recognise those characters to display them with colourful emoji. Any device which doesn't recognise them, should use the symbol font I've created.

I naïvely thought that this CSS would work:

@font-face {
    font-family: 'quiviraregular';
    src: url('quivira.eot');
    src: url('quivira.eot?#iefix') format('embedded-opentype'),
         url('fonts/quivira.woff2') format('woff2'),
         url('quivira.woff') format('woff'),
         url('quivira.ttf') format('truetype');
}

body{
	font-family:sans-serif,quiviraregular;
}

Theoretically, Quivira should only be called if the font is not found in the system's sans-serif set. But it doesn't. I've tried on Android with Chrome, Firefox, and Opera. No dice.

It doesn't matter what I put in that font-family declaration. Once Android detects a font with the glyph, it doesn't fall back to displaying it as an emoji.

I fiddled around with several font-family settings I found around the web "pictograph", "fantasy", "Apple Color Emoji", "Droid Emoji", "emoji" (using this shim) - none of them worked.

It's possible to set a unicode-range for fonts. I couldn't find a way to tell browsers to use their fallback fonts first for a specific range.

I can find the names of the Emoji system fonts - but I can't find a way to reference them.

I've tried every variation I can think of:

@font-face {
	font-family: 'emoji';
	src:  local('Android Emoji'),
	src:  local('NotoColorEmoji'),
	src:  local('NotoColorEmoji.ttf'),
	src:  local('/system/fonts/NotoColorEmoji.ttf'),
	src:  local('Noto Color Emoji'),
	src:  local('Android Emoji');
}
body{
	font-family:emoji,sans-serif,quiviraregular;
}

And

body{
	font-family:'Android Emoji','NotoColorEmoji','NotoColorEmoji.ttf','/system/fonts/NotoColorEmoji.ttf','Noto Color Emoji','Android Emoji',sans-serif,quiviraregular;

Still no difference - it does not show the colourful Emoji. Instead it just falls through to the symbol font I created.

Well, I'm stumped! Does anyone know the answer? I'd really rather use fonts than images.

  1. If a browser has an Emoji representation of a character - show it.
  2. If not, use the provided font.

If you know, please leave a comment here or on StackOverflow.

Leave a Reply

Your email address will not be published. Required fields are marked *