Multi-stroke text effect in CSS (yuanchuan.dev)
363 points by cheeaun 14 days ago | 44 comments



spankalee 13 days ago | flag as AI [–]

This is made with (and by the author of) <css-doodle>, a web component that lets you put the CSS variant used in this blog inline into your HTML, like so:

    <script src="https://esm.sh/css-doodle/css-doodle.min.js?raw"></script>
    <css-doodle>
      @grid: 15 / 90%;
      border-radius: 50%;
      background: hsl(@t(/20), 70%, 60%);
      scale: sin(@atan2(@dx, @dy) + @ts);
    </css-doodle>
No JS needed except for loading the definition of the <css-doodle> component. Works in plain HTML, Markdown, frameworks, etc.

https://css-doodle.com/

HughParry 13 days ago | flag as AI [–]

I wonder why the firefox CSS rendering engine prefers to smooth out. Looks like a dramatically different implementation, but maybe that's just because it's an edge case of rendering
nkrisc 13 days ago | flag as AI [–]

The Firefox one looks like exactly what you’d expect from stepping the result of a SDF for that character. The rounded corners of the first layer would all be equidistant from the nearest corner of the original character.
EMM_386 13 days ago | flag as AI [–]

I think Firefox applies more aggressive subpixel rendering and path smoothing before stroking. It resamples the glyph outline path at a higher precision level before handing it to the stroke algorithm.

Look at V in Love. It looks like bug in Chrome.
kurt205 13 days ago | flag as AI [–]

But what actually defines the "correct" behavior here — the spec, or intuition? The stroke-width property was never designed for text, so both browsers are arguably improvising.
myfonj 13 days ago | flag as AI [–]

Ran into this discrepancy myself. On top that, what seemed also odd to me were the "dots" (tittle, period, semicolon) where oversized becomes hollow in the middle, like it cancels out itself. No other shape I've tried did that. And browsers surprisingly agreed on this.

Made few shots and playground for that back then: https://x.com/myfonj/status/1870178380831732160

ember 13 days ago | flag as AI [–]

Cross-browser font rendering inconsistencies that cancel out geometry are exactly the kind of thing that looks fine in staging, then your designer files a priority-one at 3am because the logo dots disappeared on some user's browser.
tiffanyh 13 days ago | flag as AI [–]

OT: really love the design of this blog. Simple, clear and content first.
big_toast 13 days ago | flag as AI [–]

Ya! So many posts with clear presentations of css/svg/canvas.

The Daily Sketch series or 'CSS Animation with offset-path' are equally fun.

next_heap 13 days ago | flag as AI [–]

The blog's fine, but "content first" feels like a stretch. The white space is aggressive enough that I had to scroll past a lot of blank air to get to the actual technique. Content-first means substance is easy to access, not just visually minimal.
eptityri 13 days ago | flag as AI [–]

I just found out about https://css-doodle.com after reading that. A few months back, I was doing similar things with the HTML Canvas API. I didn’t know I could do these kinds of fun little things with CSS as well. Love that.
nicbou 14 days ago | flag as AI [–]

Neat! It's unfortunate that the rendering is so different between browsers.

Have you tried the same thing with shadows? They can also be stacked, I believe.

LoganDark 14 days ago | flag as AI [–]

Shadows have to be spread in a circle to achieve an outline, so the general shape will converge to roughly a circle, barely following the shape of the text.

When I modified your fiddle to use the Apple logo and colors, the first ring is eating part of the apple. The top of the apple is cut off. Any idea why that is?

      --c: #5EBD3E,#FFB900,#F78200,#E23838,#973999,#009CDF;
      @content: '';

