Robin Rendle – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Tue, 20 Dec 2022 17:42:26 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 Robin Rendle – CSS-Tricks https://css-tricks.com 32 32 45537868 Care for the Text https://css-tricks.com/care-for-the-text/ https://css-tricks.com/care-for-the-text/#comments Fri, 24 Dec 2021 12:33:11 +0000 https://css-tricks.com/?p=358565 How do you make a great website? Everyone has an answer at the ready: Flashy animations! The latest punk-rock CSS trick! Gradients! Illustrations! Colors to pack a punch! Vite! And, sure, all these things might make a website better. But …


Care for the Text originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
How do you make a great website? Everyone has an answer at the ready: Flashy animations! The latest punk-rock CSS trick! Gradients! Illustrations! Colors to pack a punch! Vite! And, sure, all these things might make a website better. But no matter how fancy the application is or how dazzling the technology will ever be under the hood, a great website will always require great text.

So, whenever I’m stuck pondering the question: “how do I make this website better?” I know the answer is always this:

care for the text.

Without great writing, a website is harder to read, extremely difficult to navigate, and impossible to remember. Without great writing, it’s hardly a website at all. But it’s tough to remember this day in and day out—especially when it’s not our job to care about the text—yet each and every <p> tag and <button> element is an opportunity for great writing. It’s a moment to inject some humor or add a considerate note that helps people.

So: care for the text. Got it. But there are so many ways to care! From commas and smart quotes, to labels in our forms, to typography, and even the placeholders in our inputs. It’s a dizzying amount of responsibility—but it’s worth every second of our time.

Here’s one example: a while ago, we needed to explain a new feature to our users and point to it in the UI. We could use our pop-up component to explain how our team just fixed something for a ton of folks—but!—I knew that no matter what the fancy new feature was, our customers would be annoyed by a pop-up.

After thinking about it for far too long I realized that this was an opportunity to acknowledge how annoying this popup was:

With this project, I could’ve just thrown some text in that button that says “Dismiss” but our little team of writers at Sentry constantly remind me that even the smallest, most boring block of text can be a playground. Each string has potential, even in this dumb example. It doesn’t change the world or anything, but it improves something that would otherwise be yawn-worthy, predictable.

Not every bit of text in a website needs to be passive-aggressive though. When you’re in the checkout ordering medicine, you likely don’t want to be reading a quirky story or a poem, and you don’t want to click a button that insults you. In this context, caring for the text means something entirely different. It’s about not getting in the way but being as efficient and empathetic as possible. And this is true of every link in the footer, every navigation item, every <alt> tag, and subtitle—they all require care and attention. Because all of these details add up.

These are the details that make a good website great.


Care for the Text originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/care-for-the-text/feed/ 4 358565
Yes, Design Systems Do Improve Developer Efficiency and Design Consistency https://css-tricks.com/yes-design-systems-do-improve-developer-efficiency-and-design-consistency/ https://css-tricks.com/yes-design-systems-do-improve-developer-efficiency-and-design-consistency/#comments Fri, 05 Nov 2021 19:58:37 +0000 https://css-tricks.com/?p=355888 One of the toughest things about being someone who cares deeply about design systems is making the case for a dedicated design system. Folks in leadership will often ask you to prove the value of it. Why should we care …


Yes, Design Systems Do Improve Developer Efficiency and Design Consistency originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
One of the toughest things about being someone who cares deeply about design systems is making the case for a dedicated design system. Folks in leadership will often ask you to prove the value of it. Why should we care about good front-end development and consistency? Sure, sure, sure, they say—everyone wants a flashy design system—but is it worth the cost?

That question is tough because developer productivity, front-end quality, and even accessibility to some extent, are all such nebulous things. In contrast, this is one of the smartest things about Google’s Core Web Vitals because it puts a number on the problem and provides very actionable things to do next.

When it comes to design systems, we don’t really have metrics that we can point to and say “Ah, yes, I need to put folks on the design systems team so that we can push our design system up from a bad score of 60/100.” It would be neat if we did, but I don’t think we ever will.

Enter Sparkbox. They wanted to fix this by testing how much faster their eight developers were in a little test. They got their devs to make a form, by hand, and then do it again using IBM’s Carbon design system, which they’d never used before.

The results are super interesting:

Using a design system made a simple form page 47% faster to develop versus coding it from scratch. The median time for the scratch submissions was 4.2 hours compared to the 2 hour median time for Carbon submissions. The Carbon timing included the time the developers spent familiarizing themselves with the design system.

Now imagine if those devs were familiar with Carbon’s design system! If that was the case, I imagine the time to build those forms would be way, way faster than those initial results.

To Shared LinkPermalink on CSS-Tricks


