web-platform-tests / interop

web-platform-tests Interop project
https://wpt.fyi/interop
307 stars 28 forks source link

Sumptuous stroked text in CSS #759

Open robole opened 2 weeks ago

robole commented 2 weeks ago

Description

A stroke is a border drawn along the outline of a letter.

fill-and-stroke-figure

It can be used to create a range of beautiful aesthetics:

yulia

costa-egypt

iron-maiden-stroked-text

The existing "nonstandard" -webkit properties that are specified in the WHATWG Living Standard have inconsistent implementations. They are:

  1. -webkit-text-stroke: this is the shorthand property for the following 2 properties,
  2. webkit-text-stroke-width,
  3. webkit-text-stroke-color,
  4. -webkit-text-fill-color.

There is the W3C CSS Fill and Stroke Module Level 3 Specification that covers the same properties . The fundamental properties proposed are:

The paint-order property should be reviewed in this change also as it determines the layering of stroke and fill.

The other stroke and fill properties in the specification could be implemented separately.

It is your decision if you fix interop issues for the "nonstandard" WHATWG Living Standard spec or shift towards the "standard" W3C CSS Fill and Stroke Module Level 3 Specification. The work will be complementary in the long-run.

Specification

WHATWG Living Standard, W3C CSS Fill and Stroke Module Level 3 Specification.

Standards Positions

Site Breakage and Workaround

The existing -webkit properties that are specified in the WHATWG Living Standard for stroke and fill are well supported, but have inconsistencies in the implementations. It can be difficult to get an accurate and attractive result with the -webkit-text-stroke property for stroked text.

It is more common to embed a SVG or image in a webpage of the text for this instead. See IMDB Top Series of 2022 example in the screenshot below.

imdb-top-series-2022-page-hero-section-devtools

Size and Current State of the Feature

The existing "nonstandard" -webkit properties enable specifying the width and color of a stroke for text content, and its fill color. The -webkit-text-stroke property is currently supported by approximately 96% of modern browsers.

Depending on the font and property combinations used, the stroke can be drawn with mistakes. Stroke corners don't look the same in all browsers. See bugs below.

vintage

The paint-order property controls the layering of the fill and stroke. It had issues. In Chrome on Linux, I encountered an issue using the property in the recent past, but it appears to be OK now. There is a Firefox bug related to this topic.

You have no control of stroke alignment. This would make a major difference to outcomes.

stroke-alignment

Without consistent results, you are unlikely to want to use a stroke and fill together. If you use a stroke without a fill (transparent), results are much better.

Browser Bugs

There are web platform tests for -webkit prefixed filling/stroking.

Here are the specific bugs that I could find, but I have a feeling that they may be more.

Chromium bugs:

Mozilla bugs

Developer Surveys

In the State of CSS 2023, one of the top answers to the question, What features do you feel are currently missing from CSS altogether? is "SVG-in-CSS". This covers support for SVG syntax inside CSS, of which stroke and fill properties are fundamental.

Other Developer Sentiment

The Chrome Platform Status shows that usage of -webkit-text-stroke has doubled in the last 2 years despite its shortcomings.

The article - Can you create beautiful stroked text in CSS? - outlines some of the opportunities to use stroked text on the web, and the limitations of what currently can be achieved.

Likely Compatibility Impact

It is unlikely that it would cause any compatibility issues. Effort mostly involves improving interop of existing features, or implementing new, proposed properties.

Platform Impact

The implementation of stroked text will allow developers to implement more imaginative designs. What is possible in design tools regarding stroke and fill is not possible in CSS. This can be a point of contention between designers and developers. Currently the caveats and limitations with implementing designs involving stroked text is offputting. Designs that are commonplace in print media, are quite rare on the web.

It will be an improvement for accessibility if standard HTML elements are used for stroked text rather than SVG. People often forget to consider accessibility issues when embedding SVG documents in webpages.

It will be an improvement for internationalization. People often forget to consider text embedded in SVG documents.

thebabydino commented 2 weeks ago

From the LogRocket article:

In Chrome (Linux), it appears that the paint-order property is ignored

FWIW, I'm on Ubuntu and I've been playing a lot with both -webkit-text-stroke and paint-order this year and I have never seen paint-order being ignored in Chrome. And the CodePen demo it links to looks fine and not like in the screenshot in the article. The article is dated April 2023, so sometime between then and early this spring, this must have been fixed. Also, it's not clear to me what the Firefox problem with paint-order may be. Seems to work fine to me - am I missing something?

That being said, there are lots of problems with CSS text stroke.

Detailing the above with examples/ screenshots/ live links.

Stroke corners don't look the same in all browsers. In Firefox, the outer angle stroke corners get rounded, in WebKit browsers they don't.

The example below (live demo) uses an SVG filter for a more interesting effect, but the double stroke is created with -webkit-text-stroke. The inner half of the stroke is its inner half overlapping the letter fill, while the outer half is its outer half that's outside the text fill. What I'm doing is using a semi-transparent stroke, extracting its inner and outer halves separately via a feColorMatrix and then painting them differently. You can see the outer angle stroke corners are rounded in Firefox, which looks really weird.

