Journal tags: v

833

sparkline

Influence

Hidde gave a great talk recently called On the origin of cascades (by means of natural selectors):

It’s been 25 years since the first people proposed a language to style the web. Since the late nineties, CSS lived through years of platform evolution.

It’s a lovely history lesson that reminded me of that great post by Zach Bloom a while back called The Languages Which Almost Became CSS.

The TL;DR timeline of CSS goes something like this:

Håkon and Bert joined forces and that’s what led to the Cascading Style Sheet language we use today.

Hidde looks at how the concept of the cascade evolved from those early days. But there’s another idea in Håkon’s proposal that fascinates me:

While the author (or publisher) often wants to give the documents a distinct look and feel, the user will set preferences to make all documents appear more similar. Designing a style sheet notation that fill both groups’ needs is a challenge.

The proposed solution is referred to as “influence”.

The user supplies the initial sheet which may request total control of the presentation, but — more likely — hands most of the influence over to the style sheets referenced in the incoming document.

So an author could try demanding that their lovely styles are to be implemented without question by specifying an influence of 100%. The proposed syntax looked like this:

h1.font.size = 24pt 100%

More reasonably, the author could specify, say, 40% influence:

h2.font.size = 20pt 40%

Here, the requested influence is reduced to 40%. If a style sheet later in the cascade also requests influence over h2.font.size, up to 60% can be granted. When the document is rendered, a weighted average of the two requests is calculated, and the final font size is determined.

Okay, that sounds pretty convoluted but then again, so is specificity.

This idea of influence in CSS reminds me of Cap’s post about The Sliding Scale of Giving a Fuck:

Hold on a second. I’m like a two-out-of-ten on this. How strongly do you feel?

I’m probably a six-out-of-ten, I replied after a couple moments of consideration.

Cool, then let’s do it your way.

In the end, the concept of influence in CSS died out, but user style sheets survived …for a while. Now they too are as dead as a dodo. Most people today aren’t aware that browsers used to provide a mechanism for applying your own visual preferences for browsing the web (kind of like Neopets or MySpace but for literally every single web page …just think of how empowering that was!).

Even if you don’t mourn the death of user style sheets—you can dismiss them as a power-user feature—I think it’s such a shame that the concept of shared influence has fallen by the wayside. Web design today is dictatorial. Designers and developers issue their ultimata in the form of CSS, even though technically every line of CSS you write is a suggestion to a web browser—not a demand.

I wish that web design were more of a two-way street, more of a conversation between designer and end user.

There are occassional glimpses of this mindset. Like I said when I added a dark mode to my website:

Y’know, when I first heard about Apple adding dark mode to their OS—and also to CSS—I thought, “Oh, great, Apple are making shit up again!” But then I realised that, like user style sheets, this is one more reminder to designers and developers that they don’t get the last word—users do.

Dream speak

I had a double-whammy of a stress dream during the week.

I dreamt I was at a conference where I was supposed to be speaking, but I wasn’t prepared, and I wasn’t where I was supposed to be when I was supposed to be there. Worse, my band were supposed to be playing a gig on the other side of town at the same time. Not only was I panicking about getting myself and my musical equipment to the venue on time, I was also freaking out because I couldn’t remember any of the songs.

You don’t have to be Sigmund freaking Freud to figure out the meanings behind these kinds of dreams. But usually these kind of stress dreams are triggered by some upcoming event like, say, oh, I don’t know, speaking at a conference or playing a gig.

I felt really resentful when I woke up from this dream in a panic in the middle of the night. Instead of being a topical nightmare, I basically had the equivalent of one of those dreams where you’re back at school and it’s the day of the exam and you haven’t prepared. But! When, as an adult, you awake from that dream, you have that glorious moment of remembering “Wait! I’m not in school anymore! Hallelujah!” Whereas with my double-booked stress dream, I got all the stress of the nightmare, plus the waking realisation that “Ah, shit. There are no more conferences. Or gigs.”

I miss them.

Mind you, there is talk of re-entering the practice room at some point in the near future. Playing gigs is still a long way off, but at least I could play music with other people.

Actually, I got to play music with other people this weekend. The music wasn’t Salter Cane, it was traditional Irish music. We gathered in a park, and played together while still keeping our distance. Jessica has written about it in her latest journal entry:

It wasn’t quite a session, but it was the next best thing, and it was certainly the best we’re going to get for some time. And next week, weather permitting, we’ll go back and do it again. The cautious return of something vaguely resembling “normality”, buoying us through the hot days of a very strange summer.

No chance of travelling to speak at a conference though. On the plus side, my carbon footprint has never been lighter.

Online conferences continue. They’re not the same, but they can still be really worthwhile in their own way.

I’ll be speaking at An Event Apart: Front-end Focus on Monday, August 17th (and I’m very excited to see Ire’s talk). I’ll be banging on about design principles for the web:

Designing and developing on the web can feel like a never-ending crusade against the unknown. Design principles are one way of unifying your team to better fight this battle. But as well as the design principles specific to your product or service, there are core principles underpinning the very fabric of the World Wide Web itself. Together, we’ll dive into applying these design principles to build websites that are resilient, performant, accessible, and beautiful.

Tickets are $350 but I can get you a discount. Use the code AEAJER to get $50 off.

I wonder if I’ll have online-appropriate stress dreams in the next week? “My internet is down!”, “I got the date and time wrong!”, “I’m not wearing any trousers!”

Actually, that’s pretty much just my waking life these days.

Wildlife Photographer Of The Year on the Clearleft podcast

Episode three of the Clearleft podcast is here!

This one is a bit different. Whereas previous episodes focused on specific topics—design systems, service design—this one is a case study. And, wow, what a case study! The whole time I was putting the episode together, I kept thinking “The team really did some excellent work here.”

I’m not sure what makes more sense: listen to the podcast episode first and then visit the site in question …or the other way around? Maybe the other way around. In which case, be sure to visit the website for Wildlife Photographer Of The Year.

That’s right—Clearleft got to work with London’s Natural History Museum! A real treat.

Myself and @dhuntrods really enjoyed our visit to the digitisation department in the Natural History Museum. Thanks, Jen, Josh, Robin, Phaedra, and @scuff_el!

This episode of the podcast ended up being half an hour long. It should probably be shorter but I just couldn’t bring myself to cut any of the insights that Helen, James, Chris, and Trys were sharing. I’m probably too close to the subject matter to be objective about it. I’m hoping that others will find it equally fascinating to hear about the process of the project. Research! Design! Dev! This has got it all.