Yes, Design Systems Do Improve Developer Efficiency and Design Consistency originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/yes-design-systems-do-improve-developer-efficiency-and-design-consistency/feed/ 3 355888
Websites We Like: MD Nichrome https://css-tricks.com/websites-we-like-md-nichrome/ https://css-tricks.com/websites-we-like-md-nichrome/#comments Wed, 06 Oct 2021 22:24:18 +0000 https://css-tricks.com/?p=353219 Here’s a beautiful website: it’s a type specimen for Mass-Driver’s ever-so-lovely type family MD Nichrome. There’s a ton of nifty animations and graphics explaining all the features inside…

If you’re wondering how those animations work, they’re actually styled <video>


Websites We Like: MD Nichrome originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Here’s a beautiful website: it’s a type specimen for Mass-Driver’s ever-so-lovely type family MD Nichrome. There’s a ton of nifty animations and graphics explaining all the features inside…

If you’re wondering how those animations work, they’re actually styled <video> elements.

There’s lots of great graphic design touches as well, such as how the letters below trail off and fade away…

That little bit of CSS is neat. It makes sure that each <h1> stays on a single line with white-space, then sets hidden overflow on them so the heading trails off. The fading is courtesy of a linear gradient that incorporates transparency. The gradient is actually a mask-image in this case. That’s a good reminder that CSS gradients are images generated by the browser.

h1 {
  white-space: nowrap;
  overflow: hidden;
  -webkit-mask-image: linear-gradient(to right, black 75%, transparent);
}

In the image above you can also see how Mass-Driver is advertising the OpenType features of the font. That’s stuff like fractions or alternate letters that gives your text superpowers. By default, these sections show what the feature is, but when you hover over them they do the following:

.element {
  font-feature-setting: unset;
}

I don’t think I’ve ever used unset before but this is a great place to use it—show what the feature looks like up front and then when you hover show what the default is. Smart stuff.

But the part that caught my eye—besides the kick ass typography—is the background. It’s made up of two parts: a shimmery animation that makes the page look like paper, and the gradient that’s stacked on top of it. And after digging around in DevTools I realized that shimmering effect is a PNG image where the background-position property moves the picture around slightly to animate it like a GIF. It’s hard to see in pictures, so here’s a copycat demo I made with the opacity turned off to make it easier to see:

See that lovely fuzziness? It gives the background a kind of… texture… that I haven’t seen for a long time, perhaps since around 2008 when everyone was trying to make buttons look like real, analog buttons on the web. Geoff covered the same sort of technique a while back where you can get a deep dive into how it works.

The other part of the design of this website is the gradient in the background. How are those so smooth? Well, Rutherford Craze, the designer behind this ingenious bit of web design, made a thread explaining how he got this effect to work in the browser. He created a gradients tool that lets you create a similar effect:

Rutherford writes:

Conventional CSS gradients plot a straight line through colour space, interpolating directly from the start to the end colour. This tool applies the principles of bézier curves, the basis of digital fonts, to this operation.

By introducing ‘control points’ along the gradient, you can more finely control the interpolation and produce a smoother end result. The tool then samples this ‘bézier gradient’ to produce a linear gradient you can work with in CSS.

What Rutherford is describing above is what’s known as the “Gray Dead Zone” of gradients, where often in a linear gradient there’s this gray color that forms in the middle.

Another small detail that I almost didn’t catch was the sticky navigation: when you first load the website you just see the logo with nothing else, but then as you scroll you’ll see the nav and it locks into place:

Notice how sticky positioning is also used later on to demonstrate the font’s glyphs.

CSS makes this sort of thing so easy. Declare sticky positioning on the element, then offset the stickiness if the element should start sticking at a certain spot.

.sticky-thing {
  position: sticky;
  top: 75px;
}

Since they want you to focus on the letters first and not all the rest of the UI, it makes a ton of sense to put the navigation off to one side, only when you need it. And this makes the overall design feel incredibly focused and straightforward, barely worth commenting on at all perhaps, but when most websites are so full of distractions then I think it’s worth celebrating quiet websites like these.


Websites We Like: MD Nichrome originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/websites-we-like-md-nichrome/feed/ 1 353219
Designing Beautiful Shadows in CSS https://css-tricks.com/designing-beautiful-shadows-in-css/ https://css-tricks.com/designing-beautiful-shadows-in-css/#comments Fri, 17 Sep 2021 22:49:39 +0000 https://css-tricks.com/?p=352082 My favorite kind of blog post is when someone takes a subject that I’ve spent all of five minutes considering and then says—no!—this is an enormous topic worthy of a dissertation. Look at all the things you can do with …


Designing Beautiful Shadows in CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
My favorite kind of blog post is when someone takes a subject that I’ve spent all of five minutes considering and then says—no!—this is an enormous topic worthy of a dissertation. Look at all the things you can do with this tiny CSS property!

I was reminded of this when I spotted this post by Josh Comeau about designing beautiful shadows in CSS:

In my humble opinion, the best websites and web applications have a tangible “real” quality to them. There are lots of factors involved to achieve this quality, but shadows are a critical ingredient.

When I look around the web, though, it’s clear that most shadows aren’t as rich as they could be. The web is covered in fuzzy grey boxes that don’t really look much like shadows.

