#253: 25 years of CSS, CSS font descriptors, and :nth-letter woes

[Robin]: Earlier this week I stumbled upon a problem where the only solution I could think of was a hypothetical one: an :nth-letter selector in CSS. It would work something like this:

.element:nth-letter(2) {
  color: red;
}

Similar to :nth-child, the CSS above would make the second letter in that word red. Yet, today no such thing exists, unfortunately. A while back Jeremy Keith wrote why he believes :nth-letter would be so darn useful and you’ve likely experienced this limitation, too. One common example is when you want to edit big display titles on a website, let’s say something like this:

Imagine we want to change the color of each of these letters in this word. Perhaps the best solution would be to make it an SVG or to wrap each letter in a span like this:

<h1>
  <span>r</span>
  <span>a</span>
  <span>i</span>
  <span>n</span>
  <span>b</span>
  <span>o</span>
  <span>w</span>  
  <span>!</span>  
</h1>

Pretty gross, right? It’s a shame that we have to mess up the markup simply to make a relatively simple aesthetic change.

Since we’ve been so very lucky with properties in CSS, I feel like this is now at the top of my CSS wishlist. It’s one of the few remaining challenges that have stuck around in web development since before I started and fixing it would help us make micro-typographic changes to the characters in a word or in a paragraph whilst encouraging folks to think about text in a different way on the web.

[Chris]: Ten years ago (2011), I wrote A Call for ::nth-everything. Not just letters, but words and lines too. Maybe even sentences. Wondering about use cases? Well, anything that uses Splitting.js for one (here’s a collection of demos).

Last I heard, I think the danger/pushback on all this is other languages. Like, there are some languages where one character also represents a word or phrase, so how do you design a feature like this that isn’t too biased toward English, and similarly-featured languages?

I believe the danger of the <span>s that Robin posted above is that screen readers (some, anyway?) read each of those characters with pauses in between, rather than just speaking “rainbow.” So, if you really want to do that to get the style, maybe try:

<h1>
  <span class="visually-hidden">rainbow</span>
  <span aria-hidden="true">
    <span>r</span>
    <span>a</span>
    <span>i</span>
    <span>n</span>
    <span>b</span>
    <span>o</span>
    <span>w</span>  
    <span>!</span>  
  </span>
</h1>

25 Years of CSS

Please forgive my snarky joke above (reference) because this is a really lovely piece by Eric Meyer about celebrating 25 years of CSS with a story of the first ever conference that he heard of the CSS language:

When I saw a single word turned a rich blue and 100-point size with just a single element and a few simple rules, I was utterly hooked. I still remember the buzzing tingle of excitement that encircled my head as I felt like I was seeing a real shift in the web’s power, a major leap forward, and exactly what I’d been holding out for.

[…] And it all kicked off 25 years ago this month in a conference room in Paris, May 7th, 1996. What a journey it’s been. I wonder now, in the latter half of my life, what CSS — what the web itself — will look like in another 25 years.


CSS Font Descriptors

Barry Pollard wrote this particularly excellent piece about the problem with webfonts today:

Font loading has long been a bugbear of web performance, and there really are no good choices here. If you want to use web fonts your choices are basically Flash of Invisible Text (aka FOIT) where the text is hidden until the font downloads or Flash of Unstyled Text (FOUT) where you use the fallback system font initially and then upgrade it to the web font when it downloads. Neither option has really “won out” because neither is really satisfactory, to be honest.

I’ve ignored this problem up until now, assuming that FOUT or FOIT were the only options we had and I should just live with it. And sure, today we could use tools like Font Style Matcher to make the switch between local and web fonts smoother but it is, as we say where I’m from, an enormous faff.

So if loading fonts today is pretty annoying and janky as heck, then how do we go about fixing them?

A potential solution is on the horizon: CSS font descriptors. These are CSS properties that help us manipulate a local font (like Arial) to make it match the webfont that we have to wait download (such as IBM Plex). When that fancy webfont has been downloaded we can then make the switch between the two much more gracefully than we could ever possibly do today. As a font nerd, I am very excited about this.

Right now there are four new CSS properties associated with this CSS font descriptors stuff: size-adjust, ascent-override, descent-override, and line-gap-override. I’m pretty darn excited to dig into these properties soon.


How to Show Images on Click

Lately we’ve had a ton of improvements ship in browsers but I still think there are performance problems:

Most images on the web are superfluous. If I might be a jerk for a bit, 99% of them aren’t even that helpful at all (although there are rare exceptions). That’s because images don’t often complement the text they’re supposed to support and instead hurt users, taking forever to load and blowing up data caps like some sort of performance tax.

So—if images aren’t great for performance—why don’t we hide them by default and then load them on click? What if images were optional?

Perhaps something like this:

We can make this accessible with the humble hyperlink and some JavaScript. On click, we fetch the resource in the href of the link and then create an img tag and delete <a> tag. Maybe this technique won’t take the world by storm or anything but I reckon it’s an interesting idea.

[Chris]: There are a couple of comments with ideas on doing it sans-JavaScript, like with the checkbox hack (demo), or using <details> (demo). The latter reminds me of how you can use <details> to pause a GIF.


Making GitHub’s homepage fast

Tobias Ahlin writes about how the team at GitHub improved performance of their homepage and made note of a few things that caught them by surprise:

[…] we also went through all of our animations and doubled down on one of the core tenets of optimizing animations: only animate the transform and opacity properties, since these properties are easier for browsers to animate (generally computationally less expensive). We thought we did a fairly good job of following this principle already, but we discovered that in some circumstances we did not, because unexpected properties were bleeding into our transitions and polluting them as elements changed state.

Tobias recommends avoiding transitions on all CSS properties, like this:

.animated {
  /* animation properties go here */
  transition: all 0.6s ease;
}

And instead we should list them all out:

.animated {
  /* animation properties go here */
  transition: opacity 0.6s ease, transform 0.6s ease;
}

Within this post there’s also an incredible trick where the team embeds a regular old JPEG image within an SVG to create a mask around the image so that it has a transparent background, just like a PNG except without all the performance overhead. They’re just doing that to support older browsers that don’t support .webp but it’s still a mighty hack nonetheless.

If you’re interested in more articles like this, then I’d check out Chris’s post where collects a few tutorials and blog posts about performance that he’s enjoyed recently.


Kintone Developer Program

Need a Web Database for your Hackathon project? Follow this step-by-step tutorial to learn how to spin up Web Databases ridiculously quickly. Accelerate your development with Kintone’s useful APIs and Tools. Get your free developer license now!


[Chris]: It’s interesting to see strongly differing opinions on ES Modules (e.g. native import and export in JavaScript). Sindre Sorhus is stoked about it, even though in Node-land, the change is much more tumultuous than it is in client-side JavaScript. Devon Govett thinks it was a waste of time.

Welp, ya can’t A/B test history. So it’ll have to remain a thought exercise on whether we think the JavaScript ecosystem would be in a healthier place if Node never even tried to support ES Modules. If the core question is was it worth it? There is no way to answer that question. Moving on is required.

Me, I think it’s worth fighting long, hard battles for better syntax, better interoperability, better naming, and as far as I know, better ride-along features. But most importantly for me is that it works in browsers. ES Modules is literally industry-changing, and we’re only at the beginning. Web components are evolving because of ES Modules. Next-gen bundlers are evolving because of ES Modules. CDNs are evolving because of ES Modules.