I had a lot of fun with the opening of the episode. I wanted to create a montage effect like the scene-setting opening of a film that has overlapping news reports. I probably spent far too long doing it but I’m really happy with the final result.

And with this episode, we’re halfway through the first season of the podcast already! I figured a nice short run of six episodes is enough to cover a fair bit of ground and give a taste of what the podcast is aiming for, without it turning into an overwhelming number of episodes in a backlog for you to catch up with. Three down and three to go. Seems manageable, right?

Anyway, enough of the backstory. If you haven’t already subscribed to the Clearleft podcast, you should do that. Then do these three things in whichever order you think works best:

Hey now

Progressive enhancement is at the heart of everything I do on the web. It’s the bedrock of my speaking and writing too. Whether I’m writing about JavaScript, Ajax, HTML, or service workers, it’s always through the lens of progressive enhancement. Sometimes I explicitly bang the drum, like with Resilient Web Design. Other times I don’t mention it by name at all, and instead talk only about its benefits.

I sometimes get asked to name some examples of sites that still offer their core functionality even when JavaScript fails. I usually mention Amazon.com, although that has other issues. But quite often I find that a lot of the examples I might mention are dismissed as not being “web apps” (whatever that means).

The pushback I get usually takes the form of “Well, that approach is fine for websites, but it wouldn’t work something like Gmail.”

It’s always Gmail. Which is odd. Because if you really wanted to flummox me with a product or service that defies progressive enhancement, I’d have a hard time with something like, say, a game (although it would be pretty cool to build a text adventure that’s progressively enhanced into a first-person shooter). But an email client? That would work.

Identify core functionality.

Read emails. Write emails.

Make that functionality available using the simplest possible technology.

HTML for showing a list of emails, HTML for displaying the contents of the HTML, HTML for the form you write the response in.

Enhance!

Now add all the enhancements that improve the experience—keyboard shortcuts; Ajax instead of full-page refreshes; local storage, all that stuff.

Can you build something that works just like Gmail without using any JavaScript? No. But that’s not what progressive enhancement is about. It’s about providing the core functionality (reading and writing emails) with the simplest possible technology (HTML) and then enhancing using more powerful technologies (like JavaScript).

Progressive enhancement isn’t about making a choice between using simpler more robust technologies or using more advanced features; it’s about using simpler more robust technologies and then using more advanced features. Have your cake and eat it.

Fortunately I no longer need to run this thought experiment to imagine what it would be like if something like Gmail were built with a progressive enhancement approach. That’s what HEY is.

Sam Stephenson describes the approach they took:

HEY’s UI is 100% HTML over the wire. We render plain-old HTML pages on the server and send them to your browser encoded as text/html. No JSON APIs, no GraphQL, no React—just form submissions and links.

If you think that sounds like the web of 25 years ago, you’re right! Except the HEY front-end stack progressively enhances the “classic web” to work like the “2020 web,” with all the fidelity you’d expect from a well-built SPA.

See? It’s not either resilient or modern—it’s resilient and modern. Have your cake and eat it.

And yet this supremely sensible approach is not considered “modern” web development:

The architecture astronauts who, for the past decade, have been selling us on the necessity of React, Redux, and megabytes of JS, cannot comprehend the possibility of building an email app in 2020 with server-rendered HTML.

HEY isn’t perfect by any means—they’ve got a lot of work to do on their accessibility. But it’s good to have a nice short answer to the question “But what about something like Gmail?”

It reminds me of responsive web design:

When Ethan Marcotte demonstrated the power of responsive design, it was met with resistance. “Sure, a responsive design might work for a simple personal site but there’s no way it could scale to a large complex project.”

Then the Boston Globe launched its responsive site. Microsoft made their homepage responsive. The floodgates opened again.

It’s a similar story today. “Sure, progressive enhancement might work for a simple personal site, but there’s no way it could scale to a large complex project.”

The floodgates are ready to open. We just need you to create the poster child for resilient web design.

It looks like HEY might be that poster child.

I have to wonder if its coincidence or connected that this is a service that’s also tackling ethical issues like tracking? Their focus is very much on people above technology. They’ve taken a human-centric approach to their product and a human-centric approach to web development …because ultimately, that’s what progressive enhancement is.

Service design on the Clearleft podcast

If you’re subscribed to the Clearleft podcast there’s a new episode winging its way across the airwaves to alight in your podcast software of choice.

This episode is all about service design. More precisely, it’s about me trying to understand what service design is. I don’t think I’m alone in being unsure of its meaning.

So in some ways, this is similar to the first episode, which involved a lot me asking “What exactly is a design system anyway?” But for the service design episode, rather than using interviews as my source material, I’ve dug into the archives of UX London. There are past talks on Clearleft’s Vimeo channel. I made plenty of use of presentations by Kerry Bodine, Jamin Hegeman, and Lou Downe.

That worked out well, but I felt there was still something missing from the episode. It needed a good story to wrap things up. So I cornered Rich for a chat about a project Clearleft worked on for Brighton council. That did the trick!

Again, there’s not much of me in this one. I’m there to thread the narrative together but my voice is not the one doing the explaining or the story-telling.

The episode ended up being almost half an hour long. Like I said before, rather than trying to squeeze each episode into a predefined timeslot, each episode will be as long as needs to be. And this one needed the time for Rich to tell his story.

Ooh, and I even tried adding in some sound effects during that part! It probably just sounds cheesy, but I’m still trying to figure out what works and what doesn’t.

Anyway, have a listen to this episode and see what you think. It’s got dead badgers, Downton Abbey, icebergs, and airplanes. Service design really does encompass a lot!

Accessibility

There’s a new project from Igalia called Open Prioritization:

An experiment in crowd-funding prioritization of new feature implementations for web browsers.

There is some precedent for this. There was a crowd-funding campaign for Yoav Weiss to implement responsive images in Blink a while back. The difference with the Open Prioritization initiative is that it’s also a kind of marketplace for which web standards will get the funding.

Examples include implementing the CSS lab() colour function in Firefox or implementing the :not() pseudo-class in Chrome. There are also some accessibility features like the :focus-visible pseudo-class and the inert HTML attribute.

I must admit, it makes me queasy to see accessibility features go head to head with other web standards. I don’t think a marketplace is the right arena for prioritising accessibility.