Josh shows the regular old boring shadow approaches and then explores all the ways to improve and optimize them into shadows with real depth. It all comes down to taking a closer look color and exploring the box-shadow CSS property. And speaking of depth, Rob O’Leary’s “Getting Deep Into Shadows” is another comprehensive look at shadows.

I had also completely forgotten about filter: drop-shadow; which is particularly useful on adding shadows to images that you want to throw onto a page. Great stuff all round.

To Shared LinkPermalink on CSS-Tricks


Designing Beautiful Shadows in CSS originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/designing-beautiful-shadows-in-css/feed/ 1 352082
kbar https://css-tricks.com/kbar/ https://css-tricks.com/kbar/#comments Wed, 15 Sep 2021 18:51:36 +0000 https://css-tricks.com/?p=351868 It’s not every day that a new pattern emerges across the web, but I think cmd + k is here to stay. It’s a keyboard shortcut that usually pops open a search UI and it lets you toggle settings on …


kbar originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
It’s not every day that a new pattern emerges across the web, but I think cmd + k is here to stay. It’s a keyboard shortcut that usually pops open a search UI and it lets you toggle settings on or off, such as dark mode. And lots of apps support it now—Slack, Notion, Linear, and Sentry (my current gig) are the ones that I’ve noticed lately, but I’m sure tons of others have started picking up on this pattern.

Speaking of which, this looks like a great project:

kbar is a fully extensible command+k interface for your site

My only hope is that more websites and applications start to support it in the future—with kbar being a great tool to help spread the good word about this shortcut.

To Shared LinkPermalink on CSS-Tricks


kbar originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/kbar/feed/ 7 351868
Stay alert https://css-tricks.com/stay-alert/ https://css-tricks.com/stay-alert/#comments Thu, 12 Aug 2021 21:10:22 +0000 https://css-tricks.com/?p=346608 A few days ago, Chris wrote up his thoughts about how alert(), confirm(), and prompt() were being deprecated by Chrome and collected a bunch of thoughts from developers. If certain features can essentially be turned off by …


Stay alert originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
A few days ago, Chris wrote up his thoughts about how alert(), confirm(), and prompt() were being deprecated by Chrome and collected a bunch of thoughts from developers. If certain features can essentially be turned off by a major browser, a lot of folks started to worry about the predictability of the web.

On that note, I really liked this note by Richard Harris:

We can’t normalise the attitude that collateral damage is the price of progress, even if we accept the premise — which I don’t — that removing APIs like alert represents progress. For all its flaws, the web is generally agreed to be a stable platform, where investments made today will stand the test of time. A world in which websites are treated as inherently transient objects, where APIs we commonly rely on today could be cast aside as unwanted baggage by tomorrow’s spec wranglers, is a world in which the web has already lost.

This specific bit of drama isn’t of much interest to me, I must admit. But! I think it brings up a super important distinction between software and the web. Here’s a story.

The other day I was faffing about with Astro (which I like a lot). I was rebuilding my personal site with it and I decided — in a spark of punk rock-ness — to update to the latest version of it. I thought perhaps it might make my build process a bit quicker and give me a chance to explore new features. But alas — everything broke. APIs had been deprecated! My build process broke! Everything crumbled down around me.

This isn’t me dunking on Astro. I love it, still. But it’s important to remember that Astro isn’t the web. Neither is React or any other framework, really. Those teams can feel free to deprecate things, improve things as much as they want. They can burn it all to the ground and start again. But stuff like alert(), old CSS features, and HTML elements aren’t in the same category. They can’t be deprecated in the same way because, as Jeremy said, the web needs to be predictable. And we can’t treat the web like plain ol’ software because no one team or individual owns those features.

Here’s the gist of my rant: alert() and confirm() aren’t features of Chrome, but of the web. But I fear that’s how a lot of folks might think about them.

This is also why standards are so important! Talking about new features in public lets us fix all the bugs and answer all the questions before a new feature ships onto this platform where you can’t just delete it when you realize you goofed up. I’m not even really dunking on Chrome here either, but this distinction between software and the open web is an important one to make. Right?

To Shared LinkPermalink on CSS-Tricks


Stay alert originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/stay-alert/feed/ 7 346608
CSS Nesting, specificity, and you https://css-tricks.com/css-nesting-specificity-and-you/ https://css-tricks.com/css-nesting-specificity-and-you/#comments Tue, 10 Aug 2021 14:51:39 +0000 https://css-tricks.com/?p=346355 Here’s Kilian Valkhof on CSS nesting which isn’t available in browsers yet, but will be soon. There are a few differences he notes between CSS nesting and nesting in Sass or Less though. Take, for example, the following code:

div 


CSS Nesting, specificity, and you originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Here’s Kilian Valkhof on CSS nesting which isn’t available in browsers yet, but will be soon. There are a few differences he notes between CSS nesting and nesting in Sass or Less though. Take, for example, the following code:

div {
  background: #fff;
  & p {
    color: red;
  }
  border: 1px solid;
}

