Care for the Text

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.

Yes, Design Systems Do Improve Developer Efficiency and Design Consistency

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


The post Yes, Design Systems Do Improve Developer Efficiency and Design Consistency appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Websites We Like: MD Nichrome

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.


The post Websites We Like: MD Nichrome appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

kbar

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.

Direct Link to ArticlePermalink


The post kbar appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

Stay alert

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?

Direct Link to ArticlePermalink


The post Stay alert appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

The Nine States of Design

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.

Direct Link to ArticlePermalink


The post The Nine States of Design appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

The Web’s Worst Default

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 post The Web’s Worst Default appeared first on CSS-Tricks. You can support CSS-Tricks by being an MVP Supporter.

How to Show Images on Click

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!).

Method #2: Using links to create an image

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?


The post How to Show Images on Click appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

The Almost-Complete Guide to Cumulative Layout Shift

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.

Direct Link to ArticlePermalink


The post The Almost-Complete Guide to Cumulative Layout Shift appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Say Hello to CSS Container Queries

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 {
  contain: 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 contain: 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.

Direct Link to ArticlePermalink


The post Say Hello to CSS Container Queries appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Building Dark Mode

Like many companies, we have a Hack Week at Sentry. In 2017, we coded an app which blared entrance music for anyone who stepped foot in our office. In 2019, we encouraged folks to be nice on the Internet. Noble causes, sure, but for this year’s Hack Week I was determined to advance a cause near and dear to my cold British heart: dark mode.

Little did I know that what started as a minor hack week project would become a major lift that included pantone colors, hex codes, and all sorts of variables.

Where the World Wide Web Shines

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.

Direct Link to ArticlePermalink


The post Where the World Wide Web Shines appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

The Mobile Performance Inequality Gap

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.

Direct Link to ArticlePermalink


The post The Mobile Performance Inequality Gap appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Did You Know About the :has CSS Selector?

File this under stuff you don’t need to know just yet, but I think the :has CSS selector is going to have a big impact on how we write CSS in the future. In fact, if it ever ships in browsers, I think it breaks my mental model for how CSS fundamentally works because it would be the first example of a parent selector in CSS.

Before I explain all that, let’s look at an example:

div:has(p) {
  background: red;
}

Although it’s not supported in any browser today, this line of CSS would change the background of a div only if it has a paragraph within it. So, if there’s a div with no paragraphs in it, then these styles would not apply.

That’s pretty handy and yet exceptionally weird, right? Here’s another example:

div:has(+ div) { 
  color: blue; 
}

This CSS would only apply to any div that directly has another div following it.

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 is so utterly strange to me because it breaks with my mental model of how CSS works. This is how I’m used to thinking about CSS:

/* Not valid CSS, just an illustration */
.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.

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

Okay, one last 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.

Although :has isn’t supported in browsers right now (probably for those performance reasons), it is part of the CSS Selectors Level 4 specification which is the same spec that has the extremely useful :not pseudo-class. 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:

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;
}

So that’s it! :has might not be useful today but 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 post Did You Know About the :has CSS Selector? appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

The web didn’t change; you did

I love this piece from Remy Sharp where he argues that the web didn’t get more complicated over the last 20 years, despite what we might think:

Web development did not change. Web development grew. There are more options now, not different options.

Browsers have become more capable and still work with web pages built over 20 years ago.

[…] The web really didn’t change. It really didn’t become complex. The web development process is not one single path. There is simply more choice and more options.

Remy argues that the web is only really as complex as we make it and, when we choose an enormous framework for a small problem, it’s us that’s choosing the complexity. We really don’t have to build a website with the latest and greatest tools if we’re familiar with the old stuff and there’s no shame in using float over flexbox, if that works for you.


There’s a lot of ego in web design, and there’s a lot of folks out there bashing others for using the “incorrect” tools. But here’s the secret when it comes to making website: there are no perfect tools, and there’s no perfect way to build a website. That sucks, but it’s also exciting because we get to figure it all out; nothing is set in stone.

For example: I use Sass all the time for side projects and I know for a fact that a lotta folks would scoff at that. There’s emotion and Tachyons! There’s plain CSS! There’s PostCSS! But hey: I like Sass for a few things. I like the power it gives me and I like that I’m familiar with it. That doesn’t stop me from reaching for emotion in my day job or experimenting with something new when it comes along.

But old tech isn’t bad just because it’s old. And new tech isn’t good just because it’s new. You can see that sentiment playing out in the comment thread of Chris’ “Front-End Dissatisfaction (and Backing Off)” post.

Direct Link to ArticlePermalink


The post The web didn’t change; you did appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Is CSS float deprecated?

An interesting conversation came up at work the other day: Should we use the CSS float property now that we have CSS Grid and Flexbox?

The short answer

No! Well, mostly. I’d only use it today for wrapping text around images, though and I’d avoid using float entirely for layouts.

