CSS background-clip Demo: Text with Animated Emoji

Fun demo by Elad Shechter:


See the Pen Background-clip: text with Animated Emoji by Elad Shechter (@elad2412) on CodePen.

Behind it are two techniques:

  1. The 👻 emoji is set as the background-image of the text. To do so one must wrap it inside an SVG, and successively inject the SVG using a Data URL.

  2. To clip the emoji to the foreground text, he uses background-clip: text.

I like the fact that these techniques by themselves are not new, yet their combination is (at least to me this was the case):

  1. The “Emoji in SVG”-technique allows you to have an Emoji Mouse Cursor or use an emoji as favicon.
  2. Using background-clip: text works on any background image. As gradients can also be set as background images, you can create gradient links.

Using Emoji as the Mouse Cursor on a Webpage

Recently I saw this tweet by Marco Denic fly by:

To use an emoji as the cursor you can’t simply type in the emoji though.

/* ❌ This won't work */
html {
	cursor: 👻, auto;
}

What you’ll have to do instead is embed the emoji inside an SVG and then successively embed that SVG in the CSS file by passing it as a Data URL into the url() function.

/* ✅ This will work */
html {
	cursor: url('data:image/svg+xml;charset=utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" height="64" width="64"><text y="28" font-size="32">👻</text><path d="M0,2 L0,0 L2,0" fill="red" /></svg>'), auto;
}

See the Pen
Emoji Cursor
by Bramus (@bramus)
on CodePen.

If you’re on a device that does not show a pointer, here’s a recording of what the demo looks like:

In the code above I’ve also added a little triangle in the top left corner of the SVG, as that’s where the actual tip of the pointer is. Omitting it makes up for a really weird experience.

To customize the color of the tip you can change its fill value to any color you like. Although not recommended you can remove the entire <path> if you don’t want it.

Update 2020-01-27: As reader Louis Houbregts points out it’s also possible to set the X/Y coordinates to indicate where the tip of the pointer is.

html {
	cursor: url(…) 10 0, auto;
}

For emoji this isn’t an ideal option though, as emoji differ per platform/vendor.

To change the overall size of the emoji cursor, change the height and width attributes of the SVG. Best is to leave the other attributes (such as viewBox and font-size) alone, as those have been carefully tweaked.

🔥 Using this same technique you can set an emoji as the favicon.

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Emoji Customizer created with CSS Variables

Fun pen by Jakob Eriksen in which he combines Emoji and CSS Custom Properties to create an Emoji Customizer.

The reason that this works is because of the fact that emoji can have modifiers. Skin Tone and Hair, as used in the demo above, are such modifiers. Using the ZWJ ("\u200d") you can glue all parts together so that they become an “Emoji ZWJ Sequence”, yielding a new Emoji.

🤓 My favorite Emoji ZWJ Sequence is the Rainbow Flag (🏳️‍🌈). It literally is the combination of a white flag (🏳) and a rainbow (🌈).

Using an Emoji as a Favicon

Great “hack” popularized by Lea Verou (but first discovered by Leandro): if you place an emoji inside <text> in an SVG Favicon you instantly have an Emoji Favicon 🙂

Beware of potential clipping on various platforms though, as emoji differ per platform.

Emoji Compositions — Create your own emoji by combining existing ones (👱‍♂️ + 🎩 + 🔎 = …)

Last Friday Max Lynch sent out this tweet:

Inspired by an idea that first came to my mind after seeing these emoji compositions using the 😎 emoji, I quickly replied that it’d be perfectly possible to (visually) create this new emoji by using a combination of the existing 👨, 🎩, and 🔎 emojis.

Not soon thereafter I quickly knocked on up on codepen:

At the base is one <span> element that contains the 👨 emoji. Using ::before and ::after I then inject the 🎩 and 🔎 emojis and position them absolutely on top of the 👨 emoji.

And then … I got distracted. And created some more compositions:

Due to the fact that I’m using ::before and ::after here, I’m limited to only two “decorations” per base emoji. Next to positioning the emojis some also got rotated, flipped, or even clipped to form a better match. I’m especially happy with the “cool lisping geek” and “smoking king” ones 🙂

Do note that this will only work on macOS/iOS as other platforms use other emojis. If you’re on another platform, be sure to check out the reference image.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

gitmoji – An emoji guide for your commit messages

Gitmoji is an initiative to standardize and explain the use of emojis on GitHub commit messages. Using emojis on commit messages provides an easy way of identifying the purpose or intention of a commit with only looking at the emojis used.

Next to the guide there’s also a CLI binary to help you perform commits (in case you don’t want to do it manually)

gitmoji →
gitmoji-cli →

😎 Emoji Compositions

In succession to Split emoji text effect with CSS (which has received an update by now BTW), PixelAmbacht has created a nice Emoji composition using the U+1F60E Smiling Face With Sunglasses emoji (😎) as the key modifier.

Note: For some mysterious reason the original demo yielded a blank page for me. Changing the font-size to anything lower than the originally set 8em fixed this issue. Therefore I’ve embedding a fork of the original demo.

Here’s how it works: The 😎 emoji is injected using generated content. It is positioned on top of the original emoji, and cut off (in height) so that only the sunglasses remain. In the end mix-blend-mode: darken; is added to make ‘m a bit transparent. Only works with the default Mac Emoji BTW.

Personally I’ve gone with overlaying the 🕶 emoji, to not have to use any blending at all.

Sidenote: Marcin Wichary has also been busy mocking up some emoji variations, and compositions using the ❤️ emoji:

Workshopped a bunch of emoji ligatures for more complex and underrepresented feelings.

The emoji ligature Rorschach test →

runes – Unicode-aware JS string splitting with full Emoji support

At Small Town Heroes I’m currently working on a newsreader app built using React Native. On Android (even 7.1.1) we noticed this weird issue where some emojis would render incorrectly when we were applying styling on it using index-based ranges: the range seemed to be off by one, splitting the emoji into its separate bytes. What made this issue even more weird is that this behaviour stopped when we connected the app to a debugging session.

Result of applying a specific style on this 41 symbol counting sentence
Figure: Result of applying a specific style on this 41 symbol counting sentence.

As you might be aware emoji can be multibyte strings and thus compromise two (or even more) bytes. When asking the length of a string, JavaScript will count the number of bytes, not the number of symbols. Technically correct, but no so good for us:

// I count 7, what about you my dear JavaScript?
>> 'Emoji 🤖'.length
8

When asking the length of a string, JavaScript will count the number of bytes, not the number of symbols.

To get the correct symbol count, you can use Array.from() or the spread operator (*):

>> Array.from('Emoji 🤖');
["E", "m", "o", "j", "i", " ", "🤖"]

>> Array.from('Emoji 🤖').length
7

>> [...'Emoji 🤖'].length
7

(*) Do note that this technique is not 100% bulletproof though. It has “problems” with skin tone modifiers and other emoji combinations – which in itself yields some fun results – but let’s ignore that for now.

Knowing how to get the correct count, it’s possible to extract proper substrings from that sentence, to apply your styling on (*):

// Wrong way to do it (not multibyte-aware)
>> 'Emoji 🤖'.substr(0,7);
"Emoji �"

// Correct way to do it (multibyte-aware)
>> [...'Emoji 🤖'].slice(0,7).join('');
"Emoji 🤖"

(*) Why not just use String#length and String#split all throughout our code (thus bypassing the whole thing) you might wonder? Well, the editor used to input the article *is* multibyte aware, so it would return 7 as the length of that sentence 😉

Now, even though we were using Array.from() to get the correct substrings, we ran into issues on Android whilst doing so: it would aways yield "Emoji �", no matter which technique we used. Long story short: we found out that the runtime on the Android phone – somehow – was using a non-multibyte aware Array.from(), explaining the wrong result.