When CSS nesting lands, that last line border: 1px solid; won’t be applied to the div like it would be in, say, Sass. That’s because with CSS nesting, any styles you want applied to that div have to be written before any nesting styles are written. I think this makes a ton of sense because I tend to enforce that style in any Sass codebases I work on (it’s just much easier to read), but I can imagine people getting confused about this the first time around.

One of the smaller and, yet for some reason, super exciting things about CSS nesting is how we’ll be able to nest media queries, as Kilian notes, just like this:

body {
  background: red;
  
  @media (min-width: 40rem) {
    & {
      background: blue;
    }
  }
}

This is very exciting!

To Shared LinkPermalink on CSS-Tricks


CSS Nesting, specificity, and you originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/css-nesting-specificity-and-you/feed/ 2 346355
The Nine States of Design https://css-tricks.com/the-nine-states-of-design/ https://css-tricks.com/the-nine-states-of-design/#respond Tue, 20 Jul 2021 23:34:53 +0000 https://css-tricks.com/?p=345062 Here’s a really good ol’ post from way back in 2015 all about the nine states of design and how we should think all the edge cases whenever we’re building interfaces. Vince Speelman writes:

Modern UI teams are designing components


The Nine States of Design originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Here’s a really good ol’ post from way back in 2015 all about the nine states of design and how we should think all the edge cases whenever we’re building interfaces. Vince Speelman writes:

Modern UI teams are designing components first; Interfaces are merely the thoughtful composition of components. This leaves an often glaring hole for users on “the unhappy path” — The places where users may, intentionally or not, stray from your idealized flow. As we learn to craft systems rather than pages, we must invest effort into shaping these often missed states of design and create with a component lifecycle that can support everyone. Here’s the lifecycle as I see it:


  1. Nothing state
  2. Loading
  3. None
  4. One
  5. Some
  6. Too many
  7. Incorrect
  8. Correct
  9. Done

During the design process I think everyone (including me!) tends to focus on the ideal state of a component or interface, often leaving the extremely important edge cases forgotten until the last moment. I think I need to stick this list to my screen so I don’t forget it in my next project.

To Shared LinkPermalink on CSS-Tricks


The Nine States of Design originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/the-nine-states-of-design/feed/ 0 345062
The Web’s Worst Default https://css-tricks.com/the-webs-worst-default/ https://css-tricks.com/the-webs-worst-default/#comments Wed, 07 Jul 2021 14:30:34 +0000 https://css-tricks.com/?p=343388 There are a lot of great defaults when it comes to browsers and the web. Think about all the accessibility features that are baked into HTML so that you don’t have to do weird stuff, like this example from Manuel


The Web’s Worst Default originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
There are a lot of great defaults when it comes to browsers and the web. Think about all the accessibility features that are baked into HTML so that you don’t have to do weird stuff, like this example from Manuel:

<h2 role="heading" aria-level="1" class="sr-only">
  Title
</h2>

You can just write your <h2> and the browser deals with the accessibility parts. This is why we should start with semantic HTML first before adding ARIA roles to everything.

There are other great defaults of the modern web, like responsive design: a lot of folks have mentioned that the web is responsive by default and it’s actually us web developers that break it.

Then there are defaults when it comes to CSS. I’m thinking of stuff like flex. It feels pretty darn good to slap display: flex onto a parent element and all the children just snap next to each other since that’s mostly what I want to accomplish.

So: defaults on the web are good!

But there’s also a lot of bad defaults. You might be familiar with my favorite website, an Incomplete List of Mistakes in the Design of CSS, where the CSS Working Group lists out a ton of problems in the CSS spec such as:

size should have been a shorthand for width and height instead of an @page property with a different definition

These defaults are annoying, some minor, some major. And some of them can be fixed, like the box-sizing CSS property. Yes, there was a time on the web when even adding padding, borders, or width to an element would be confusing as all heck. Now we don’t have to worry about that quite so much.

But I think the absolute worst default on the web was the backspace key—in most browsers, it would force users to go back to the previous page. There have been countless times where I’ve tried to remove text in an input field and suddenly I would be dragged back to the last page I was on and all my data would be lost. That sort of thing makes typing into forms feel so fragile, as if at any moment you might exhale and your entire house implodes.

Side note: I think this is why a lot of folks prefer native over the web. They feel how fragile the web is when it comes to these default settings. When you load an app it feels like you’re on solid ground but a web app? It’s a rickety house that’s ready to fall apart at any moment.

Anyway, I didn’t even realize that Chrome removed the backspace key shortcut way back in 2016! Firefox also removed it earlier this year and yet, to this very day, five years later, I’m still scared of clicking that darn backspace key. I’ll always hesitate if I click the wrong key and then, very slowly, I’ll make sure that I’m focused on the correct input, unless I nuke all my data in the form.

I think this is kind of a good lesson when designing software: first, default settings are the most important thing in the world and are very difficult to get right; second, even if you do the right thing and fix all those bad defaults, habits are extremely hard to break.