I get a similar feeling of discomfort when a presentation or article on accessibility spends a fair bit of time describing the money that can be made by ensuring your website is accessible. I mean, I get it: you’re literally leaving money on the table if you turn people away. But that’s not the reason to ensure your website is accessible. The reason to ensure that your website is accessible is that it’s the right thing to do.

I know that people are uncomfortable with moral arguments, but in this case, I believe it’s important that we keep sight of that.

I understand how it’s useful to have the stats and numbers to hand should you need to convince a sociopath in your organisation, but when numbers are used as the justification, you’re playing the numbers game from then on. You’ll probably have to field questions like “Well, how many screen reader users are visiting our site anyway?” (To which the correct answer is “I don’t know and I don’t care”—even if the number is 1, the website should still be accessible because it’s the right thing to do.)

It reminds of when I was having a discussion with a god-bothering friend of mine about the existence or not of a deity. They made the mistake of trying to argue the case for God based on logic and reason. Those arguments didn’t hold up. But had they made their case based on the real reason for their belief—which is faith—then their position would have been unassailable. I literally couldn’t argue against faith. But instead, by engaging in the rules of logic and reason, they were applying the wrong justification to their stance.

Okay, that’s a bit abstract. How about this…

In a similar vein to talks or articles about accessibility, talks or articles about diversity often begin by pointing out the monetary gain to be had. It’s true. The data shows that companies that are more diverse are also more profitable. But again, that’s not the reason for having a diverse group of people in your company. The reason for having a diverse group of people in your company is that it’s the right thing to do. If you tie the justification for diversity to data, then what happens should the data change? If a new study showed that diverse companies were less profitable, is that a reason to abandon diversity? Absolutely not! If your justification isn’t tied to numbers, then it hardly matters what the numbers say (though it does admitedly feel good to have your stance backed up).

By the way, this is also why I don’t think it’s a good idea to “sell” design systems on the basis of efficiency and cost-savings if the real reason you’re building one is to foster better collaboration and creativity. The fundamental purpose of a design system needs to be shared, not swapped out based on who’s doing the talking.

Anyway, back to accessibility…

A marketplace, to me, feels like exactly the wrong kind of place for accessibility to defend its existence. By its nature, accessibility isn’t a mainstream issue. I mean, think about it: it’s good that accessibility issues affect a minority of people. The fewer, the better. But even if the number of people affected by accessibility were to trend downwards and dwindle, the importance of accessibility should remain unchanged. Accessibility is important regardless of the numbers.

Look, if I make a website for a client, I don’t offer accessibility as a line item with a price tag attached. I build in accessibility by default because it’s the right thing to do. The only way to ensure that accessibility doesn’t get negotiated away is to make sure it’s not up for negotiation.

So that’s why I feel uncomfortable seeing accessibility features in a popularity contest.

I think that markets are great. I think competition is great. But I don’t think it works for everything (like, could you imagine applying marketplace economics to healthcare or prisons? Nightmare!). I concur with Iain M. Banks:

The market is a good example of evolution in action; the try-everything-and-see-what- -works approach. This might provide a perfectly morally satisfactory resource-management system so long as there was absolutely no question of any sentient creature ever being treated purely as one of those resources.

If Igalia or Mozilla or Google or Apple implement an accessibility feature because they believe that accessibility is important and deserves prioritisation, that’s good. If they implement the same feature just because it received a lot of votes …that doesn’t strike me as a good thing.

I guess it doesn’t matter what the reason is as long as the end result is the same, right? But I suspect that what we’ll see is that the accessibility features up for bidding on Open Prioritization won’t be the winners.

Putting design principles into action

I was really looking forward to speaking at An Event Apart this year. I was going to be on the line-up for Seattle, Boston, and Minneapolis; three cities I really like.

At the start of the year, I decided to get a head-start on my new talk so I wouldn’t be too stressed out when the first event approached. I spent most of January and February going through the chaotic process of assembling a semi-coherent presentation out of a katamari of vague thoughts.

I was making good progress. Then The Situation happened. One by one, the in-person editions of An Event Apart were cancelled (quite rightly). But my talk preparation hasn’t been in vain. I’ll be presenting my talk at an online edition of An Event Apart on Monday, August 17th.

You should attend. Not for my talk, but for Ire’s talk on Future-Proof CSS which sounds like it was made for me:

In this talk, we’ll cover how to write CSS that stands the test of time. From progressive enhancement techniques to accessibility considerations, we’ll learn how to write CSS for 100 years in the future (and, of course, today).

My talk will be about design principles …kinda. As usual, it will be quite a rambling affair. At this point I almost take pride in evoking a reaction of “where’s he going with this?” during the first ten minutes of a talk.

When I do actually get around to the point of the talk—design principles—I ask whether it’s possible to have such a thing as universal principles. After all, the whole point of design principles is that they’re specific to an endeavour, whether that’s a company, an organisation, or a product.

I think that some principles are, if not universal, then at least very widely applicable. I’ve written before about two of my favourites: the robustness principle and the principle of least power:

There’s no shortage of principles, laws, and rules out there, and I find many of them very useful, but if I had to pick just two that are particularly applicable to my work, they would be the robustness principle and the rule of least of power.

What’s interesting about both of those principles is that they are imperative. They tell you how to act:

Be conservative in what you send, be liberal in what you accept.

Choose the least powerful language suitable for a given purpose.

Other princples are imperative, but they tell you what not to do. Take the razors of Occam and Hanlon, for example:

Entities are not to be multiplied without necessity.

Never attribute to malice that which is adequately explained by stupidity.

But these imperative principles are exceptions. The vast majority of “universal” principles take the form of laws that are observations. They describe the state of the world without providing any actions to take.

There’s Hofstadter’s Law, for example:

It always takes longer than you expect, even when you take into account Hofstadter’s Law.

Or Clarke’s third law:

Any sufficiently advanced technology is indistinguishable from magic.

By themselves, these observational laws are interesting but they leave it up to you to decide on a course of action. On the other hand, imperative principles tell you what to do but don’t tell you why.

It strikes me that it could be fun (and useful) to pair up observational and imperative principles:

Because of observation A, apply action B.

For example:

Because of Murphy’s Law, apply the principle of least power.

Or in its full form:

Because anything that can go wrong will go wrong, choose the least powerful language suitable for a given purpose.

I feel like the Jevons paradox is another observational principle that should inform our work on the web:

The Jevons paradox occurs when technological progress increases the efficiency with which a resource is used, but the rate of consumption of that resource rises because of increasing demand.

