Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-fonts][css-text] Variation Selection of Colorful (Emoji) or Monochrome Glyphs #352

Closed
Crissov opened this issue Jul 28, 2016 · 35 comments
Labels
css-fonts-4 Current Work css-text-4 i18n-tracker Group bringing to attention of Internationalization, or tracked by i18n but not needing response.

Comments

@Crissov
Copy link
Contributor

Crissov commented Jul 28, 2016

In late March, on www-style, Addison Philips posted a request on behalf of W3C’s I18N WG to be able to control the style of emoji characters via CSS. There were links to the relevant I18N minutes and Unicode minutes as well as the reference document UTR51.

default : style characters to use each character's default display
text : style characters to use their text display
emoji : style characters to use their emoji display

The issue had been brought up in 2014 already, but I cannot find a WG conclusion on it. It has been suggested to be handled by font-variant-color (John Dagget), font-variant-emoji (Xidorn Quan @upsuper), “something more generic” or @font-palette (Cameron McCormack @heycam) or “a new property” (Amelia Bellamy Royds @AmeliaBR).

I agree with some of the concerns that this is not an issue appropriate to be handled by font-variant-*, not just because there’s no corresponding Open Type feature. I was about to propose the selection being part of text-transform, but I then realized that this would only be reasonable to override or synthesize variation selectors (U+FE0E = VS-15 ‘text’, U+FE0F = VS-16 ‘emoji’). UTR51 wants VSs to take precedence over normal styling, though. I suggest we add both capabilities!

font-color: 'auto' | 'monochrome' | 'colorful'  | <color>+

text-transform: <text-transform-case> || <text-transform-width> || <text-transform-variation>
text-transform-case: 'none' | 'capitalize' | 'uppercase' | 'lowercase'
text-transform-width: 'none' | 'full-width'
text-transform-variation: 'none' | 'text' | 'emoji'

Bikeshedding welcome.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Jul 28, 2016

To clarify the interaction of these properties, can you confirm whether these are the intended outcome of the following combinations?

  • Colorful text:

    font-color: colorful;
    text-transform-variation: text;

    Use the multi-color default palette defined in the font, if there is one (or fallback to currentColor otherwise).

  • Custom colorful text:

    font-color: tomato royalBlue indigo;
    text-transform-variation: text;

    Use the specified colors as a three-color palette for the font, if it supports it (or fallback to currentColor otherwise).

  • Default OS emoji + monochrome:

    font-color: monochrome;
    text-transform-variation: emoji;

    Substitute in standard OS full-color emoji if they are available; render all other glyphs with currentColor, regardless of the color palettes available in the font.

  • OS emoji + full-color font:

    font-color: auto;
    text-transform-variation: emoji;

    Substitute in standard OS full-color emoji if they are available; render other glyphs with the font's default full-color palette if available, or with currentColor otherwise.

If I've got that all correct, my remaining questions are:

  • Is there a meaningful difference between auto and colorful? I'm assuming both mean "use the default font palette if available". Would they behave differently if the font doesn't have a color palette, e.g., with fallback to currentColor?
  • How do the multi-color syntax and the keywords interact with the use of CSS variables to set font palette colors individually?

@svgeesus
Copy link
Contributor

@font-palette (Cameron McCormack @heycam)
I prefer @font-palette, as described in CSS4 Fonts:
https://drafts.csswg.org/css-fonts-4/#font-palette-control

Both of the vector-format chromatic font options in OpenType v.3 use palettes, via the CPAL table, so a way to override these from CSS is needed. Putting this in an at-rule allows the same font to be used with different palettes at the same time.

@Crissov
Copy link
Contributor Author

Crissov commented Jul 28, 2016