The Web’s Worst Default originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/the-webs-worst-default/feed/ 7 343388
How to Show Images on Click https://css-tricks.com/how-to-show-images-on-click/ https://css-tricks.com/how-to-show-images-on-click/#comments Thu, 27 May 2021 14:25:29 +0000 https://css-tricks.com/?p=341020 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 …


How to Show Images on Click originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
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.

Thankfully, this is mostly a design problem today because making images performant and more user-friendly is so much easier than it once was. We have better image formats like WebP (and soon, perhaps, JPEG XL). We have the magic of responsive images of course. And there are tons of great tools out there, like ImageOptim, as well as resources such as Addy Osmani’s new book.

Although perhaps my favorite way to improve image performance is with lazy loading:

<img href="image.webp" alt="Image description" loading="lazy">

This image will only load when a user scrolls down the page so it’s visible to the user — which removes it from the initial page load and that’s just great! Making that initial load of a webpage lightning fast is a big deal.

But maybe there are images that should never load at all. Perhaps there are situations where it’d be better if a person could opt-into seeing it. Here’s one example: take the text-only version of NPR and click around for a bit. Isn’t it… just so great?! It’s readable! There’s no junk all over the place, it respects me as a user and — sweet heavens — is it fast.

Did I just show you an image in a blog post that insults the very concept of images? Yep! Sue me.

So! What if we could show images on a website but only once they are clicked or tapped? Wouldn’t it be neat if we could show a placeholder and swap it out for the real image on click? Something like this:

Well, I had two thoughts here as to how to build this chap (the golden rule is that there’s never one way to build anything on the web).

Method #1: Using <img> without a src attribute

We can remove the src attribute of an <img> tag to hide an image. We could then put the image file in an attribute, like data-src or something, just like this:

<img data-src="image.jpg" src="" alt="Photograph of hot air balloons by Musab Al Rawahi. 144kb">

By default, most browsers will show a broken image icon that you’re probably familiar with:

Okay, so it’s sort of accessible. I guess? You can see the alt tag rendered on screen automatically, but with a light dash of JavaScript, we can then swap out the src with that attribute:

document.querySelectorAll("img").forEach((item) => {
  item.addEventListener("click", (event) => {
    const image = event.target.getAttribute("data-src");
    event.target.setAttribute("src", image);
  });
});

Now we can add some styles and ugh, oh no:

Ugh. In some browsers there’ll be a tiny broken image icon in the bottom when the image hasn’t loaded. The problem here is that browsers don’t give you a way to remove the broken image icon with CSS (and we probably shouldn’t be allowed to anyway). It’s a bit annoying to style the alt text, too. But if we remove the alt attribute altogether, then the broken image icon is gone, although this makes the <img> unusable without JavaScript. So removing that alt text is a no-go.

As I said: Ugh. I don’t think there’s a way to make this method work (although please prove me wrong!).

The other option we have is to start with the humble hyperlink, like this:

<a href="image.jpg">Photograph of hot air balloons by Musab Al Rawahi. 144kb<a>

Which, yep, nothing smart happening yet — this will just render a link to an image:

That works accessibility-wise, right? If we don’t have any JavaScript, then all we have is just a link that folks can optionally click. Performance-wise, it can’t get much faster than plain text!

But from here, we can reach for JavaScript to stop the link from loading on click, grab the href attribute within that link, create an image element and, finally, throw that image on the page and remove the old link once we’re done:

document.querySelectorAll(".load-image").forEach((item) => {
  item.addEventListener("click", (event) => {
    const href = event.target.getAttribute("href");
    const newImage = document.createElement("img");
    event.preventDefault();
    newImage.setAttribute("src", href);
    document.body.insertBefore(newImage, event.target);
    event.target.remove();
  });
});

We could probably style this placeholder link to make it look a bit nicer than what I have below. But this is just an example. Go ahead and click the link to load the image again:

And there you have it! It isn’t groundbreaking or anything, and I’m sure someone’s done this before at some point or another. But if we wanted to be extremely radical about performance beyond the first paint and initial load, then I think this is an okay-ish solution. If we’re making a text-only website then I think this is definitely the way to go.

Perhaps we could also make a web component out of this, or even detect if someone has prefers-reduced-data and then only load images if someone has enough data or something. What do you think?


How to Show Images on Click originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/how-to-show-images-on-click/feed/ 11 341020
The Almost-Complete Guide to Cumulative Layout Shift https://css-tricks.com/the-almost-complete-guide-to-cumulative-layout-shift/ https://css-tricks.com/the-almost-complete-guide-to-cumulative-layout-shift/#comments Thu, 22 Apr 2021 19:04:48 +0000 https://css-tricks.com/?p=339053 Here’s Jess B. Peck writing all about Google’s Core Web Vitals:

Let’s step back one. CLS is when you’re about to click on a link, and the whole page shifts and you click on a different link instead. It’s when