For example, even though devices, browsers, and networks are much, much better now than they were, say, ten years ago, that doesn’t mean that websites have become better or faster. Instead, it’s precisely because there’s more power available that people think nothing of throwing megabytes of JavaScript at users. See Scott’s theory that 5G Will Definitely Make the Web Slower, Maybe:

JavaScript size has ballooned as networks have improved.

This problem would be addressed if web developers were more conservative in what they sent. The robustness principle in action.

Because of the Jevons paradox, apply the robustness principle.

Admittedly, the expanded version of that is far too verbose:

Because technological progress increases the efficiency with which a resource is used, but the rate of consumption of that resource rises because of increasing demand, be conservative in what you send, be liberal in what you accept.

I’m sure there are more and better pairings to be made: an observational principle to tell you why you should take action, and an imperative principle to tell you what action you should take.

Implementors

The latest newsletter from The History Of The Web is a good one: The Browser Engine That Could. It’s all about the history of browsers and more specifically, rendering engines.

Jay quotes from a 1992 email by Tim Berners-Lee when there was real concern about having too many different browsers. But as history played out, the concern shifted to having too few different browsers.

I wrote about this—back when Edge switched to using Chromium—in a post called Unity where I compared it to political parties:

If you have hundreds of different political parties, that’s not ideal. But if you only have one political party, that’s very bad indeed!

I talked about this some more with Brian and Stuart on the Igalia Chats podcast: Web Ecosystem Health (here’s the mp3 file).

In the discussion we dive deeper into the naunces of browser engine diversity; how it’s not the numbers that matter, but representation. The danger with one dominant rendering engine is that it would reflect one dominant set of priorities.

I think we’re starting to see this kind of battle between different sets of priorities playing out in the browser rendering engine landscape.

Webkit published a list of APIs they won’t be implementing in their current form because of security concerns around fingerprinting. Mozilla is taking the same stand. Google is much more gung-ho about implementing those APIs.

I think it’s safe to say that every implementor wants to ship powerful APIs and ensure security and privacy. The issue is with which gets priority. Using the language of principles and priorities, you could crudely encapsulate Apple and Mozilla’s position as:

Privacy, even over capability.

That design principle would pass the reversibility test. In fact, Google’s position might be represented as:

Capability, even over privacy.

I’m not saying Apple and Mozilla don’t value powerful APIs. I’m not saying Google doesn’t value privacy. I’m saying that Google’s priorities are different to Apple’s and Mozilla’s.

Alas, Alex is saying that Apple and Mozilla don’t value capability:

There is a contingent of browser vendors today who do not wish to expand the web platform to cover adjacent use-cases or meaningfully close the relevance gap that the shift to mobile has opened.

That’s very disappointing. It’s a cheap shot. As cheap as saying that, given Google’s business model, Chrome wouldn’t want to expand the web platform to provide better privacy and security.

Design systems on the Clearleft podcast

If you’ve already subscribed to the Clearleft podcast, thank you! The first episode is sliding into your podcast player of choice.

This episode is all about …design systems!

I’m pretty happy with how this one turned out, although as it’s the first one, I’m sure I’ll learn how to do this better. I may end up looking back at this first foray with embarrassment. Still, it’s fairly representative of what you can expect from the rest of the season.

This episode is fairly short. Just under eighteen minutes. That doesn’t mean that other episodes will be the same length. Each episode will be as long (or as short) as it needs to be. Form follows function, or in this case, episode length follows content. Other episodes will be longer. Some might be shorter. It all depends on the narrative.

This flies in the face of accepted wisdom when it comes to podcasting. The watchword that’s repeated again and again for aspiring podcasters is consistency. Release on a consistent schedule and have a consistent length for episodes. I kind of want to go against that advice just out of sheer obstinancy. If I end up releasing episodes on a regular schedule, treat it as coincidence rather than consistency.

There’s not much of me in this episode. And there won’t be much of me in most episodes. I’m just there to thread together the smart soundbites coming from other people. In this episode, the talking heads are my colleagues Jon and James, along with my friends and peers Charlotte, Paul, and Amy (although there’s a Clearleft connection with all of them: Charlotte and Paul used to be Clearlefties, and Amy spoke at Patterns Day and Sofa Conf).

I spoke to each of them for about an hour, but like I said, the entire episode is less than eighteen minutes long. The majority of our conversations ended up on the cutting room floor (possibly to be used in future episodes).

Most of my time was spent on editing. It was painstaking, but rewarding. There’s a real pleasure to be had in juxtaposing two snippets of audio, either because they echo one another or because they completely contradict one another. This episode has a few examples of contradictions, and I think those are my favourite moments.

Needless to say, eighteen minutes was not enough time to cover everything about design systems. Quite the opposite. It’s barely an introduction. This is definitely a topic that I’ll be returning to. Maybe there could even be a whole season on design systems. Let me know what you think.

Oh, and you’ll notice that there’s a transcript for the episode. That’s a no-brainer. I’m a big fan of the spoken word, but it really comes alive when it’s combined with searchable, linkable, accessible text.

Anyway, have a listen and if you’re not already subscribed, pop the RSS feed into your podcast player.

Custom properties

I made the website for the Clearleft podcast last week. The design is mostly lifted straight from the rest of the Clearleft website. The main difference is the masthead. If the browser window is wide enough, there’s a background image on the right hand side.

I mostly added that because I felt like the design was a bit imbalanced without something there. On the home page, it’s a picture of me. Kind of cheesy. But the image can be swapped out. On other pages, there are different photos. All it takes is a different class name on that masthead.

I thought about having the image be completely random (and I still might end up doing this). I’d need to use a bit of JavaScript to choose a class name at random from a list of possible values. Something like this:

var names = ['jeremy','katie','rich','helen','trys','chris'];
var name = names[Math.floor(Math.random() * names.length)];
document.querySelector('.masthead').classList.add(name);

(You could paste that into the dev tools console to see it in action on the podcast site.)

Then I read something completely unrelated. Cassie wrote a fantastic article on her site called Making lil’ me - part 1. In it, she describes how she made the mouse-triggered animation of her avatar in the footer of her home page.

It’s such a well-written technical article. She explains the logic of what she’s doing, and translates that logic into code. Then, after walking you through the native code, she shows how you could use the Greeksock library to achieve the same effect. That’s the way to do it! Instead of saying, “Here’s a library that will save you time—don’t worry about how it works!”, she’s saying “Here’s it works without a library; here’s how it works with a library; now you can make an informed choice about what to use.” It’s a very empowering approach.