Oh, I only checked css-fonts-3 briefly and thus missed that font-palette and @palette-entries are already drafted for level 4, also didn’t see the original full proposal. Thanks for the heads-up, @svgeesus. I think I agree with the chosen solution for font-defined palettes, but I believe there should be a simple way to get monochrome glyphs using only currentcolor or shades thereof, which seems more appropriate for the vector variants, COLR and SVG, than for bitmap CBDT. My font-color: <color>+ was intended to either make a user-defined palette or populate --color1 etc. easily and @AmeliaBR is right, I hadn’t thought through the exact meaning of auto.

Nevertheless, my point regarding text-transform[-variant] stands and I think the expected results are as shown in the table below.

U+2661 U+2665 U+2764 U+1F499 U+1F5A4
Name White Heart Suit Black Heart Suit Heavy Black Heart Blue Heart Black Heart (UC9)
default, none 💙 🖤
VS15 or text ♡︎ ♥︎ ❤︎ 💙︎ 🖤︎
VS16 or emoji ♡️ ♥️ ❤️ 💙️ 🖤️
VS15 and emoji ♥️ ❤️ 💙️ 🖤️
VS16 and text ♡︎ ♥︎ ❤︎ 💙︎ 🖤︎
emoji and monochrome 🖤️ 🖤️ 🖤️ 🖤️
text and monochrome ♡︎ ♥︎ ❤︎ 🖤︎ 🖤︎

@fantasai
Copy link
Collaborator

fantasai commented Aug 2, 2016 via email

@kojiishi
Copy link
Contributor

kojiishi commented Aug 3, 2016

I'm confused what this thread is talking about. It looks like the first comment was about choosing emoji/text representation, the same functionality as VS15/VS16. But then other people are talking about changing color palette only for Emoji fonts. Which are we talking about?

Either way, this is about font selection and rendering, they should be font-, not in text-.

@Crissov
Copy link
Contributor Author

Crissov commented Aug 3, 2016

This issue is about both features and how to distinguish them, @kojiishi.

text-transform is about using the glyph of a different character than the one encoded or, some may argue, changing the code of the character and thus the glyph. Variation selectors are a different mechanism to choose an alternative glyph, but – much like font-variant and its foundational Open Type features – usually it’s specific to the encoded character and is not shared with or taken from a different character. That’s why I believe this part belongs into css-text. I think I would be okay with a separate text-… property, though.

Controlling the font palette of multi-color fonts belongs in css-fonts, on the other hand, maybe with considerations in css-color. The features interact insofar that requesting a monochrome palette is often almost the same as transforming all emojis to text style, except that not all emojis support VS-15 as shown with the blue heart in the table. The “black” hearts are always colored red when treated as emoji, but with a monochrome palette they should look much like the newly encoded U+1F5A4 (assuming color: black).

@tabatkins
Copy link
Member

The two features aren't really connected in any meaningful way, except weakly by metaphor. Emoji switching is changing the entire glyph used to render the codepoint; multicolor fonts just let you specify the color palette directly.

In particular, rendering a multicolor font with monochrome is the default - if you don't invoke the font-palette property, all the palette colors default to currentcolor.

Since the OP was about emoji transformation, let's stick with that topic. You can split off a separate font palette discussion to another issue.

@svgeesus
Copy link
Contributor

svgeesus commented Aug 3, 2016

In particular, rendering a multicolor font with monochrome is the default - if you don't invoke the font-palette property, all the palette colors default to currentcolor

That isn't what is currently implemented. Does something in the spec say this?

@Crissov
Copy link
Contributor Author

Crissov commented Oct 13, 2016

There is a related question on Stack Overflow. The answers suggest some shadow hacks to get monochrome or outlined emoji glyphs.

@Crissov
Copy link
Contributor Author

Crissov commented Dec 16, 2016

The lack of being able to enforce monochrome glyphs instead of colorful emojis is an important reason for symbol fonts to use PUA code points, which leads to a11y problems, e.g. FortAwesome/Font-Awesome#222.

@litherum
Copy link
Contributor

In particular, rendering a multicolor font with monochrome is the default - if you don't invoke the font-palette property, all the palette colors default to currentcolor

That isn't what is currently implemented. Does something in the spec say this?