The Almost-Complete Guide to Cumulative Layout Shift originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Here’s Jess B. Peck writing all about Google’s Core Web Vitals:

Let’s step back one. CLS is when you’re about to click on a link, and the whole page shifts and you click on a different link instead. It’s when you’re halfway through a blogpost and an ad loads and you lose your place. It is when… the layout shifts. At least, that’s what it’s trying to measure– both those shifts, how often they happen, and the irritation that causes the user.

I didn’t quite understand just how complex Cumulative Layout Shift is before reading Jess’s piece. As Jess explains:

CLS is a measure for a robot to approximate the user perception of instability. This means we’re getting a unit of change over time. It’s a three dimensional equation, and there are tons of things that can affect it. […] The idea is more to alert devs to a problem area, rather than be a perfect measurement of how annoying a page is.

I had this problem on, of all places, Google dot com. I kept tapping an element just as it appeared on screen and this sent me to the wrong page.

Jess notes that these metrics are sometimes more of an art than a science, and so we shouldn’t be obsessed with making sure that just these Core Web Vital metrics are okay. Chris mentioned a while ago that he worries folks might begin to game these metrics for improving their SEO:

This feels like the start of a weird new era of web performance where the metrics of web performance have shifted to user-centric measurements, but people are implementing tricky strategies to game those numbers with methods that, if anything, slightly harm user experience.

Harry Roberts mentioned something similar:

I feel like this is our responsibility as web developers, to explain that what we want to do here is reduce user misery on our websites. That’s not to say it’s easy, though, and there’s certainly not much we can do to avoid the shady folks who’ll game these metrics only to improve SEO.

As Jeremy wrote just the other day:

The map is not the territory. The numbers are a proxy for user experience, but it’s notoriously difficult to measure intangible ideas like pain and frustration.

To Shared LinkPermalink on CSS-Tricks


The Almost-Complete Guide to Cumulative Layout Shift originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/the-almost-complete-guide-to-cumulative-layout-shift/feed/ 4 339053
Say Hello to CSS Container Queries https://css-tricks.com/say-hello-to-css-container-queries/ https://css-tricks.com/say-hello-to-css-container-queries/#comments Tue, 20 Apr 2021 14:21:44 +0000 https://css-tricks.com/?p=338521 Container queries are finally here! Now available behind a flag in the latest version of Chrome Canary, you can go ahead and experiment to your heart’s content. Oh, and if you’re not familiar with container queries then check out …


Say Hello to CSS Container Queries originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Container queries are finally here! Now available behind a flag in the latest version of Chrome Canary, you can go ahead and experiment to your heart’s content. Oh, and if you’re not familiar with container queries then check out this post by Ethan Marcotte about why they’re so dang important.

Ahmad Shadeed described his excitement and showcased a ton of great use cases for problems that container queries solves:

I haven’t been more excited for a CSS feature like I’m now in the past six years I spent as a front-end developer. The prototype of container queries is now available behind a flag in Chrome Canary. Thanks to efforts from smart people like Miriam Suzanne and other folks.

I remember seeing a lot of jokes about the support for CSS container queries, but they are finally there.

Once you’ve activated the feature in chrome://flags you can then begin to write code like this:

.parent {
  container: layout inline-size;
}

@container (min-width: 400px) {
  .child {
    display: flex;
    flex-wrap: wrap;
  }
}

First off, you need to tell the parent component that a child needs to change size (that’s the container: layout inline-size part). Next, you can use a new kind of query called @container which will detect when the parent of an element changes width.

Andy Bell also made a bunch of great examples when he argued that we often need elements to change based on the size of the parent element more so than the width of the browser window, especially when it comes to typography:

Most importantly with container queries, we can set typography contextually! This for me is the most needed feature in design system implementations and why I constantly wish we had container queries. We can respond with media queries and set font sizes etc that way, but when you have no idea where an element will end up, this isn’t an ideal approach. Now we have container queries, we can make type adjustments that actually make sense a lot easier than before.

This post reminds me that Miriam Suzanne made an excellent proposal where you can read more about how container queries were designed and all the various snaffus and problems that came up along the way. It’s so neat to see a document like this that shows CSS being improved in public.

Personally, I believe this is the biggest improvement to CSS since Grid. It opens up all sorts of elegant solutions to problems we work around on a daily basis. I hit a snag just the other day when I wanted to set the type of an element in a sidebar depending on the width of the element wrapping it. And gah — it just wasn’t possible without introducing a bunch of weird hacks!

Container queries aren’t just some far-flung pipe dream now. They’re here to stay.

To Shared LinkPermalink on CSS-Tricks


Say Hello to CSS Container Queries originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/say-hello-to-css-container-queries/feed/ 8 338521
Where the World Wide Web Shines https://css-tricks.com/where-the-world-wide-web-shines/ https://css-tricks.com/where-the-world-wide-web-shines/#comments Wed, 31 Mar 2021 22:17:50 +0000 https://css-tricks.com/?p=336979 Here’s a fabulous post by Vitaly Friedman that looks at how to make accessible front-end components and what problems there are today when it comes to building them.