Anyway, in the article, Cassie demonstrates how you can use custom properties as a bridge between JavaScript and CSS. JavaScript reads the mouse position and updates some custom properties accordingly. Those same custom properties are used in CSS for positioning. Voila! Now you’ve got the position of an element responding to mouse movements.

That’s what made me think of the code snippet I wrote above to update a class name from JavaScript. I automatically thought of updating a class name because, frankly, that’s how I’ve always done it. I’d say about 90% of the DOM scripting I’ve ever done involves toggling the presence of class values: accordions, fly-out menus, tool-tips, and other progressive disclosure patterns.

That’s fine. But really, I should try to avoid touching the DOM at all. It can have performance implications, possibly triggering unnecessary repaints and reflows.

Now with custom properties, there’s a direct line of communication between JavaScript and CSS. No need to use the HTML as a courier.

This made me realise that I need to be aware of automatically reaching for a solution just because that’s the way I’ve done something in the past. I should step back and think about the more efficient solutions that are possible now.

It also made me realise that “CSS variables” is a very limiting way of thinking about custom properties. The fact that they can be updated in real time—in CSS or JavaScript—makes them much more powerful than, say, Sass variables (which are more like constants).

But I too have been guilty of underselling them. I almost always refer to them as “CSS custom properties” …but a lot of their potential comes from the fact that they’re not confined to CSS. From now on, I’m going to try calling them custom properties, without any qualification.

Announcing the Clearleft podcast

I’ve been working on something new for the past few months and now I’d like to share it with you…

The Clearleft Podcast.

Now I know what you’re thinking: aren’t there enough podcasts in the world already? Well, frankly, no. Unless you also concede that there are enough books and records and films in the world already too (to be fair, this is a reasonable thought to have when you’re navigating Amazon, Spotify, and Netflix).

In any case, this podcast is going to be a bit different.

In our field, the usual podcast format is in the form of a conversation: a host or hosts interviewing a guest or guests. Those are great. I’ve certainly enjoyed being the guest on many a great podcast. But I wanted to do something a bit more like an audio documentary.

If you’ve seen a lot of documentaries you’ll know that there are two key factors to getting a great story:

  1. the source material and
  2. the editing.

That’s what makes the Clearleft podcast different.

For the source material, I’ve interviewed my colleagues at Clearleft as well as our peers in other companies. I’ve also gathered great material from conference talks—we’ve got a wealth of wonderful insights from multiple editions of events like UX London, Leading Design, Ampersand, Responsive Day Out, Patterns Day, and dConstruct.

A lot of work has gone into the editing. It probably works out at about an hour of work per minute of podcast. I know that seems excessive, but I really wanted to get a snappy feel for each episode, juxtaposing multiple viewpoints.

The focus of the episode will be around a particular topic rather than a person and will feature lots of different voices woven together. The really challenging part is threading a good narrative. It’s kind of like preparing a conference talk in that respect—I’ve always found the narrative thread to be the hardest but most rewarding part of putting a talk together.

It’s simultaneously exciting and nerve-wracking to put this out into the world. But I think you’re going to enjoy it.

Visit the website for the podcast and choose your preferred method of subscribing. There’s the RSS feed, but the Clearleft podcast is also available on Apple Podcasts, Google Podcasts, Spotify, Stitcher, Deezer, TuneIn, Castro, and Overcast.

The first episode will go live later this week. In the meantime, there’s a short trailer to give you a taste of what’s to come.

The episodes will be grouped together into seasons. I reckon a season will around six episodes long. So you can expect the first season to be released over the next six weeks.

Hope you like it!

podcast.clearleft.com

The Machines Stop

The Situation feels like it’s changing. It’s not over, not by a long shot. But it feels like it’s entering a different, looser phase.

Throughout the lockdown, there’s been a strange symmetry between the outside world and the inside of our home. As the outside world slowed to a halt, so too did half the machinery in our flat. Our dishwasher broke shortly before the official lockdown began. So did our washing machine.

We had made plans for repairs and replacements, but as events in the world outside escalated, those plans had to be put on hold. Plumbers and engineers weren’t making any house calls, and rightly so.

We even had the gas to our stovetop cut off for a while—you can read Jessica’s account of that whole affair. All the breakdowns just added to the entropic Ballardian mood.

But the gas stovetop was fixed. And so too was the dishwasher, eventually. Just last week, we got our new washing machine installed. Piece by piece, the machinery of our interier world revived in lockstep with the resucitation of the world outside.

As of today, pubs will be open. I won’t be crossing their thresholds just yet. We know so much more about the spread of the virus now, and gatherings of people in indoor spaces are pretty much the worst environments for transmission.

I’m feeling more sanguine about outdoor spaces. Yesterday, Jessica and I went into town for Street Diner. It was the first time since March that we walked in that direction—our other excursions have been in the direction of the countryside.

It was perfectly fine. We wore masks, and while we were certainly in the minority, we were not alone. People were generally behaving responsibly.

Brighton hasn’t done too badly throughout The Situation. But still, like I said, I have no plans to head to the pub on a Saturday night. The British drinking culture is very much concentrated on weekends. Stay in all week and then on the weekend, lassen die Sau raus!, as the Germans would say.

After months of lockdown, reopening pubs on a Saturday seems like a terrible idea. Over in Ireland, pubs have been open since Monday—a sensible day to soft-launch. With plenty of precautions in place, things are going well there.

I’ve been watching The Situation in Ireland throughout. It’s where my mother lives, so I was understandably concerned. But they’ve handled everything really well. It’s not New Zealand, but it’s also not the disaster that is the UK.

It really has been like watching an A/B test run at the country level. Two very similar populations confronted with exactly the same crisis. Ireland took action early, cancelling the St. Patrick’s Day parade(!) while the UK was still merrily letting Cheltenham go ahead. Ireland had clear guidance. The UK had dilly-dallying and waffling. And when the shit really hit the fan, the Irish taoiseach rolled up his sleeves and returned to medical work. Meanwhile the UK had Dominic Cummings making a complete mockery of the sacrifices that everyone was told to endure.

What’s strange is that people here in the UK don’t seem to realise how the rest of the world, especially other European countries, have watched the response here with shock and horror. The narrative here seems to be that we all faced this thing together, and with our collective effort, we averted the worst. But the numbers tell a very different story. Comparing the numbers here with the numbers in Ireland—or pretty much any other country in Europe—is sobering.

So even though the timelines for reopenings here converge with Ireland’s, The Situation is far from over.

