I got a very helpful bug report the other day (thanks Kilian!) about the <details> element in a blog post of mine not showing the default ▶ icon, and thus looking rather like any ol’ random <p>.
It wasn’t terribly hard to diagnose. I just opened the page in Firefox, inspected the element in Firefox DevTools, and played with properties and values until I saw the ▶ come back. The problem? I was using a (very old) copy of Normalize.css, which must have followed me through several redesigns on this site, and set…
In Chrome, the User Agent style for <summary>isblock, so no problem with setting it to block. But in Firefox, best I can tell, the User Agent style is list-item.
Hence Jon setting it to list-item in the current version of Normalize.
You can also see in the Firefox DevTools that the ▶ is applied with a ::marker pseudo element. As soon as <summary> isn’t a list-item anymore, the ::marker disappears. I guess that makes some sense, as the spec says:
So, you know how many emoji have different skin tones? Emoji skin tones are extremely popular, especially over text and on social media. The raised black fist emoji (✊🏿) was voted “The Most 2020 Emoji” by Emojipedia’s World Emoji Awards.
Each tone is a modifier and many emoji are made up of modifiers and base encodings that map to specific characters. Unfortunately, not every emoji library supports modifiers. But, given their popularity, emoji skin tone modifiers are more than a “nice to have” feature. Plus, they’re a smart way to work because they allow us to write more modular and efficient code.
So that’s what we’re doing in this article: figure out how to work with emoji modifiers programmatically. This way, if you’re ever stuck without skin tone support — or want to create custom variations of other emoji — then you’ll know how!
Meet the Fitzpatrick scale
Skin tone modifiers were officially added to emoji in 2015 as part of Unicode 8.0. They are based on the Fitzpatrick scale, which is a formal classification of human skin tones. The following chart shows how the emoji characters match to Fitzpatrick types:
Skin tone character
In the simplest use case, when one of these characters is appended to an emoji that supports skin tone modifiers, it will change the skin tone of the emoji.
Another way to say that: 👶 +🏽 = 👶🏽
Applying skin tone modifiers with CSS
To swap between emoji skin tones using CSS, we would start with the base emoji character (👶) and then append the skin tone using the ::after pseudo-selector.
In addition to using the rendered emoji characters, we could use the Unicode hex codes instead:
What’s going on here? First, we start with a baby emoji with Fitzpatrick Type 4. We then pass it into the function removeModifier, which searches for any of the skin tone modifiers and removes it from the string. Now that we have the emoji without a modifier, we can add whichever modifier we like.
While this approach works with many emoji, we run into problems when other modifiers are introduced. That’s why we now need to talk about…
ZWJ sequences are most commonly used to add gender modifiers to emoji. For example, a person lifting weights, plus ZWJ, plus the female sign, equals a woman lifting weights (️🏋️ + ♀︎ = 🏋️♀️).
There’s a few important things to need to keep in mind when working with ZWJ sequences:
The sequences are only recommendations. They come from the Unicode Consortium and are not guaranteed to be supported on every platform. If they are not supported by a platform, then a fallback sequence of regular emoji will be displayed instead.
Skin tone modifiers, if present, must be included after the emoji but before the ZWJ.
Some ZWJ sequences include multiple emoji that each have different skin tone modifiers.
Given this information, we need to make the following changes to the previous code example:
The skin tone modifiers need to be inserted immediately after any base emoji rather than simply being appended to the end of the emoji.
If there are multiple emoji in a ZWJ sequence that have skin tone modifiers, then the modifiers will need to be replaced for each of those emoji.
From this example, you may notice the limitation of consistency. The editor view shows each of the characters in a ZWJ sequence separately, with exception to the skin tone modifiers, which are immediately applied to their corresponding emoji. The console or results views, on the other hand, will attempt render the character for the entire sequence.
Support for this will vary by platform. Some editors may attempt to render ZWJ sequences, and not all browsers will support the same sets of ZWJ sequences.
Additionally, adding skin tones in a ZWJ sequence requires knowing what’s being used as the base emoji. While this would be relatively simple in a situation where the emoji are provided by a known collection, things become more difficult if we want to be able to handle arbitrary input from a user.
Also, be aware that the CSS solutions in this post are not compatible with ZWJ sequences.
Questions to guide development
I put some questions together you may want to ask yourself when you’re designing a system that needs to handle emoji skin tone modifiers:
Do I have control over which emoji my system will interact with?
Does my emoji library have information about which emoji support skin tone modifiers?
Does my system need to add, remove, or change the modifiers?
Does my platform support ZWJ sequences? If so, which ones?