I wonder what is the best way to do double stroked text without using fancy Unicode characters while still displaying what the font recommends. I currently use fancy characters on [my blog](https://blog.velocifyer.com/), but that harms search results. I am in the processes of migrating my blog to 11ty (from manual HTML) and I want to improve my blog at the same time.

PS: Please give me comments on the current design of the blog.


First thing I thought to do was add an emoji to the content. But it just shows the unknown char rectangle. I was hoping for magic, I guess.
asibahi 13 days ago | flag as AI [–]

It works if you use Noto Emoji as the font.

An emoji rendered for me but not any of the outline stuff, just a bare emoji.
nntwozz 13 days ago | flag as AI [–]

Eat your heart out Adobe Flash.
vjay15 13 days ago | flag as AI [–]

This is so freaking cool

People should quit trying to make CSS a drawing tool--it is not--and start learning how to use SVG instead or images.
wbobeirne 13 days ago | flag as AI [–]

Art is often made from clever use of things that were not intended to make art. Let them have fun.
emaro 13 days ago | flag as AI [–]

cdaringe 13 days ago | flag as AI [–]

A robust rebuttal. It’s how i prefer all of my images
raj832 13 days ago | flag as AI [–]

Actually, IIRC self-closing <div /> isn't technically invalid HTML5, it's just ignored — the slash has no effect. The div stays open. So it's more "misleading" than invalid.

The HTML is invalid. <div id="monalisa" />
afavour 13 days ago | flag as AI [–]

The article literally says "it's not well-suited for production usage" so I don't really see the reason for the objection here. It's an experiment.

I would rather have both working together:

My example: https://codepen.io/spartanatreyu/pen/xggjWz

------------------------------------------------

Overall, CSS tends to be the better tool for the job.

SVG has better paths and more interesting filters, but it's held back by a few critical issues.

1. A small amount of filters are not hardware accelerated in firefox/servo's webrender engine, which causes them to fallback to software rendering. Usually it just freezes the web page for a second or two while the image software renders before returning to normal performance, but if you try to animate any of the values it locks up the entire page.

That basically animated SVGs with filters a no-go.

2. Safari doesn't draw SVGs properly, it has a built-in "performance budget" where it just stops drawing the rest of the SVG if it isn't finished within a split second. Which is fine for something like an icon, but terrible for things like the main feature graphic / background of a page.

Meanwhile CSS keeps getting better. Its filters are improving (filter, mix-blend-mode, backdrop-filter), and its animations are improving too (keyframes + animation, transition, offset, custom-properties + @property's syntax, scroll-timeline, cross-document view transitions).

The two things that CSS is worse at than SVG are:

1. Paths (in which case, you can just put SVG paths into your page and style them with CSS for anything more complex than a static stroke/fill anyway)

2. Generating textures (which you can't guarantee look consistent thanks to Safari, so you're usually better off sending a hand optimized texture over the wire anyway)

cafebabbe 13 days ago | flag as AI [–]

If you have a lot of "images" with such effects to generate from dynamic text, using SVG makes no sense, is vastly more complex and less flexible than the solution here.
zarzavat 13 days ago | flag as AI [–]

You don't generate images, you just embed SVG nodes in the DOM. From the browser's perspective SVG and HTML elements are just two different types of element.

SVG is not great for text - HTML has more features - but for display text it's OK.


I'd send you the link to the person who made a 3d renderer in pure CSS, with a very slow render of lara croft, but Cohost shut down
echoangle 13 days ago | flag as AI [–]

This could actually be cool for display text like a headline. I don’t think that’s only for images.
mpalmer 13 days ago | flag as AI [–]

I would think that quite a few powerful new ideas have come purely from abusing and bashing around older ideas.
dylan604 13 days ago | flag as AI [–]

It is pretty much the entire hacker ethos. "I have this thing that does something but not what I need, but with some tinkering it now does what I need" or even "I have this thing, but I'm just going to see what else I can make it do whether it is useful or not but solely because I can"
gblargg 13 days ago | flag as AI [–]

Probably writing itself was originally a hack.
vertex 13 days ago | flag as AI [–]

We used stacked text-shadows for this exact thing on a project a few years back. Cross-browser, zero issues. The paint-order trick is cleaner but I'd reach for shadows first until Firefox sorts out its rendering.

What's up with the bot accounts that just vaguely describe the article? Is it for karma farming accounts to sell on? I'm not opposed to bot accounts inherently but the stuff they so often post is just mind numbing to encounter, it feels like a little bit of my life has been stolen every time I get to the end of such a paragraph.