Even without any trips to pubs, restaurants, or other indoor spaces, I’m looking forward to making some more excursions into town. Not that it’s been bad staying at home. I’ve really quite enjoyed staying put, playing music, reading books, and watching television.

I was furloughed from work for a while in June. Normally, my work at this time of year would involve plenty of speaking at conferences. Seeing as that wasn’t happening, it made sense to take advantage of the government scheme to go into work hibernation for a bit.

I was worried I might feel at a bit of a loose end, but I actually really enjoyed it. The weather was good so I spent quite a bit of time just sitting in the back garden, reading (I am very, very grateful to have even a small garden). I listened to music. I watched movies. I surfed the web. Yes, properly surfed the web, going from link to link, get lost down rabbit holes. I tell you, this World Wide Web thing is pretty remarkable. Some days I used it to read up on science or philosophy. I spent a week immersed in Napoleonic history. I have no idea how or why. But it was great.

I’m back at work now, and have been for a couple of weeks. But I wouldn’t mind getting furloughed again. It felt kind of like being retired. I’m quite okay with the propsect of retirement now, as long as we have music and sunshine and the World Wide Web.

That’s the future. For now, The Situation continues, albeit in looser form.

I’ve really enjoyed reading other people’s accounts throughout. My RSS reader is getting a good workout. I always look forward to weeknotes from Alice, Nat, and Phil (this piece from Phil has really stuck with me). Jessica has written fifteen installments—and counting—of A Journal of the Plague Week. I know I’m biased, but I think it’s some mighty fine writing. Start here.

Dark mode revisited

I added a dark mode to my website a while back. It was a fun thing to do during Indie Web Camp Amsterdam last year.

I tied the colour scheme to the operating system level. If you choose a dark mode in your OS, my website will adjust automatically thanks to the prefers-color-scheme: dark media query.

But I’ve seen notes from a few friends, not about my site specifically, but about how they like having an explicit toggle for dark mode (as well as the media query). Whenever I read those remarks, I’d think “I’m really not sure I’ve got time to deal with adding that kind of toggle to my site.”

But then I realised, “Jeremy, you absolute muffin! You’ve had a theme switcher on your website for almost two decades now!”

Doh! I had forgotten about that theme switcher. It dates back to the early days of CSS. I wanted my site to be a demonstration of how you could apply different styles to the same underlying markup (this was before the CSS Zen Garden came along). Those themes are very dated now, but if you like you can view my site with a Zeldman theme or a sci-fi theme.

To offer a dark-mode theme for my site, all I had to do was take the default stylesheet, pull out the custom properties from the prefers-color-scheme: dark media query, and done. It took less than five minutes.

So if you want to view my site in dark mode, it’s one of the options in the “Customise” dropdown on every page of the website.

Hemimastigophora

Probably fewer than a hundred people in the world have seen what you’re looking at right now.

Jessica and I were taking turns at the microscope when we were told that.

Let me back up a bit and explain how we found ourselves in this this situation…

It all started with The Session, the traditional Irish music community site that I run. There’s a big focus on getting together and playing music—something that’s taken a big hit during this global pandemic. Three sections of the website are devoted to face-to-face gatherings: events (like concerts and festivals), sessions, and the most recent addition, trips.

The idea with trips is that you input somewhere you’re going to be travelling to, along with the dates you’ll be there. It’s like a hyper-focused version of Dopplr. The site then shows you if any events are happening, if there are any sessions on, and also if there are any members of the site in that locality (if those members have added their location to their profiles).

Last August, I added the trips I would be taking in the States. There’s be a trip to Saint Augustine to hang out with Jessica’s family, a trip to Chicago to speak at An Event Apart, and a trip to New York for a couple of days because that’s where the ocean liner was going to deposit us after our transatlantic crossing.

A fellow member of The Session named Aaron who is based in New York saw my trip and contacted me to let me know about the session he goes to (he plays tin whistle). Alas, that session didn’t coincide with our short trip. But he also added:

I work at the American Museum of Natural History, and if you have time and interest, I can provide you with vouchers for tickets to as many special exhibits and such as you’d like!

Ooh, that sounded like fun! He also said:

In fact I could give you a quick behind-the-scenes tour if you’re interested.

Jessica and I didn’t have any set plans for our time in New York, so we said why not?

That’s how we ended spending a lovely afternoon being shown around the parts of the museum that the public don’t usually get to see. It’s quite the collection of curiosities back there!

There’s also plenty of research. Aaron’s particular area was looking into an entirely different kingdom of life—neither animal, nor plant, nor fungus. Remarkably, these microscopic creatures were first identified—by a classmate of Aaron’s—by happenstance in 2016:

The hemimastigotes analyzed by the Dalhousie team were found by Eglit during a spring hike with some other students along the Bluff Wilderness Trail outside Halifax a couple of years ago. She often has empty sample vials in her pockets or bags, and scooped a few tablespoons of dirt into one of them from the side of the trail.

That’s like a doctor announcing that they’d come across a hitherto-unknown limb on the human body. The findings were published in the paper, Hemimastigophora is a novel supra-kingdom-level lineage of eukaryotes in 2018.

In the “backstage” area of the American Museum of Natural History, Aaron had samples of them. He put them under the microscope for us. As we took turns looking at them wriggling their flagella, Aaron said:

Probably fewer than a hundred people in the world have seen what you’re looking at right now.

100 tunes

We got a headstart on the lockdown. A week before the UK government finally stopped dilly-dallying (at the expense of tens of thousands of lives), Clearleft became a remote-only company. At the beginning of this stay-at-home time, I started recording a tune a day. I wasn’t sure how long I’d keep it up, but I’ve managed to keep it going the whole time.

Yesterday I recorded my 100th tune.

It’s funny how small efforts can build up into a satisfying corpus. It’s not like I’m attempting anything ambitious, like Matthias, who is doing 100 days of writing. Recording one tune isn’t too much hassle. There are days when it’s frustrating and I have to do multiple takes, but overall it’s not too taxing. But now, when I look at the cumulative result, I’m very happy that I didn’t skip any days.

One hundred is a nice round number, so this could be a good time to stop. I could quit while I’m ahead. But I think I’ll keep going. Again, despite what the official line might be from the UK government (who have lost all trust), I reckon I’ll be staying at home for a while yet. As long as I’m here, I may as well keep playing. I have plenty more tunes to play.

At some point, the daily streak will end. But even then, I think I’ll continue to record tunes like this, even if it becomes more sporadic.