There’s so much great info packed into this one post that I’m …


Where the World Wide Web Shines originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Here’s a fabulous post by Vitaly Friedman that looks at how to make accessible front-end components and what problems there are today when it comes to building them.

There’s so much great info packed into this one post that I’m going to keep it open in a tab for quite some time. But I have two thoughts here. First, just skimming through the article is enough to make anyone realize that accessibility is a complex subject and it’s so very easy to get things wrong; colors, images, text, HTML, mouse pointer vs. touch, small screens vs. large screens, charts and data viz, form components, layout and semantic ordering. The list goes on and on. It’s clear to me now (and I am late to the party) that accessibility is a full-time job.

Second, Vitaly makes note of some of the excellent work that the Government Digital Service (GDS) is doing in the UK by releasing open-source components such as accessible-autocomplete. And I have to say, I think the work that GDS is doing is so very inspiring to me as a web designer and developer.

Here’s a story: a few years ago I had to book an appointment to get a driver’s license. I hopped on the website and, immediately, I recognized that it was using the GDS design system. That gave me a great sigh of relief, but then I found myself sailing through this form at lightning speed. By the end, I realized that this is what every website should feel like; I used the site, did what I needed to do as quickly as possible, and then left.

It was one of the most shocking experiences for me as a web designer because there was no cruft, no junk, and no messing around with the experience in any way. It was fast, didn’t break down, crash the browser, or confuse me at all. The form inputs were big and clickable and the correct keyboard was selected when I viewed it on my phone. All of this accessibility work that they’ve poured into making things just work is a joyous thing.

This reminds me of something that Jeremy Keith wrote about the other day when he used another government website to get vaccinated:

[…] it’s a sequence of short forms, clearly labelled. Semantic accessible HTML, some CSS, and nothing more. If your browser doesn’t support JavaScript (or you’ve disabled it for privacy reasons), that won’t make any difference to your experience. This is the design system in action and it’s an absolute pleasure to experience.

[…] Maybe I’ll never need to visit that URL again. In the case of the NHS, I hope I won’t need to visit again. I just need to get in, accomplish my task, and get out again. This is where the World Wide Web shines.

To Shared LinkPermalink on CSS-Tricks


Where the World Wide Web Shines originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/where-the-world-wide-web-shines/feed/ 3 336979
The Mobile Performance Inequality Gap https://css-tricks.com/the-mobile-performance-inequality-gap/ https://css-tricks.com/the-mobile-performance-inequality-gap/#comments Thu, 18 Mar 2021 19:26:19 +0000 https://css-tricks.com/?p=336548 Alex Russell made some interesting notes about performance and how it impacts folks on mobile:

[…] CPUs are not improving fast enough to cope with frontend engineers’ rosy resource assumptions. If there is unambiguously good news on the tooling front,


The Mobile Performance Inequality Gap originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Alex Russell made some interesting notes about performance and how it impacts folks on mobile:

[…] CPUs are not improving fast enough to cope with frontend engineers’ rosy resource assumptions. If there is unambiguously good news on the tooling front, multiple popular tools now include options to prevent sending first-party JS in the first place (Next.jsGatsby), though the JS community remains in stubborn denial about the costs of client-side script. Hopefully, toolchain progress of this sort can provide a more accessible bridge as we transition costs to a reduced-script-emissions world.

A lot of the stuff I read when it comes to performance is focused on America, but what I like about Russell’s take here is that he looks at a host of other countries such as India, too. But how does the rollout of 5G networks impact performance around the world? Well, we should be skeptical of how improved networks impact our work. Alex argues:

5G looks set to continue a bumpy rollout for the next half-decade. Carriers make different frequency band choices in different geographies, and 5G performance is heavily sensitive to mast density, which will add confusion for years to come. Suffice to say, 5G isn’t here yet, even if wealthy users in a few geographies come to think of it as “normal” far ahead of worldwide deployment

This is something I try to keep in mind whenever I’m thinking about performance: how I’m viewing my website is most likely not how other folks are viewing it.

To Shared LinkPermalink on CSS-Tricks


The Mobile Performance Inequality Gap originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/the-mobile-performance-inequality-gap/feed/ 4 336548
The CSS :has Selector (and 4+ Examples) https://css-tricks.com/the-css-has-selector/ https://css-tricks.com/the-css-has-selector/#comments Wed, 17 Mar 2021 18:40:16 +0000 https://css-tricks.com/?p=336424 The CSS :has selector helps you select elements when they contain other elements that match the selector you pass into :has().


The CSS :has Selector (and 4+ Examples) originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
The CSS :has selector helps you select elements that contain elements that match the selector you pass into the :has() function. It’s essentially a “parent” selector, although far more useful than just that. For example, imagine being able to select all <div>s but only when they contain a <p>. That’s what we can do:

div:has(p) {
  background: red;
}
/*
  <div> <!-- selected! -->
     <p></p>
  <div>

  <div></div> <!-- not selected -->
  <div> <!-- not selected -->
    <section></section>
  </div>
*/

Although it’s not supported in any browser as I write, it has now dropped in Safari Technical Preview 137, so it’s starting to happen!

Pretty darn handy right! Here’s another example. Say you want space after your headers. Of course! A bit of margin-block-end on your h2 should do it. But… what if there is a subtitle? Now we can select a parent on the condition a subtitle is present and adjust the spacing.

h2,
.subtitle {
  margin: 0 0 1.5rem 0;
}
.header-group:has(h2):has(.subtitle) h2 {
  margin: 0 0 0.2rem 0; /* reduce spacing on header, because subtitle will handle it */
}

/*
  <div class="header-group">
    <h2>Blog Post Title</h2> <!-- main spacing applied here -->
  </div>

  <div class="header-group">
    <h2>Blog Post Title</h2>
    <div class="subtitle"> <!-- main spacing applied here -->
      This is a subtitle
    </div>
  </div>
*/
The CSS :has selector being helpful in spacing headers with subtitles (or not).
On the left, the main spacing happens after the h2, on the right, the main spacing happens after the subtitle.

The way I think about :has is this: it’s a parent selector pseudo-class. That is CSS-speak for “it lets you change the parent element if it has a child or another element that follows it.” This might feel weird! It might break your mental model of how CSS works. This is how I’m used to thinking about CSS:

.parent .child {
  color: red;
}

You can only style down, from parent to child, but never back up the tree. :has completely changes this because up until now there have been no parent selectors in CSS and there are some good reasons why. Because of the way in which browsers parse HTML and CSS, selecting the parent if certain conditions are met could lead to all sorts of performance concerns.

If I sit down and think about all the ways I might use :has today, I sort of get a headache. It would open up this pandora’s box of opportunities that have never been possible with CSS alone.

Another example: let’s say we want to only apply styles to links that have images in them:

a:has(> img) {
  border: 20px solid white;
}

This would be helpful from time to time. I can also see :has being used for conditionally adding margin and padding to elements depending on their content. That would be neat.

The :has selector is part of the CSS Selectors Level 4 specification which is the same spec that has the extremely useful :not pseudo-class.


You could argue that the CSS :has selector is more powerful than just a “parent” selector, which is exactly what Bramus has done! Like in the subheadings example above, you aren’t necessarily ultimately selecting the parent, you might select the parent in a has-condition, but then ultimately select a child element from there.

/*  Matches <figure> elements that have a <figcaption> as a child element */
figure:has(figcaption) { … }

/* Matches <img> elements that is a child of a <figure> that contains a <figcaption> child element */
figure:has(figcaption) img { … }

There you can quickly see that the second selector is selecting a child <img>, not just the parent of the <figcaption>.

Selector List

You can chain it:

article:has(h2):has(ul) {

}

Or give it a selector list:

article:has(h2, ul) {

}

And the list is forgiving: The list is no longer “forgiving” after the W3C adopted a resolution in December 2020 in response to a reported issue. So, if the selector list contains even one invalid argument, the entire list is ignored:

/* 👎 */
article:has(h2, ul, ::-blahdeath) {
  /* ::blahdeath is invalid, making the entire selector invalid. */
}

A workaround is to nest a more forgiving selector in there, such as :is() or :where():

/* 👍 */
article:has(:where(h2, ul, ::-blahdeath)) {
  /* :where is a forgiving selector, making this valid. */
}

Testing for Support

@supports(selector(:has(p))) {
  /* Supported! */
}

The :not() selector is part of the same spec…

Unlike :has, :not does have pretty decent browser support and I used it for the first time the other day:

ul li:not(:first-of-type) {
  color: red;
}

That’s great I also love how gosh darn readable it is; you don’t ever have to have seen this line of code to understand what it does.

Another way you can use :not is for margins:

ul li:not(:last-of-type) {
  margin-bottom: 20px;
}

So every element that is not the last item gets a margin. This is useful if you have a bunch of elements in a card, like this:

… and also :is() and :where()

CSS Selectors Level 4 is also the same spec that has the :is selector that can be used like this today in a lot of browsers:

:is(section, article, aside, nav) :is(h1, h2, h3, h4, h5, h6) {
  color: #BADA55;
}

/* ... which would be the equivalent of: */
section h1, section h2, section h3, section h4, section h5, section h6, 
article h1, article h2, article h3, article h4, article h5, article h6, 
aside h1, aside h2, aside h3, aside h4, aside h5, aside h6, 
nav h1, nav h2, nav h3, nav h4, nav h5, nav h6 {
  color: #BADA55;
}

More Info

So that’s it! :has should be quite useful to use soon, and its cousins :is and :not can be fabulously helpful already and that’s only a tiny glimpse — just three CSS pseudo-classes — that are available in this new spec.


The CSS :has Selector (and 4+ Examples) originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/the-css-has-selector/feed/ 29 336424