I'd like to echo Chris's question - on iOS and macOS we have different defaults. I believe that according to Unicode this is allowed; if this behavior doesn't follow web content specs I'd love to hear about it.

@litherum
Copy link
Contributor

litherum commented Dec 16, 2016

For triggering emoji presentation style (often triggered by variation selectors), UTR51 explicitly states "Some systems may also provide this distinction with higher-level markup, rather than variation sequences." Therefore, the text-transform property should not be used to trigger this type of presentation style, since this behavior may not actually transform text. Similarly, the font-variant properties should also not be used because implementation of this behavior does not use font features.

This behavior is implemented by the 'cmap' table in the font. That is, drawing the string U+2603 U+FE0E in a font may actually end up drawing a different glyph ID than if you drew the string U+2603 U+FE0F using the same font. This has particular implications for font fallback - the strings above may map to glyph ID 0, which means that a fallback font may be chosen. This affects layout because the fallback font may have different metrics than the requested font.

On the other hand, color palettes are implemented after glyph selection, meaning they have no effect on font fallback. Palette selection describes how to draw a glyph once you already have a glyph ID in hand. Importantly, it also can't change the metrics of the glyph, meaning it doesn't affect layout.

Because of this, the two concepts should be kept separate, and should be triggered with orthogonal properties. Telling a font to draw with a text presentation while also specifying a color palette should be legal and valid. (Perhaps most fonts won't react to the color palette in this situation, but it's totally possible to build a font which would.)

@litherum litherum changed the title [css-fonts][css-text] Variant Selection of Colorful (Emoji) or Monochrome Glyphs [css-fonts][css-text] Variation Selection of Colorful (Emoji) or Monochrome Glyphs Dec 16, 2016
@litherum
Copy link
Contributor

litherum commented Dec 16, 2016