If you like these tunes, as well as being here on my own site, they’re all in a YouTube set. So …like’n’subscribe, or something?

Gormless

I sometimes watch programmes on TG4, the Irish language broadcaster that posts most shows online. Even though I’m watching with subtitles on, I figure it can’t be bad for keeping my very rudimentary Irish from atrophying completely.

I’m usually watching music programmes but occassionally I’ll catch a bit of the news (or “nuacht”). Their coverage of the protests in America reminded me of a peculiar quirk of the Irish language. The Black community would be described as “daoine gorm” (pronunced “deenee gurum”), which literally translated would mean “blue people”. In Irish, the skin colour is referred to as “gorm”—blue.

This isn’t one of those linguistic colour differences like the way the Japanese word ao means blue and green. Irish has a perfectly serviceable word for the colour black, “dubh” (pronounced “duv”). But the term “fear dubh” (“far duv”) which literally means “black man” was already taken. It’s used to describe the devil. Not ideal.

In any case, this blue/black confusion in Irish reminded me of a delicious tale of schadenfreude. When I was writing about the difference between intentions and actions, I said:

Sometimes bad outcomes are the result of good intentions. Less often, good outcomes can be the result of bad intentions.

Back in 2017, the Geeky Gaeilgeoir wrote a post called Even Racists Got the Blues. In it, she disects the terrible translation job done by an Irish-American racist sporting a T-shirt that reads:

Gorm Chónaí Ábhar.

That’s completely nonsensical in Irish, but the intent behind the words was to say “Blue Lives Matter.” Except… even if it made grammatical sense, what this idiot actually wrote would translate as:

Black Lives Matter.

What a wonderful chef’s kiss of an own goal!

If only it were a tattoo.

CSS custom properties and the cascade

When I wrote about programming CSS to perform Sass colour functions I said this about the brilliant Lea Verou:

As so often happens when I’m reading something written by Lea—or seeing her give a talk—light bulbs started popping over my head (my usual response to Lea’s knowledge bombs is either “I didn’t know you could do that!” or “I never thought of doing that!”).

Well, it happened again. This time I was reading her post about hybrid positioning with CSS variables and max() . But the main topic of the post wasn’t the part that made go “Huh! I never knew that!”. Towards the end of her article she explained something about the way that browsers evaluate CSS custom properties:

The browser doesn’t know if your property value is valid until the variable is resolved, and by then it has already processed the cascade and has thrown away any potential fallbacks.

I’m used to being able to rely on the cascade. Let’s say I’m going to set a background colour on paragraphs:

p {
  background-color: red;
  background-color: color(display-p3 1 0 0);
}

First I’ve set a background colour using a good ol’ fashioned keyword, supported in browsers since day one. Then I declare the background colour using the new-fangled color() function which is supported in very few browsers. That’s okay though. I can confidently rely on the cascade to fall back to the earlier declaration. Paragraphs will still have a red background colour.

But if I store the background colour in a custom property, I can no longer rely on the cascade.

:root {
  --myvariable: color(display-p3 1 0 0);
}
p {
  background-color: red;
  background-color: var(--myvariable);
}

All I’ve done is swapped out the hard-coded color() value for a custom property but now the browser behaves differently. Instead of getting a red background colour, I get the browser default value. As Lea explains:

…it will make the property invalid at computed value time.

The spec says:

When this happens, the computed value of the property is either the property’s inherited value or its initial value depending on whether the property is inherited or not, respectively, as if the property’s value had been specified as the unset keyword.

So if a browser doesn’t understand the color() function, it’s as if I’ve said:

background-color: unset;

This took me by surprise. I’m so used to being able to rely on the cascade in CSS—it’s one of the most powerful and most useful features in this programming language. Could it be, I wondered, that the powers-that-be have violated the principle of least surprise in specifying this behaviour?

But a note in the spec explains further:

Note: The invalid at computed-value time concept exists because variables can’t “fail early” like other syntax errors can, so by the time the user agent realizes a property value is invalid, it’s already thrown away the other cascaded values.

Ah, right! So first of all browsers figure out the cascade and then they evaluate custom properties. If a custom property evaluates to gobbledygook, it’s too late to figure out what the cascade would’ve fallen back to.

Thinking about it, this makes total sense. Remember that CSS custom properties aren’t like Sass variables. They aren’t evaluated once and then set in stone. They’re more like let than const. They can be updated in real time. You can update them from JavaScript too. It’s entirely possible to update CSS custom properties rapidly in response to events like, say, the user scrolling or moving their mouse. If the browser had to recalculate the cascade every time a custom property didn’t evaluate correctly, I imagine it would be an enormous performance bottleneck.

So even though this behaviour surprised me at first, it makes sense on reflection.

I’ve probably done a terrible job explaining the behaviour here, so I’ve made a Codepen. Although that may also do an equally terrible job.

(Thanks to Amber for talking through this with me and encouraging me to blog about it. And thanks to Lea for expanding my mind. Again.)

Intent

There are intentions and there are outcomes. Sometimes bad outcomes are the result of good intentions. Less often, good outcomes can be the result of bad intentions. But generally we associate the two: we expect good outcomes to come from good intentions and we expect bad outcomes to come from bad intentions.

Perhaps it’s because of this conflation that we place too much emphasis on intentions. If, for example, someone is called out for causing a bad outcome, their first response is often to defend their intentions. That’s understandable. When someone says “you have created a bad outcome”, I understand why the person on the receiving end would receive that feedback as “you intended to create this bad outcome.” Cue a non-apology that clarifies the (good) intention without acknowledging the reality of the outcome (“It was never my intention to…”).

I get it. Intentions do matter …just not as much as we give them credit for. I mean, in general, I’d prefer bad outcomes to be the inadvertent result of good intentions. But in some ways, it really doesn’t matter: a bad outcome is a bad outcome.

Anyway, all of this is just to preface something I’m going to say about myself:

I am almost certainly racist.

I don’t intend to be racist, but like I said, intentions aren’t really what matter. Outcomes are.

Note, for example, the cliché of the gormless close-minded goon who begins a sentence with “I’m not racist, but…” before going on to say something clearly racist. It’s as though the racism could be defanged by disavowing bad intent.

The same defence mechanism is used to defend racist traditions. “Oh, it’s not racist—that’s just something we’ve always done.” Again, the defence is for the intention, not the outcome. And again, outcomes matter far, far more than intentions.