// Android 7.1.1
>> Array.from('Emoji 🤖');
["E", "m", "o", "j", "i", " ",  "�", "�"] // <-- Wait, wut?

With this, we also found out that the JavaScript runtime used during a debugging session is different from the one used in standalone mode. For the debug session, the one contained in node (e.g. V8) would be used.

The solution to bypassing this mysterious problem was to use runes, a library that's Unicode-aware. Above that it also plays nice with skin tone modifiers and other emoji combinations, making it superior to the Array.from() technique.

const runes = require('runes');
 
// Standard String.split 
'♥️'.split('') => ['♥', '️']
'Emoji 🤖'.split('') => ['E', 'm', 'o', 'j', 'i', ' ', '�', '�']
'👩‍👩‍👧‍👦'.split('') => ['�', '�', '‍', '�', '�', '‍', '�', '�', '‍', '�', '�']
 
// ES6 string iterator 
[...'♥️'] => [ '♥', '️' ]
[...'Emoji 🤖'] => [ 'E', 'm', 'o', 'j', 'i', ' ', '🤖' ]
[...'👩‍👩‍👧‍👦'] => [ '👩', '', '👩', '', '👧', '', '👦' ]
 
// Runes 
runes('♥️') => ['♥️']
runes('Emoji 🤖') => ['E', 'm', 'o', 'j', 'i', ' ', '🤖']
runes('👩‍👩‍👧‍👦') => ['👩‍👩‍👧‍👦']
const runes = require('runes')
 
// String.substring 
'👨‍👨‍👧‍👧a'.substring(1) => '�‍👨‍👧‍👧a'
 
// Runes 
runes.substring('👨‍👨‍👧‍👧a', 1) => 'a'

runes – Unicode-aware JS string splitting with full Emoji support →

Related: The presentation Javascript ❤️ Unicode and accompnaying blogpost JavaScript has a Unicode Problem by Mathias Bynens is pure gold when it comes to JavaScript and Unicode 😉

Did this help you out? Like what you see?
Consider donating.

I don't run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

Split emoji text effect with CSS

Thanks to some absolute positioning, hue-rotation, and even some clipping you can create nice split emoji:

I especially like the experiments near the lower part of the demo, where one emoji is used as a modifier for the other (e.g. the 🎩 is placed on top of 😁, yielding a new emoji). They remind me of this ingenious XKCD Comic on “the vomiting emoji” (U+1F92E):

💥 Did you know you can also create Emoji Silhouettes and/or Outlines? And did you know that some emoji wrap lines, and some don’t?

Text-wrapping, hyphenation, emojis and what not

Earlier today I ran some tests to see how text-wrapping/hyphenation of long uninterrupted strings works in browsers. I tested both “normal” strings and strings of emojis.

The tests (and its rendering results per browser) are stored on Codepen and embedded below:

💩 and ⚠️ behave differently (click to enlarge):

These tests left me with some core questions:

  1. Why do some emojis get text-wrapped, and some not?
  2. If the above is a feature: is there a list of emojis – or can we detect which emojis – that get text-wrapped (and those who are not) available somewhere?
  3. Why do emojis get text-wrapped, and not hyphenated?

~

Later in the afternoon Khaled Hosny jumped in on Twitter, and pointed me towards the needed Line Breaking Properties Specification, by which I was able to answer the core questions. Here goes …

1. Why do some emojis get text-wrapped, and some not?

This is dependent on the “Line Breaking Property” which is set for/on a character.

The Line Breaking Properties Specification defines a set of possible classes:

(A)
Allows a break opportunity after in specified contexts
(XA)
Prevents a break opportunity after in specified contexts
(B)
Allows a break opportunity before in specified contexts
(XB)
Prevents a break opportunity before in specified contexts
(P)
Allows a break opportunity for a pair of same characters
(XP)
Prevents a break opportunity for a pair of same characters

These classes are then combined into properties. To us relevant properties (extracted from the spec) are:

ID

Ideographic (B/A)

Characters with this property do not require other characters to provide break opportunities; lines can ordinarily break before and after and between pairs of ideographic characters.

AL

Ordinary Alphabetic and Symbol Characters (XP)

Characters with this property require other characters to provide break opportunities; otherwise, no line breaks are allowed between pairs of them.

It’s these properties that can then be assigned to a specific character.

Say a character has the AL Line Breaking Property set, then it means that no line breaks are allowed between pairs of them.

Characters (and thus emojis) have a “Line Breaking Property”, which applies one or more breaking classes onto the character. Two of the possible values for said property are:

  • ID = (B) and (A) classes = allow breaks before and after the character
  • AL = (XP) class = don’t allow breaks in between pairs.

~

2. If the above is a feature: is there a list of emojis – or can we detect which emojis – that get text-wrapped (and those who are not) available somewhere?

The answer to question 1 clearly indicates that it’s an actual feature. Khaled also sent me a link to a plain text file mentioning the Line Breaking Properties per character. Linking back to the tests I ran, we can extract these values for 💩 and ⚠️:

  • 💩 = 1F4A5..1F4A9;ID
  • ⚠️ = 26A0..26BC;AL

The plot thickens, right?

💩 and ⚠️ have a different Line Breaking Property set:

  • 💩 = ID = breaks allowed before and after the character
  • ⚠️ = AL = no breaks allowed in between pairs.

~

2b. (Bonus question) Can I somehow force emojis with the AL-property to split in between pairs?

Yes you can! From the spec:

Use ZWSP as a manual override to provide break opportunities around alphabetic or symbol characters.

ZWSP = ZERO WIDTH SPACE (U+200B or HTML &#8203;).

When looking that one up in the list, we can see that is has ZW set as a value for its Line Breaking Property. The spec mentions that ZW applies the (A) class, thus allowing breaks after it 😊

Manually sprinkle a ZWSP character in between pairs of AL-emoijs to provide break opportunities.

Using CSS you can use word-break: break-all; to allow breaks be inserted between any two characters.

~

3. Why do emojis get text-wrapped, and not hyphenated?

Browsers use a language-based hyphenation dictionary to apply hyphenation. The dictionary to use is defined by the set language on a document or element. From the CSS Text Module Level 3 Spec:

Correct automatic hyphenation requires a hyphenation resource appropriate to the language of the text being broken. The UA is therefore only required to automatically hyphenate text for which the author has declared a language (e.g. via HTML lang) and for which it has an appropriate hyphenation resource.

(*) As seen in the tests it should be noted that firefox follows this guideline quite strictly, as hyphenation only works when explicitly setting the lang attribute to a one of its supported languages (see tests). Chrome and Safari, apparently, are not so strict in this and use a default language. There’s a bug filed for Chrome on this.

There is no hyphenation dictionary for emojis.

Emojis don’t hyphenate because they have no hyphenation-dictionary. For regular text, be sure to set your lang attribute if you want hyphenation to work properly. Also: IE/Edge don’t like my tests, apparently.

~

Now, that was an interesting journey I must say. I now understand why certain things (should) happen. 🙂

Remains – as per usual – a few browser-specific quirks to be answered …

  1. Why, in Chrome, is hyphenation not applied on the last string?
    It’s a bug! and has been fixed in Chrome 56 and up. This issue regressed, and is now properly fixed in Chrome 90.
  2. Why, in Firefox, does the container stretch out on the ⚠️-test, whilst other browsers overflow?
    → …
  3. Why, in IE11/Edge, does the 💩-test not wrap, whilst other browsers do?
    → …
  4. Why, in IE11/Edge, does hyphenation not work even though it should? Setting the lang to en-US, or setting the lang on the body or html yield the same result.
    → …
  5. Why, in Chrome and Safari, is hyphenation applied even when the required lang is not set?
    → Bugs for Chrome and Safari have been filed.
Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)