The longer, more annoying answer

Before flexbox and grid, we had to use the CSS float property to make grids and layouts. In fact, it was the first thing I learned about web design. On one hot summer afternoon I cracked open a copy of Designing with Web Standards by Jeffrey Zeldman and then moved a tiny red div with float: right. It was magic. There was power in the float.

It was so easy to move something around on the screen that I now wonder how many designers fell in love with the web simply because of how easy it is to use move things around like that.

But using float to build complex layouts was always a hack: it was only really designed to let text wrap around an image.

img {
  width: 150px;
  float: left;
}

The problems with float begin when we try to build giant layouts and magazine-style grids. But that’s what we had to do since there were no alternatives back then like we do today.

One problem with the float property is that you’d have to wrap floated elements with something called a clearfix that looked like this:

<div class="clearfix">
  <div class="float-left">Column</div>
  <div class="float-left">Column</div>
  <div class="float-left">Column</div>
</div>
clearfix:after {
  content: "";
  display: table;
  clear: both;
}

Jay Hoffman described the clearfix hack a while back:

The clearfix, for those unaware, is a CSS hack that solves a persistent bug that occurs when two floated elements are stacked next to each other. When elements are aligned this way, the parent container ends up with a height of 0, and it can easily wreak havoc on a layout. All you might be trying to do is position a sidebar to the left of your main content block, but the result would be two elements that overlap and collapse on each other. To complicate things further, the bug is inconsistent across browsers. The clearfix was invented to solve all that.

Things began to slowly change after that. Back in 2017, Rachel Andrew explained how browsers can handle the clearfix problem without any hacks at all. All we need is the following CSS to make the same fix:

.container {
  display: flow-root;
}

The odd thing is that I didn’t know the flow-root value existed until about three minutes before I typed that. But I guess this sort of defends the argument I’m about to make here: with CSS Grid and Flexbox we don’t really need float at all. The property was really designed to do one thing: let text wrap around images. But now, with grid and flexbox, we have wonderful powers that can do all the heavy lifting for real layouts.


Back to the argument I was having at work. Some folks said that we should go back and delete all the instances of float in our codebase because it’s old code and we can easily replace it with flexbox or grid. But this is where I’d say, Whoa! hold up a sec. I don’t think having the float property in a few places in our codebase is doing that much harm at all — this isn’t radioactive code that’s causing problems.

So should we be using CSS float for anything besides letting text wrap around text? Nope. But should we all go out and immediately purge the web of CSS float declarations because it’s not pure and not the “correct” way of doing things? Nope again.

The nifty thing about the web is that old code shouldn’t break things. Just ask Chris. A website that isn’t using the fanciest CSS properties or the coolest tricks isn’t useless or bad. We’ve simply replaced float with alternatives that are better. I think it’s a good lesson here that these CSS properties are likely going to stick around forever because they still have applicable use cases in modern web design.

And that’s okay.


The post Is CSS float deprecated? appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

A Whole Website in a Single HTML File

I can’t stop thinking about this site. It looks like a pretty standard fare; a website with links to different pages. Nothing to write home about except that… the whole website is contained within a single HTML file.

What about clicking the navigation links, you ask? Each link merely shows and hides certain parts of the HTML.

<section id="home">
  <!-- home content goes here -->
</section>
<section id="about">
  <!-- about page goes here -->
</section>

Each <section> is hidden with CSS:

section { display: none; }

Each link in the main navigation points to an anchor on the page:

<a href="#home">Home</a>
<a href="#about">About</a>

And once you click a link, the <section> for that particular link is displayed via:

section:target { display: block; }

See that :target pseudo selector? That’s the magic! Sure, it’s been around for years, but this is a clever way to use it for sure. Most times, it’s used to highlight the anchor on the page once an anchor link to it has been clicked. That’s a handy way to help the user know where they’ve just jumped to.

Anyway, using :target like this is super smart stuff! It ends up looking like just a regular website when you click around:

Direct Link to ArticlePermalink


The post A Whole Website in a Single HTML File appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

The End of Adobe Flash

I come to bury Flash, not to praise it, writes Matt May in this excellent thread about the end of Adobe Flash. Not so long ago, web designers used Flash to create striking visuals and animations and games. But shortly after that, it began to replace HTML and CSS which caused a ton of accessibility problems. Most Flash websites weren’t navigable by keyboard and screen readers couldn’t parse them at all.

Matt describes this core problem at the very heart of Flash: the fact that it excluded so many people from the web back then.

“A picture of an interface” is a good way to think about it. But, overall, I reckon this thread is important because it reinforces the idea that we ought to think about accessibility every single day, regardless of whether we’re working on a large web app, a tiny marketing website, or contributing to an enormous JavaScript framework:

Every day we write code, we’re deciding who is welcome and who is not.

Direct Link to ArticlePermalink


The post The End of Adobe Flash appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.