I really don’t intend to be racist. But how could I not be? I grew up in a small town in Ireland where literally everyone else looked like me. By the same token, I’m also almost certainly sexist. Growing up as a cisgender male in a patriarchal society guarantees that my mind has been shaped in ways I now wish it weren’t.

Acknowledging my racism—and sexism—doesn’t mean I’m okay with it. On the contrary. It’s a source of shame. But acknowledging my racism is a necessary step to changing it.

In any case, it doesn’t really matter how I feel about any of this. This isn’t meant to be a confessional. What matters are outcomes. Outcomes aren’t really the direct result of intentions—outcomes are the direct result of actions.

Most of my actions lately have been very passive. Listening. Watching. Because my actions are passive, they are indistinguishable from silence. That’s not good. Silence can be interpreted as acquiescence, acceptance. That’s not what I intend …but my intentions don’t matter.

So, even though this isn’t about me or my voice or my intentions, and even though this is something that is so self-evident that it shouldn’t need to be said, I want to say:

Black lives matter.

Programming CSS to perform Sass colour functions

I wrote recently about moving away from Sass to using native CSS features. I had this to say on the topic of mixins in Sass:

These can be very useful, but now there’s a lot that you can do just in CSS with calc(). The built-in darken() and lighten() mixins are handy though when it comes to colours.

I know we will be getting these in the future but we’re not there yet with CSS.

Anyway, I had all this in the back of my mind when I was reading Lea’s excellent feature in this month’s Increment: A user’s guide to CSS variables. She’s written about a really clever technique of combining custom properites with hsl() colour values for creating colour palettes. (See also: Una’s post on dynamic colour theming with pure CSS.)

As so often happens when I’m reading something written by Lea—or seeing her give a talk—light bulbs started popping over my head (my usual response to Lea’s knowledge bombs is either “I didn’t know you could do that!” or “I never thought of doing that!”).

I immediately set about implementing this technique over on The Session. The trick here is to use separate custom properties for the hue, saturation, and lightness parts of hsl() colour values. Then, when you want to lighten or darken the colour—say, on hover—you can update the lightness part.

I’ve made a Codepen to show what I’m doing.

Let’s say I’m styling a button element. I make custom propertes for hsl() values:

button {
  --button-colour-hue: 19;
  --button-colour-saturation: 82%;
  --button-colour-lightness: 38%;
  background-color: hsl(
    var(--button-colour-hue),
    var(--button-colour-saturation),
    var(--button-colour-lightness)
  );
}

For my buttons, I want the borders to be slightly darker than the background colour. When I was using Sass, I used the darken() function to this. Now I use calc(). Here’s how I make the borders 10% darker:

border-color: hsl(
  var(--button-colour-hue),
  var(--button-colour-saturation),
  calc(var(--button-colour-lightness) - 10%)
);

That calc() function is substracting a percentage from a percentage: 38% minus 10% in this case. The borders will have a lightness of 28%.

I make the bottom border even darker and the top border lighter to give a feeling of depth.

On The Session there’s a “cancel” button style that’s deep red.

Here’s how I set its colour:

.cancel {
  --button-colour-hue: 0;
  --button-colour-saturation: 100%;
  --button-colour-lightness: 40%;
}

That’s it. The existing button declarations take care of assigning the right shades for the border colours.

Here’s another example. Site admins see buttons for some actions only available to them. I want those buttons to have their own colour:

.admin {
  --button-colour-hue: 45;
  --button-colour-saturation: 100%;
  --button-colour-lightness: 40%;
}

You get the idea. It doesn’t matter how many differently-coloured buttons I create, the effect of darkening or lightening their borders is all taken care of.

So it turns out that the lighten() and darken() functions from Sass are available to us in CSS by using a combination of custom properties, hsl(), and calc().

I’m also using this combination to lighten or darken background and border colours on :hover. You can poke around the Codepen if you want to see that in action.

I love seeing the combinatorial power of these different bits of CSS coming together. It really is a remarkably powerful programming language.

Hard to break

I keep thinking about some feedback that Cassie received recently.

She had delivered the front-end code for a project at Clearleft, and—this being Cassie we’re talking about—the code was rock solid. The client’s Quality Assurance team came back with the verdict that it was “hard to break.”

Hard to break. I love that. That might be the best summation I’ve heard for describing resilience on the web.

If there’s a corollary to resilient web design, it would be brittle web design. In a piece completely unrelated to web development, Jamais Cascio describes brittle systems:

When something is brittle, it’s susceptible to sudden and catastrophic failure.

That sounds like an inarguably bad thing. So why would anyone end up building something in a brittle way? Jamais Cascio continues:

Things that are brittle look strong, may even be strong, until they hit a breaking point, then everything falls apart.

Ah, there’s the rub! It’s not that brittle sites don’t work. They work just fine …until they don’t.

Brittle systems are solid until they’re not. Brittleness is illusory strength. Things that are brittle are non-resilient, sometimes even anti-resilient — they can make resilience more difficult.

Kilian Valkhof makes the same point when it comes to front-end development. For many, accessibility is an unknown unknown:

When you start out it’s you, notepad and a browser against the world. You open up that notepad, and you type

<div onclick="alert('hello world');">Click me!</div>

You fire up your browser, you click your div and …it works! It just works! Awesome. You open up the devtools. No errors. Well done! Clearly you did a good job. On to the next thing.

At the surface level, there’s no discernable difference between a resilient solution and a brittle one:

For all sorts of reasons, both legitimate and, as always, weird browser legacy reasons, a clickable div will mostly work. Well enough to fool someone starting out anyway.

If everything works, how would they know it kinda doesn’t?

Killian goes on to suggest ways to try to make this kind of hidden brittleness more visible.

Furthermore we could envision a browser that is much stricter when developing.

This something I touched on when I was talking about web performance with Gerry on his podcast:

There’s a disconnect in the process we go through when we’re making something, and then how that thing is experienced when it’s actually on the web, which is dependent on network speeds and processing speeds and stuff.

I spend a lot of time wondering why so many websites are badly built. Sure, there’s a lot can be explained by misaligned priorities. And it could just be an expression of Sturgeon’s Law—90% of websites are crap because 90% of everything is crap. But I’ve also come to realise that even though resilience is the antithesis to brittleness, they both share something in common: they’re invisible.

We have a natural bias towards what’s visible. Being committed to making sure something is beautiful to behold is, in some ways, the easy path to travel. But being committed to making sure something is also hard to break? That takes real dedication.