Another note: WebKit has the concept of a "fast" text code path and a "complex" text code path. Variation selectors trigger the complex text code path (but regular emoji don't). Therefore, if we implemented this property by adding variation selector code points to every emoji, it would likely have some performance impact. Therefore, the "text-transform" model is inaccurate.

@Crissov
Copy link
Contributor Author

Crissov commented Jan 20, 2017

Since I’ve missed it before myself, please note that UTR51 already specifies a higher-level method to express the author’s preferred style of emoji-enabled code points, using BCP47 hence :lang()is also relevant to the discussion.

The locale extension “-em” can be used to specify desired presentation for characters that may have both text-style and emoji-style presentations available.

<html lang="en-Latn-u-em-default" /> <!-- default style, either colorful emoji or monochrome text -->
:lang(*-u-em-text) {text-transform-variation: text;} /* text style */
[lang*="u-em-emoji"] {text-transform-variation: emoji;} /* emoji style */
:script(Zsym) {font-script-overwrite: "Zsye"} /* ISO 15924 alpha-4 script tags,
                                                 hypothetic selector and property */

I don’t think any browser honors such language codes yet.

@litherum
Copy link
Contributor

This is a perversion of the lang attribute.

@Crissov
Copy link
Contributor Author

Crissov commented Jan 21, 2017

That’s why it should be handled by and in CSS.

@kojiishi
Copy link
Contributor

I don’t think any browser honors such language codes yet.

The fonts.xml in Android has:

<family lang="und-Zsye">
  <font weight="400" style="normal">NotoColorEmoji.ttf</font>
</family>

So any apps running on recent Android will get the behavior.

@litherum
Copy link
Contributor

litherum commented Mar 8, 2017

So, it seems that we've settled on:

  • Not using font-variant-*
  • Not using text-transform
  • Not using font-palette

I propose a new property, which is allowed to affect font fallback (see #854 (comment)):

font-presentation: auto | text | emoji
initial value: auto

This property behaves as if the appropriate variation selector is specified on all the characters which accept them (as defined by Unicode), but only if the character doesn't already have a variation selector.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Mar 8, 2017

@litherum

How would this affect the actual choice of font? I.e., whether to use the font-family stack, or whether to bypass it and grab a system emoji font?

One way to retro-actively describe the current behavior, while still allowing authors to specify alternative emoji fonts (full or mono-color) would be:

  • If emoji is specified, or if auto is specified and the character is an emoji character, the browser searches the font stack specifically for a full-color character, falling back if necessary to a full-color system font. If no full-color versions of the character are available, fall back to regular font selection.

  • If text is specified, or if auto is specified and the character is not an emoji character, use the normal font selection rules: pick the first font in the stack that can render the character.

That said, if these are the rules, I think full-color/monochrome might be better keywords than text/emoji.

Also: If there are Unicode variation selector characters in the text, should they over-ride the emoji/text values, or vice versa? (I assume that the auto value would be based on Unicode categories and variation selectors.)

@Crissov
Copy link
Contributor Author

Crissov commented Mar 8, 2017

@litherum If I understand the UTC correctly, they consider the VS solution a clutch and would like higher-level protocols (like CSS or font features) to take precedence. Richard Ishida @r12a is W3C’s (i18n) liaison contact for Unicode – I didn’t find anyone else to ping at Github (e.g. Addison Philips, Unicode’s Rick McGowan or Mark Davis, Apple’s Peter Edberg, except for Google’s Markus Scherer @markusicu) who may know better [whom to ask].

@AmeliaBR With your proposed wording, text (or monochrome) would still result in colorful emojis if the first font in the stack that has any support only has colorful glyphs. This behavior may be okay for auto, but not for text, because authors and users need a way to suppress colorful emojis altogether.

I’m not sure about this, but maybe another preference should be covered by the respective property as well: bitmap versus vector glyphs. As you may know, Apple and Google are currently using PNG-based emojis, whereas Microsoft, Mozilla and Adobe (and W3C) back vector-based solutions. Opentype 1.8 standardizes all of them. (Usually, only the vector formats could interact well with currentcolor or @font-palette. #561)

@r12a r12a added the i18n-tracker Group bringing to attention of Internationalization, or tracked by i18n but not needing response. label Mar 8, 2017
@litherum
Copy link
Contributor

litherum commented Mar 8, 2017

If emoji is specified, or if auto is specified and the character is an emoji character, the browser searches the font stack specifically for a full-color character

Right now, browsers don't have agreement about how exactly variation selectors interact with font selection (See #854). Apple platforms have particular behavior which it would be valuable to emulate in Apple browsers. I don't know about other platforms' / browsers' algorithms. Until that issue has an agreement on how variation selectors work, we shouldn't specify exactly how this property, and therefore variation selectors, work with relation to font fallback. Instead, we should only say that it can affect font fallback.

If there are Unicode variation selector characters in the text, should they over-ride the emoji/text values, or vice versa?

CSS operates on elements, which hold sequences of code points in them. Variation selector code points modify a specific code point in the sequence. Because variation selectors are specific to a particular code point inside the text node, variation selectors should have a higher precedence than the CSS applied on the entire element. The CSS property should set a default which individual characters can opt-out of. (The only alternative would be for the web author to have to create around individual character clusters just to set the presentation style, which no author wants to do)

@litherum
Copy link
Contributor

litherum commented Mar 8, 2017

I’m not sure about this, but maybe another preference should be covered by the respective property as well: bitmap versus vector glyphs.

This decision is traditionally made inside the font file. If the web author wants to use a bitmap glyph as opposed to a vector glyph, the web author should just set a different font on the element.

@litherum
Copy link
Contributor

litherum commented Mar 8, 2017

RESOLVED (3/8/17): add font-presentation to the spec and have it affect font fallback.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Mar 8, 2017

With your proposed wording, text (or monochrome) would still result in colorful emojis if the first font in the stack that has any support only has colorful glyphs. This behavior may be okay for auto, but not for text, because authors and users need a way to suppress colorful emojis altogether.

That's a good point. So the text/monochrome option would need to search the stack specifically for a solid-color glyph (simple vector shape and or 1-channel bitmap mask). In contrast, to match current behavior in browsers that support multi-color fonts, auto would need to pick the first font that has the character, and pick the multi-color version if available in a supported format.

we shouldn't specify exactly how this property, and therefore variation selectors, work with relation to font fallback. Instead, we should only say that it can affect font fallback.

I really don't like the idea of creating a new property that affects a browser behavior without specifying how it does so. That's a recipe for incompatible implementations.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Mar 8, 2017

Glad to see the resolution to move ahead. Looking forward to a draft spec text to analyze. I'm still not sure if Myles' proposal covers all of the use cases I see.

As an author, I want:

  • The ability to set my own fonts, multi-color or monochrome, for emoji characters.
  • The ability to switch from multi-color to normal text rendering, even when a font & browser support both (for any character, not just Unicode emoji characters).
  • The ability to tell the browser to find a font in the stack that has a supported multi-color format, even if fonts higher up in the stack have fallback monochrome versions. (And, as Christoph suggested, the reverse: find a monochrome version, even if higher-ranked fonts are multi-color.)
  • That the current de-facto standard behavior for emoji characters (replace with system full-color emoji) remains the default.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Mar 8, 2017

A related issue is whether specifying fill/stroke for text should override full-color emoji substitutions. Browsers are inconsistent with SVG text; I haven't tested, but I suspect the same is true with the -webkit- text fill/stroke properties.

As I've argued elsewhere, extending fill & stroke to non-SVG text is going to need a property that switches between painted vs monochrome text (because the initial value for fill is black, not currentColor).

That painted-vs-monochrome switch would make sense integrated into the emoji-vs-monochrome switch, so the options would be:

  • monochrome (glyphs that will be painted with currentColor)
  • full color (from the font) — possibly this should be two values, one requiring support for custom color palettes, one accepting a default colored glyph
  • fill and stroke paint (which assume a monochrome glyph shape from the font, ideally a vector although I think most renderers also support monochrome bitmap fonts)
  • auto (for most characters: use the first font, in color if available; for emoji characters: look specifically for a full-color glyph).

A user agent style rule would set svg elements to the fill-and-stroke mode.

The definition of "emoji characters" for auto would be based on Unicode character classes, adjusted by Unicode variation selector codepoints in the text.

@litherum
Copy link
Contributor

litherum commented Mar 8, 2017

I really don't like the idea of creating a new property that affects a browser behavior without specifying how it does so. That's a recipe for incompatible implementations.

It will be specified: the rendering should match as if the appropriate variation selector was appended to every relevant character.

The ability to set my own fonts, multi-color or monochrome, for emoji characters.

You definitely can do this by putting your own fonts inside font-family.

The ability to switch from multi-color to normal text rendering, even when a font & browser support both (for any character, not just Unicode emoji characters).

That's what this new property does.

The ability to tell the browser to find a font in the stack that has a supported multi-color format, even if fonts higher up in the stack have fallback monochrome versions. (And, as Christoph suggested, the reverse: find a monochrome version, even if higher-ranked fonts are multi-color.)

That's also what this new property does (unless I'm misunderstanding you).

That the current de-facto standard behavior for emoji characters (replace with system full-color emoji) remains the default.

This is false on macOS. The default there is text-style.

@litherum
Copy link
Contributor

litherum commented Mar 8, 2017

http://unicodesnowmanforyou.com shows a code point which can accept variation selectors, but doesn't have an accompanying variation selector. You can use it to see what the default is on your system.

EDIT: Looks like Windows doesn't have a font which can draw the snowman in emoji style, so this test doesn't seem to work there. It definitely works on macOS and iOS though. The default on macOS is text-style and the default on iOS is emoji-style. I don't know about Linux.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Mar 8, 2017

When I mentioned the "current default", I was referring to the characters that Unicode calls "default emoji presentation characters".

The only browser/OS combinations I tried that applied emoji-style to Unicode snowman (U+2603, a "default text presentation character" in the Unicode emoji data), in the absence of a variation selector codepoint, was Mobile Safari 10. Mobile Safari 9 uses text presentation. Given that this is contrary to Unicode recommendations, I think it's safe to call that a bug in that one browser, and not be worried about maintaining compatibility with something that isn't web-compatible anyway.

@litherum
Copy link
Contributor

litherum commented Mar 8, 2017

This is why the default for this property is auto and not follow-unicode (or something similar). It is valuable for UAs to follow the conventions of the platform they are on, and it is also valuable for them to follow Unicode's recommendation. UAs should be allowed to make this decision without it being considered as a bug.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Mar 9, 2017

One person's bug is another person's feature! Sorry for sounding so antagonistic there.

You definitely can do this by putting your own fonts inside font-family.

I'm not sure that's currently true everywhere. It didn't used to be true on Chrome on Windows, although I tested & it is true now on Win 10, anyway. Probably related to using the system font as their Emoji font, instead of subbing their own bitmaps. But while testing that, I also confirmed that all three major browsers on Windows 10 currently will use any emoji font you specify in the font stack, even if it's monochrome. So my tentative definition of auto fails on that point, too.

Which is one more factor to convince me that auto can't be explicitly defined. It will be "let the browser do as it wishes," whatever that is. Hopefully somewhat consistent with Unicode, and somewhat consistent with platform conventions.

I'm more concerned about having clear definitions for the other options, so that authors can reliably control the behavior if it is important. An explicit color/emoji option, to search the stack or system fallback fonts for a color glyph before falling back to monochrome, and an explicit monochrome/text option, to do the same search looking for monochrome.

(And possibly, a fill/stroke option, to look for a monochrome glyph and then paint it with fill & stroke instead of solid color. But that could be added by the proposed Paint spec, if it is determined to be useful.)

litherum pushed a commit that referenced this issue Mar 9, 2017
@litherum
Copy link
Contributor

litherum commented Mar 9, 2017

I've just added a bunch of prose to the css-fonts-4 spec which should give us a baseline place to start discussions. Because this issue is for the basic feature, I'll close this issue and let people open up new issues with the new prose as they see fit.

Thanks everyone for helping out making this a reality!

@litherum litherum closed this as completed Mar 9, 2017
@svgeesus
Copy link
Contributor

svgeesus commented Mar 13, 2017

Looks like Windows doesn't have a font which can draw the snowman in emoji style, so this test doesn't seem to work there.

In Firefox on Windows 10 I see a monochrome snowman, and dev tools tells me it is using Segoe UI Symbol. Same for Chrome and Edge.

@Crissov
Copy link
Contributor Author

Crissov commented Mar 30, 2017

For the record, I've asked the editors of UTR/UTS 51. They believe that CSS should offer 5 states governing characters with the Emoji property (and emoji sequences they are in):

  • emoji-override: force emoji presentation, i.e. override U+FE0E
  • emoji: emoji presentation, unless in a text presentation sequence
  • default: adhere to Emoji_Presentation and variation selectors
  • text: text presentation, unless in an emoji presentation sequence
  • text-override: force text presentation​, i.e. override U+FE0F

I believe Twitter's website (and many others) enforces an emoji-override behavior by replacing characters with images. The default behavior in mobile OSs seems to be more like emoji, not default. They did not express preferences for a particular CSS property or module, nor whether all states should be available through a single property.

Note that the list above does not include a possible 6th state which would comply with Emoji_Presentation but ignore any variation selector.

@AmeliaBR
Copy link
Contributor

@Crissov

I was about to suggest you start a separate issue, but see that you have already done so. Leaving a cross-link here so others can find it:

#1144 Override (Emoji) Variation Selectors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-fonts-4 Current Work css-text-4 i18n-tracker Group bringing to attention of Internationalization, or tracked by i18n but not needing response.
Projects
None yet
Development

No branches or pull requests

8 participants