The text "now" in all caps with a thick stroke, clearly rounded, not sharp in Firefox.

But they aren't for Chrome - compare the inside of the 'N' and 'W' letters.

The text "now" in all caps with a thick stroke, clearly sharp, not rounded in WebKit browsers.

Here's another example (live demo) - it's less obvious here since the strokes are thinner, but you can still see it - the outer angle stroke corners are rounded in Firefox and it's particularly obvious inside the letters 'W', 'A' and 'M'.

The text "meet me halfway" in all caps with a thin stroke. It's all more subtle with a thin stroke, but still rounded, not sharp in Firefox.

But they aren't in WebKit browsers. Look inside the letters 'W', 'A' and 'M' - there's a bevel, not a rounding.

The text "meet me halfway" in all caps with a thin stroke. It's all more subtle with a thin stroke, but still sharp, not rounded in WebKit browsers.

As weird as the Firefox rounding looks, it can look better than what Chrome does at corners for certain fonts. See the example below, using the same semi-transparent stroke + SVG filter tactic. Live demo.

Screenshot. Shows the text "Kids Ground" split on two lines on a purplish background. This text has two strokes. The outer one is a darker gradient version of the main letter gradient (pink to orange for the top line and greenish yellow to green for the second one). The inner one is white, slightly offset up and has a dark shadow. This screenshot is taken in Chrome and shows a drastic miter-like break at some of the inner stroke corners.

If you can't see it, here are problem areas for Chrome zoomed in and with circles around them.

Detail of the Chrome problem.

Firefox avoids the problem by rounding the corners.

The result in Firefox, stroke corners get rounded.

Safari has SVG filter tiling issues, but does so much better than Chrome when it comes to those stroke corners.

All would be fine in Safari if it didn't break other things unrelated to the text stroke.

I've filed Chrome bug 🪲 341319152 about this, but got marked as a duplicate of bug 🪲 40944554 that got marked as WONTFIX. ¯_(ツ)_/¯

Strokes may get painted across the inside part of letters, not just along their outline for certain fonts (which includes most cursive fonts). paint-order can help hide the problem by putting the fill on top of the stroke, but it doesn't fix it and sometimes I want to have a semi-transparent stroke on top of the fill for that double stroke effect.

Two of the "handwriting" options on Google Fonts after giving all samples a thick, semi-transparent `text-stroke` from DevTools. The inner part (overlapping the fill) of the strokes is a mess. Two of the "handwriting" options on Google Fonts after giving all samples a thick, semi-transparent `text-stroke` from DevTools. The inner part (overlapping the fill) of the strokes is a mess. Two of the "handwriting" options on Google Fonts after giving all samples a thick, semi-transparent `text-stroke` from DevTools. The inner part (overlapping the fill) of the strokes is a mess.

I came across this while wanting to recreate this Dribbble shot. I ended up using a font that doesn't have the same vibe - live demo.

But the problem isn't limited to cursive fonts. Just set a text stroke to all Google Fonts samples to see what I mean.

Google Fonts screenshot showing strokes for random fonts intersecting. Google Fonts screenshot showing strokes for random fonts intersecting. Google Fonts screenshot showing strokes for random fonts intersecting.

This makes a lot of fonts unusable with -webkit-text-stroke.

Interaction with text-shadow is weird. text-shadow is drawn relative to original unstroked text. So if you set a text-shadow and also a text stroke, the shadow gets drawn under the stroke.

White text with a thick semitransparent red stroke drawn on top of a thin, offset to top left blue text-shadow respecting original unstroked text.

robole commented 2 weeks ago

Thanks for your feedback and examples Ana ( @thebabydino )!

FWIW, I'm on Ubuntu and I've been playing a lot with both -webkit-text-stroke and paint-order this year and I have never seen paint-order being ignored in Chrome. And the CodePen demo it links to looks fine and not like in the screenshot in the article. The article is dated April 2023, so sometime between then and early this spring, this must have been fixed. Also, it's not clear to me what the Firefox problem with paint-order may be. Seems to work fine to me - am I missing something?

The paint-order property looks fine in Chrome (Linux) now. I played with it 18 months ago and I bumped into this issue. Like you said, there must be have been a fix in the meantime. I'm not sure what the failing scenario is for Firefox, the bug report is not clear. The takeaway is that the were/are some rough edges for the property, so it could do with some attention along with the stroke properties.

Like you demonstrated, there can be weird outcomes depending on what fonts and property combinations you use. If I find more, I will add specific bugs.

thebabydino commented 2 days ago

Here's another bug (🪲 373419871) about the interaction of this with filter. Since text-shadow is relative to the unstroked text, I used a drop-shadow() filter. The problem with this is that it causes the tips of thick strokes to get cut off.