The Blogroll

From: Zeldman

What a year that was.

Know your web design history.

The post What a year that was. appeared first on Jeffrey Zeldman Presents.

From: Adactio

Will There Ever Be Another You by Patricia Lockwood

Patricia Lockwood’s No One Is Talking About This knocked me for six when I read it back in 2022:

It’s like a slow-building sucker punch.

Like my other favourite book of that year—A Ghost In The Throat by Doireann Ní Ghríofa—it’s hard to classify. I think it’s autofiction. Not quite autobiography. Not quite fiction.

Will There Ever Be Another You is also autofiction. I think. It might also be poetry (which shouldn’t be surprising as Patricia Lockwood is a poet after all).

I can’t say that this one had the same emotional impact of No One Is Talking About This for me but then again, very little could.

The writing feels very impressionistic, with each chapter trying on a different mode. It’s kinda Joycean …if James Joyce was stuck indoors during a global pandemic.

The narrative—such as it is—revolves around The Situation from 2020 onwards. That was a surreal bizarre time so it makes sense that this is a surreal bizarre book.

I think I liked it. I can’t quite tell. I just let the language wash over me.

Buy this book

From: Chris Coyier

Me Trying To Take a Selfie in 2001

From: Chris Coyier

FOREVERGREEN

In the first few minutes, Ruby says to me, “This is like The Giving Tree“, and by the end, I was like, “OK, you’re right.”

From: Chris Coyier

I like how Nolan paints this two-sided picture of AI coding. The worst fact about these tools is that they work. They can write code better than you or I can, and if you don’t believe me, wait six months. You could abstain out of moral principle. And that’s fine, especially if you’re at the […]

March 2, 2026, 3:26 pm >>

From: Zeldman

Advice for job seekers

Pitching isn’t bragging.

The post Advice for job seekers appeared first on Jeffrey Zeldman Presents.

From: Adactio

The state of State Of The Browser

I went to State Of The Browser in London on the weekend. It was great!

I mean, it’s always great but this year the standard felt really high. All the talks were top quality. I’ve been at events with ticket prices a literal order of magnitude greater but with quality nowhere near this level.

Bramus got the ball rolling with an excellent presentation on CSS anchor positioning. Cassie closed the day with a great fun talk, making a game in the browser. In between we had accessibility, progressive enhancement, and other favourite topics of mine.

State Of The Browser isn’t just about the talks though. It’s very much a community event. For me, it’s like an annual get-together with some lovely people that I only get to see once a year.

But it’s not just a bunch of people who already know each other. Dave got a show of hands from people attending for the first time and it looked to me like around half the audience. That’s what you want at an event—a mix of the old and the new, the familiar and the exciting.

A personal highlight for me was spending lunchtime talking in Irish with my friend Paul from Ti.to. Bhain mé an-taitneamh as an deis Gaeilge a labhairt!

Dave handed over MC duties to Jake this year but he did do the opening and closing remarks. He’s always really, really supportive of other community events and encouraged everyone to go to Web Day Out.

He also pleads with people to buy their conference tickets early (it really does help us conference organisers sleep better) but if you’ve left it this late, you’re lucky that tickets are still available.

If you liked State Of The Browser, you’re going to like Web Day Out. And if you missed State Of The Browser and you wished you could’ve been there, you can make up for it by coming to Web Day Out.

The two events have a lot in common. Great talks, great people, and no mention of large language models.

I don’t know if it was a deliberate policy by Dave, but it felt so good to spend a day at a technology conference that wasn’t dominated by The Hype.

There were a few bits of slop in the slides of the first two talks (which always makes me cringe and wince—I crince) and Cassie threw some subtly hilarious shade during her presentation, but apart from that, the day was gloriously free of the A and the I.

No doubt some people will think that’s little more than sticking our collective head in the sand, but when the sand is this lovely, I’m okay with it.

Tickets for State Of The Browser 2027 are already on sale. Do what Uncle Dave says and get your ticket nice and early.

From: Chris Coyier

Cool little aside in Marcin Wichary’s How to shoot a screen using a board of keys: Acorn 8, a graphic app, has a delightful screenshotting feature parked under ⌘⇧7 that does something incredible: it takes a screenshot, but does so in a way where windows are separate layers, grouped by app. It’s amazing; you can […]

February 28, 2026, 4:24 pm >>

From: Boagworld

Is your website copy faceless?

Is your website copy invisible? Three quick tests to find out if your headlines are too generic to differentiate you, and how to fix them.

From: Chris Coyier

Tucci Pan Review

Stanley Tucci has a set of cookware named after him that GreenPan sells. I’ve got these two pans: I forget where they came from exactly, some silent auction or something, but I unboxed and started using them about 8 months ago. I was so hyped the first few months! It’s my daily-driver pan. I’d say […]

From: Adactio

A nice day

It’s the 25th of February and it’s a beautiful day here in Brighton. I had lunch sitting outside—that’s how unseasonably warm it is. Like a little whiff of Summer to remind us of what’s yet to come.

It’s also my birthday. The beautiful weather is an auspicious augery.

Mozilla also released a new version of Firefox. I was hoping for cross-document view transitions and scroll-driven animations for my birthday, but alas I may have to wait another year.

Later, Jessica is going to take me out for some excellent Japanese food before we head on to a session in a cosy pub. I can think of no better way to celebrate my birthday than playing a rake of jigs and reels.

I’m 55 now. It feels like a meaningful number. I think I’ve moved down an option in the select menus that ask for your age range.

I got letters in the post from my pension provider reminding me that 55 is the age when you can technically start taking money out of your pension. Something that retired people do.

I have to admit, this birthday has me entertaining retirement options. I’m already down to just three days a week. It wouldn’t take much to wind that down over the next few years. There’d be even more opportunities to savour the sunshine on a sunny day.

Anyway. Just pondering. You know, the kind of thoughts a 55-year old has.

From: Chris Coyier

You Get Good At What You Do (Or Do You?)

I used to feel really strongly about this. You get good at what you do. Like, if you build websites all the time, you get good at building websites. If you make burritos all the time, you get good at making burritos. It could extend to almost anything. Healthy places that fit into the logical […]

From: Dave Rupert

Smaller and dumber

If I can make it smaller, I should.

If I can make it dumber, I should.

Smaller, dumber things have more applications, go more places, and require less maintenance.

From: Dave Rupert

Priority of idle hands

I had a small, intrusive realization the other day that computers and the internet are probably bad for me. I mean that beyond the general advice to touch grass. From an ADHD and generalized anxiety perspective, computers and the internet have become an endless supply of poison pills for my brain; feeds full of constant dopamine hits with doom at every turn.

This is hard to accept because a lot of my work, hobbies, education, entertainment, news, communities, and curiosities are all on the internet. I love the internet, it’s a big part of who I am today, but I understand how its incentive structures harm me. I’m not planning to unplug and go off-grid yet, but it did inspire me to come up with a “priority of constituencies” for my idle hands and downtime:

Instruments over pads of paper over laptop over tablet over phone.

From: Chris Coyier

Miscalibrated

I’ve been gaining weight again. More than twenty pounds in the last ~4 months. I’ve been hitting the gym hard and getting measurably stronger, so: Food! See, your boy can eat. The amount I can eat before I feel full would astound most of you out there. Whatever you think of as a complete hearty […]

From: Zeldman

American healthcare

Cooling my heels at the drugstore.

The post American healthcare appeared first on Jeffrey Zeldman Presents.

From: Boagworld

It’s all interconnected

Why CRO, UX design, and design leadership aren't separate disciplines. They're three interconnected pieces that make each other more effective.

From: Adactio

Counting down to Web Day Out

Not long now ’till Web Day Out — just three weeks!

It’s also not that long until the start of a new financial year so if you’ve got training budget that needs to be used this year, send your team to Web Day Out. Not only is it excellent value for money, it’s also going to have an incredibly high density of knowledge bombs per talk.

CSS! Progressive web apps! Web typography! Browser support! And much more.

If you like the sound of Web Day Out, you’ll also like State Of The Browser, which is just ten days away. In-person tickets for that event are now sold out, but online streaming tickets are still available.

Better yet, if you buy a ticket to Web Day Out, you automatically get a free online streaming ticket for State Of The Browser!

So get your ticket in the next ten days, enjoy State Of The Browser from the comfort of your own home, and then enjoy a trip to Brighton for Web Day Out on Thursday, 12 March. See you there!

From: Rachel Andrew

Generative AI has broken the subject matter expert/editor relationship

Some thoughts about managing a publishing pipeline in a world of generative AI.

From: Adactio

Magic

I don’t like magic.

I’m not talking about acts of prestidigitation and illusion. I mean the kind of magic that’s used to market technologies. It’s magic. It just works. Don’t think about it.

I’ve written about seamless and seamful design before. Seamlessness is often touted as the ultimate goal of UX—“don’t make me think!”—but it comes with a price. That price is the reduction of agency.

When it comes to front-end development, my distrust of magic tips over into being a complete control freak.

I don’t like using code that I haven’t written and understood myself. Sometimes its unavoidable. I use two JavaScript libraries on The Session. One for displaying interactive maps and another for generating sheet music. As dependencies go, they’re very good but I still don’t like the feeling of being dependant on anything I don’t fully understand.

I can’t stomach the idea of using npm to install client-side JavaScript (which then installs more JavaScript, which in turn is dependant on even more JavaScript). It gives me the heebie-jeebies. I’m kind of astonished that most front-end developers have normalised doing daily trust falls with their codebases.

While I’m mistrustful of libraries, I’m completely allergic to frameworks.

Often I don’t distinguish between libraries and frameworks but the distinction matters here. Libraries are bits of other people’s code that I call from my code. Frameworks are other people’s code that call bits of my code.

Think of React. In order to use it, you basically have to adopt its idioms, its approach, its syntax. It’s a deeper level of dependency than just dropping in a regular piece of JavaScript.

I’ve always avoided client-side React because of its direct harm to end users (over-engineered bloated sites that take way longer to load than they need to). But the truth is that I also really dislike the extra layer of abstraction it puts between me and the browser.

Now, whenever there’s any talk about abstractions someone inevitably points out that, when it comes to computers, there’s always some layer of abstraction. If you’re not writing in binary, you don’t get to complain about an extra layer of abstraction making you uncomfortable.

I get that. But I still draw a line. When it comes to front-end development, that line is for me to stay as close as I can to raw HTML, CSS, and JavaScript. After all, that’s what users are going to get in their browsers.

My control freakery is not typical. It’s also not a very commercial or pragmatic attitude.

Over the years, I’ve stopped doing front-end development for client projects at work. Partly that’s because I’m pretty slow; it makes more sense to give the work to a better, faster developer. But it’s also because of my aversion to React. Projects came in where usage of React was a foregone conclusion. I wouldn’t work on those projects.

I mention this to point out that you probably shouldn’t adopt my inflexible mistrustful attitude if you want a career in front-end development.

Fortunately for me, front-end development still exists outside of client work. I get to have fun with my own website and with The Session. Heck, they even let me build the occasional hand-crafted website for a Clearleft event. I get to do all that the long, hard stupid way.

Meanwhile in the real world, the abstractions are piling up. Developers can now use large language models to generate code. Sometimes the code is good. Sometimes its not. You should probably check it before using it. But some developers just YOLO it straight to production.

That gives me the heebie-jeebies, but then again, so did npm. Is it really all that different? With npm you dialled up other people’s code directly. With large language models, they first slurp up everyone’s code (like, the whole World Wide Web), run a computationally expensive process of tokenisation, and then give you the bit you need when you need it. In a way, large language model coding tools are like a turbo-charged npm with even more layers of abstraction.

It’s not for me but I absolutely understand why it can work in a pragmatic commercial environment. Like Alice said:

Knitting is the future of coding. Nobody knits because they want a quick or cheap jumper, they knit because they love the craft. This is the future of writing code by hand. You will do it because you find it satisfying but it will be neither the cheapest or quickest way to write software.

But as Dave points out:

And so now we have these “magic words” in our codebases. Spells, essentially. Spells that work sometimes. Spells that we cast with no practical way to measure their effectiveness. They are prayers as much as they are instructions.

I shudder!

But again, this too is nothing new. We’ve all seen those codebases that contain mysterious arcane parts that nobody dares touch. coughWebpackcough. The issue isn’t with the code itself, but with the understanding of the code. If the understanding of the code was in one developer’s head, and that person has since left, the code is dangerous and best left untouched.

This, as you can imagine, is a maintenance nightmare. That’s where I’ve seen the real cost of abstractions. Abstractions often really do speed up production, but you pay the price in maintenance later on. If you want to understand the codebase, you must first understand the abstractions used in the codebase. That’s a lot to document, and let’s face it, documentation is the first casuality of almost every project.

So perhaps my aversion to abstraction in general—and large language models in particular—is because I tend to work on long-term projects. This website and The Session have lifespans measured in decades. For these kinds of projects, maintenance is a top priority.

Large language model coding tools truly are magic.

I don’t like magic.

From: Zeldman

The salad bar theory of UX professionalism

Less, but better? Not this week.

The post The salad bar theory of UX professionalism appeared first on Jeffrey Zeldman Presents.

From: Stuff & Nonsense

I made sho!io. Share what you’re working on without the social noise

I’ve been quietly working on a side project called sho!io, and I’m opening it up to a few people. It’s meant to be a quiet place where you can share one thing you’re making each day, without the usual social noise. It’s early and very much still in progress, but I’d really value your honest feedback if you’re up for trying it.

sho!io timeline in grid view

Many design platforms started out as places to share work with friends. Then they became feeds. Then they became popularity contests. Then they became businesses built on attention. Along the way, the joy went missing. I want to bring it back.

Post one piece of work every 24 hours

I wanted somewhere where I could share what I’m working on every day, not a pseudo-portfolio, or a place to attract work. So, on sho!io, you post one thing a day. It can be an illustration, a layout, a sketch, or an unfinished work in progress. It doesn’t have to be perfect. It just has to be yours.

sho!io timeline in list view

You can follow people, and they can follow you back, but no one else can see who you follow or who follows you. Likewise, you can like someone’s post, and they can like yours, but no one else can see how many likes a post received.

sho!io post detail

There are no public follower counts, visible popularity contests, and no pressure to perform. You can keep your profile private and share only with people you trust. Or it can be public. It’s your work, so your decision.

Building an app from scratch isn’t something I’ve done before, so building sho!io was a real journey into unexplored territory, as I had to create a Postgres database in Supabase and set it up using SQL queries. But, with a little help here and there, I managed it, and the scripts which enable membership, following, liking, and posting.

sho!io account settings

I know it can be improved massively, so if more people want to use it, I plan to find a developer who can help it scale.

Right now, I’m ready to open up sho!io to a few people. It’s early and very much still in progress, but I’d really value your feedback if you’re up for trying sho!io. Add your name to the wait list, and I’ll send 25 invites a week for the next few weeks.

sho!io wait list

Join the wait list

From: Chris Coyier

The Good & Not Good

I’ve spent more time with religious people in the last year than perhaps I have in my whole life. It’s got me thinking about religion with more curiosity than I ever have. So I’m having what are probably middle-school level thoughts. I’ve forever identified as agnostic, likely because that’s how most of my family rolled […]

From: Adactio

The Morrigan by Kim Curran

Every culture has its myths and legends. Greece has its gods and warriors. England has its stories of Arthur. Ireland has the Tuatha Dé Danann, The Ulster Cycle, and more.

But while the Arthurian legends and the Greek myths have been retold many times, the stories of ancient Ireland have remained largely untouched.

Kim Curran’s book The Morrigan takes on this challenge.

The blurb for the book compares it Madeline Miller’s Circe, which is a bold comparison. The writing in The Morrigan isn’t in the same league as Circe, but then again, very little is.

Structurally, the comparison makes complete sense.

Circe starts with the titular nymph in the world of the gods of Olympus before moving on to more mortal affairs, coming to a head with the events of The Odyssey, when Odysseus’s story dominates.

The Morrigan starts with the titular goddess in the world of the gods of the Túatha Dé before moving on to more mortal affairs, coming to a head with the events of The Táin, when Cú Chulainn’s story dominates.

I took me a little while to adjust to the tone, but once I did, I thoroughly enjoyed this retelling. It manages to simultaneously capture the bloody, over-the-top feeling of The Táin while also having a distinctly modern twist. By the last third, I was completely engrossed.

After finishing Circe I went on a spree of reading many, many modern retellings of Greek myths. Now that I’ve finished The Morrigan I want to do the same for the Irish legends.

But I can’t. Apart from re-reading a translation of The Táin, there’s not much else out there for me.

Kim Curran does have another book that’s just been released; Brigid (the goddess? the saint? both?). If it’s anything like The Morrigan, it’s going to be a must-read.

I hope these books are the first of many.

Buy this book

From: Boagworld

Why I’m Not Worried About My AI Dependency

Should we worry about over-relying on AI? After becoming completely dependent on it, I think we're asking the wrong question.

From: Stuff & Nonsense

Unfinished Business #139: I like red and I like hats

This week on Unfinished Business, Rich and I are joined by developer and organizer of London Web Standards and State of the Browser, Dave Letorey.


Sponsored by Contract Killer

Most web design contract templates are stuffed with boilerplate content your clients will never read. Contract Killer covers everything—payments, revisions, scope, and timelines—in plain, human language. Trusted by designers for over a decade. Peer-reviewed, fully customisable, and built to keep projects on track, and your invoices paid.

Buy Contract Killer


Also available on YouTube

For anyone who can’t get enough Unfinished Business, we publish the show in video format on YouTube.

Watch “Unfinished Business” on YouTube

Sponsor Unfinished Business

The best way to promote your product or service to the Unfinished Business audience of creative professionals, designers, and developers. Sponsors get one exclusive two-minute ad per episode, live read by me or Rich, which feels personal and relatable. We can use your script or ad-lib, and you’ll also receive a link on each episode’s post, as well as a thank-you on our Bluesky and Mastodon accounts. Interested? We’d love to hear from you.

Support Unfinished Business on Patreon

We also have three monthly membership plans so you can support Unfinished Business on Patreon. $5, $10, and $20 if you’re feeling especially generous. All money goes towards podcast editing and hosting. Support Unfinished Business on Patreon.

From: Adactio

Concertina

I watched a good film last night. Tornado from the same writer and director of the also-excellent Slow West.

Tornado is a Scottish Samurai Western set in the 1790s. Although it’s not likely that many Samurai would’ve been in Scotland during the sakoku period, I was willingly able to suspend my disbelief …until something quite minor happened on screen.

One of the characters is seen playing a concertina. “Hang on”, I thought, “1790s? That’s not right!”

And indeed, once the film was over I reached for my laptop and confirmed that the concertina is very much a 19th century invention.

Look, it’s not that I know when most musical instruments were invented, but I happened to know about the concertina’s origin because of a different technology.

See, the concertina was invented by one Charles Wheatsone. He invented quite a few things. He, along with William Cooke, more or less created the electric telegraph, around the same time as Samuel Morse.

I only know this because of the excellent book by Tom Standage called The Victorian Internet:

The remarkable story of the telegraph and the nineteenth century’s online pioneers.

Prompted by that book, I found out more about Wheatstone, including the fact that he invented the concertina. So that’s why I found myself slightly taken out of the action when watching that film last night. In the 1790s, nobody was playing the concertina in Scotland or anywhere else.

Today, though, the concertina is thriving, especially in Ireland. It’s particularly popular in County Clare. Though, as I’m writing this, I’m listening to the playing of a Kerryman, Cormac Begley.

I’ll be seeing him play tonight in the Brighton Dome where he’ll be providing the music for the superb Teaċ Damhsa production, MÁM. This’ll be my second time experiencing it. Táim ar bís!

From: Zeldman

Works in Progress

New tunes from an old maker.

The post Works in Progress appeared first on Jeffrey Zeldman Presents.

From: Dave Rupert

Magic Words

Skills are the newest hype commodity in the world of agentic AI. Skills are text files that optionally get stapled onto the context window by the agent. You can have skills like “frontend design” or “design tokens” and if the LLM “thinks” it needs more context about that topic, it can import the contents of those files into the context to help generate a response.

Generally speaking, skills do an okay job at providing on-demand context. Assuming the AI model is always 12-to-18 months behind in its training data, a skill could potentially backfill any recent framework updates. A skill could potentially undo some training data biases. A skill could potentially apply some of your sensibilities to the output. I’ve seen some impressive results with design guidance skills… but I’ve also seen tons of mediocre results from the same skills. That’s why I deliberately use the word “potentially”. When skills can be optionally included, it’s hard to understand the when and why behind how they get applied.

In that way, skills remind me a bit of magic numbers.

In programming “magic numbers” are a pattern you typically try to avoid. They’re a code smell that you haven’t actually solved the problem, but found a workaround that only works in a particular context. They’re a flashing light that you have brittle logic somewhere in your system. “We don’t know why, but setting the value to 42 appears to have fixed the issue” is a phrase that should send shivers down the spine.

And so now we have these “magic words” in our codebases. Spells, essentially. Spells that work sometimes. Spells that we cast with no practical way to measure their effectiveness. They are prayers as much as they are instructions.

Were we to sit next to each other and cast the same spell from the same book with the same wand; one of us could have a graceful floating feather and the other could have avada kedavra’d their guts out onto the floor. That unstable magic is by design. That element of randomness –to which the models depend– still gives me apprehension.

There’s an opaqueness to it all. I understand how listing skills in an AGENTS.md gives the agent context on where to find more context. But how do you know if those words are the right words? If I cut the amount of words (read: “tokens”) in a skill in half, does it still work? If I double the amount of words, does it work better? Those questions matter when too little context is not enough context and too much context causes context rot. It also matters when you’re charged per-token and more tokens is more time on the GPU. How do you determine the “Minimum Viable Context” needed to get quality out of the machines?

That sort of quality variance is uncomfortable for me from a tooling perspective. Tooling should be highly consistent and this has a “works on my machine” vibe to it. I suppose all my discomfort goes away if I quit caring about the outputs. If I embrace the cognitive dissonance and switch to a “ZOMG the future is amazeballs” hype mode, my job becomes a lot easier. But my brain has been unsuccessful in doing that thus far. I like magic and mystery, but hope- or luck-based development has its challenges for me.

Looking ahead, I expect these types of errant conjurations will come under more scrutiny when the free money subsidies run out and consumers inherit the full cost of the models’ mistakes. Supply chain constraints around memory and GPUs are already making compute a scarce resource, but our Gas Towns plunder onward. When the cost of wrong answers goes up and more and more people spend all their monthly credits on hallucinations, that will be a lot of dissatisfied users.

Anyways, all this changes so much. Today it’s skills, before that MCP, before that PRDs, before that prompt engineering… what is it going to be next quarter? And aren’t those all flavors of the same managing context puzzle? Churn, churn, churn, I suppose.

File under: non-determinism

From: Zeldman

Claude Code for Designers

FIRST, the disclaimers: Some of my favorite writers—folks who are as anti-fascist and pro-democracy as they come—publish on Substack, but I read and recommend their work less and less frequently, because Substack has a Nazi problem. To wit: Awkward: Substack’s Nazi Problem Substack call themselves a platform rather than a publication, a classic web conundrum. […]

The post Claude Code for Designers appeared first on Jeffrey Zeldman Presents.

From: Boagworld

Stuck in a Website Fixing Loop? Try This.

Fixing a broken website means inheriting all the reasons it broke. Try starting from nothing instead.

From: Zeldman

“A streamlined newspaper for a streamlined era”

Posted today for no particular reason.

The post “A streamlined newspaper for a streamlined era” appeared first on Jeffrey Zeldman Presents.

From: Dave Rupert

Write about the future you want

There’s a lot that’s not going well; politics, tech bubbles, the economy, and so on. I spend most of my day reading angry tweets and blog posts. There’s a lot to be upset about, so that’s understandable. But in the interest of fostering better discourse, I’d like to offer a challenge that I think the world desperately needs right now: It’s cheap and easy to complain and say “[Thing] is bad”, but it’s also free to share what you think would be better.

If complaining worked, we would have won the culture war already. We’d have a reformed Elon and the White House wouldn’t be committing crimes against humanity. But that’s not the world we live in. The one we live in is much worse. If you hate the here and now, write about what would be a better future. Write about what’s good and why more of that good would be good.

If you believe the current trend in tech is exploitative, write about tech that isn’t. What impresses you? What compromises did you make? Are you happy? Does giving money to a small bootstrapped company feel ten thousand times better than a large venture-backed company like I imagine? Can you list some of those out for me? Show me where I can throw my dollars.

If you detest content theft at a massive scale, describe a world where copyright matters. Tell me how you’re only going to watch TikToks with royalty free music from now on and not use an ad-blocker. Tell me how you’re going to delete that hard-drive of pirated content. No? Then invent a better copyright system! Talk about the commons and how we should tax people who abuse it by taking more than they give. What does that system look like?

If you detest the ecological impact of AI data centers, propose an alternative piece of technology that drives shareholder value. Or advocate for a broader, more equitable definition of Responsible AI. Don’t let the Effective Altruists define the terms. Itemize the problems and then dream up a version that doesn’t have those. List demands. Find levers. Or make the case for how small, local, private, and less energy-intensive models are probably “good enough” for most use cases and we should stop burning barrels of crude and use those instead. If we must throw it away, point people to organizations and political groups working towards that end.

If you believe billionaires are the problem, talk about a world without them. Share how we redistribute a billionaire tax equitably and talk about the impact it has on society. Make a spreadsheet or a chart. Get into numbers. Talk about degrowth. I know that “Line Goes Up” has problems and won’t work forever, but how are my family and I more okay if we undo centuries of continued economic growth and technical acceleration.

I think history is wrought with examples of this working; Dr. King’s “I have a Dream” speech, the Federalist Papers, David Hasselhoff singing at the Berlin Wall during the height of the Cold War… the list goes on. Few will rise to the level of Ambassador Hasselhoff, but I don’t have to look far to find people around me who have inspired me by writing about the future they want.

After repeated mass layoffs, Ethan Marcotte identified a problem with the wealth and labor dynamics in the tech industry. While Ethan could have been perfectly happy bitching about it on Twitter, he didn’t do that. Instead, he put hands to keyboard and made a talk, which turned into a book, about what he feels is the time-tested solution to our predicament: Unions. Truthfully, I’m not particularly predispositioned to be pro-union (Texan, etc), but Ethan and I agree on the problem. Seeing Ethan spend time to communicate the problem and explore the solution changed my opinion on unions. And while I certainly still have nuanced questions, Ethan convinced me that collective action is the best leverage workers have against abuses of labor. That wouldn’t have happened without Ethan’s dedication to highlighting the problem and the solution over many years.

Often people need you to show, not tell the alternative. You need to paint a picture. Not a full complete picture, but one where a person can paint themselves in it. When people want change and bad change is happening all around them, that’s a hopeless place. Build a raft of opportunity that people can latch onto in the rough open waters, instead of hitting them with spears.

From: Stuff & Nonsense

Panzera Flieger 47

I bought my first mechanical watch back when we were living in Australia for those couple of years. It was a Flieger 47 from the Australian brand Panzera, and it sparked my love of pilot watches.

I’m not sure how I found out about Panzera, but I suppose it was an ad on social media, most likely Instagram. They’re based in Sydney—which is where I was—and design their own watches using Swiss movements. The Flieger 47 was an homage to the WW2 pilot watches made for the Luftwaffe and Allied air forces by brands like IWC.

Panzera Flieger 47
Left: Panzera Flieger 47. Right: My IWC Big Pilot 43.

It has all the hallmarks of a Big Pilot, with an oversized onion crown and a large, clear display. From a reasonable distance, it looked very similar to an IWC Big Pilot and coffee shop watch nerds commented on it more than once.

I bought one in a sale for around AUD $400 and loved it. That was until the crystal mysteriously cracked during some very hot weather, and it’s been in a drawer ever since.

I really must send it back to Panzera for repair, although I suspect that will cost me more than what I paid for the watch when I bought it.

From: Zeldman

Mark your calendar: Local News Day is 9 April

It’s no secret that newspapers across the country exist in a fragile ecosystem. Automattic has long supported journalism and local media with investments in publications and platforms like Longreads, The Atavist, and Newspack. We believe that local news still matters—and now more than ever. That’s why we’re sponsoring Local News Day on April 9, 2026. — Support Journalism with […]

The post Mark your calendar: Local News Day is 9 April appeared first on Jeffrey Zeldman Presents.

From: Adactio

Daughters of Sparta by Claire Heywood

Towards the end of 2025, I wrote:

I think I might change things up in 2026. Instead of waiting until the end of the year to write all the little reviews at once, I think I should write a review as soon as I finish a book. Instead of holding onto my reckons for months, I can just set them free one at a time.

I’ll get the ball rolling with the first book I read in 2026.

I’ve mentioned before that one interesting lens to apply to modern retellings of the Greek myths is how they treat deities. Are gods and goddesses real in this story? Or is it a non-interventionist tale with a purely human cast? In her book The Shadow Of Perseus, Claire Heywood wrote about Perseus, Medusa, and Andromeda without any supernatural characters. Having been impressed by that, I figured I’d go back to investigate her debut, Daughters Of Sparta.

The framing device is one I hadn’t come across before. It follows the diverging stories of sisters Helen and Clytemnestra, flipping back and forth between the two throughout their lives. I’ve read plenty of takes on the Trojan war, and I’ve read plenty of takes on Clytemnestra’s revenge, but I think this is the first time they’ve been combined like this.

Overall, it works. There are inevitable time jumps. Some time periods are bound to get more attention than others. And at some point, the narrative just has to wrap up, even though we know there’s pleny more that follows afterwards.

All in all, a good addition to the list of modern retellings of classical Greek stories.

Buy this book

From: Chris Coyier

Tubes

Me, Stacey, and Miriam kicking it talkabout about CSS Scope & Mixins: Daniel and I chattin’ about playing the long game

From: Boagworld

Why Moving Buttons Won’t Fix Your Conversion Rate

CRO agencies promise quick UI fixes, but real conversion improvements need content overhauls and organizational change too.

From: Zeldman

We named them after the humans they were replacing.

“The word ‘computer’ only really slid over to mean ‘a machine’ in the late 19th and early 20th centuries, once we started building mechanical and then electronic devices to do that work instead [of people]. We did not name the machines after some abstract idea. We named them after the humans they were replacing.”

The post We named them after the humans they were replacing. appeared first on Jeffrey Zeldman Presents.

From: Dave Rupert

I'm swearing off APIs entirely

I got a lot of ideas for side projects rattling around in the old tin can. As part of my “No new projects” initiative, I’m trying to jump on building prototypes so I can decide if I want to explore ideas more or call it quits. A handful of my ideas are riffs or twists on existing app categories:

  • A tennis ranking app… but modern and performant
  • A nearby historical marker app… but with CarPlay support
  • A nearby real estate listing app… but with CarPlay support

All three of those have ended unceremoniously at the same dead end: no API access. USTA denied my application for tennis rankings. The aptly named Historical Marker Database site doesn’t have a public API. And you have to be an MLS® Realtor® or Broker to get access to the MLS® listings. Womp womp.

Scraping the data is always an option… but I don’t like the ethics of that and worry about the brittleness of that dependency.

Ugh. I wish I could build these little apps so that tens of people could enjoy them. I’d even be willing to pay a small API access fee ($10/mo?) and run these at a loss but whatever happened to free APIs. When I survey the land of public APIs it feels like we’ve lost a lot since the Web 2.0 days where API access was almost a God-given right.

To prevent this time loop of disappointment from happening again, I’m swearing off APIs entirely. That’s a hard stance, but I need a backstop at the idea phase to prevent me from wasting limited life force. If I don’t have the data, or can’t generate the data, or it’s not an open protocol… it’s not worth building or even thinking about.

OAuth apps are a good option and generally the best way to exfiltrate data because it’s tied to a user’s account…. but you still might run into call limits, incomplete endpoints, user-scope limitations, and so on. History also shows us what the future holds. There’s a Tweetbot-style risk when building on a someone else’s platform. Even if your app drives activity to the parent application, your access might get cut because it competes or doesn’t drive stakeholder value. And if the idea isn’t big enough, being “a feature, not a product” is also a bad position to be in, lest you get Sherlock’d.

Where’s that leave me and my pile of side project ideas? Thankfully… in a good place. I can close out these project tabs and free up some much needed Brain RAM. It sounds strange but “No more APIs” makes “Making video games” jump up in the viability rankings for side projects too, because games have closed ecosystems. Or I could spend more time writing shitty sci-fi. Write a serial. Print some zines. Who knows.

If the goal of “No new projects” is to finish more projects than I start, then I have to accept that part of figuring out which ideas to explore means “Nope” is a potential answer. It’s also not a total loss, I’m learning along the way. For example, CarPlay only lets you choose from eight pre-approved templates. There’s also pre-defined app categories and diverting in the slightest would almost guarantee App Store rejection. That sucks the fun out it… but ayyyy, I’ll probably try again. But now I know the limitation for future projects and its in the limitations where play begins.

From: Dave Rupert

Waiting for the power to go out

It’s a secret to everyone! This post is for RSS subscribers only. Read more about RSS Club.

It’s expected to freeze this evening in Austin and we may even see snow, which is exciting and novel for us Texans. But as we’ve learned in 2021 and 2023, cold snaps can lead to disaster. In those years the ice dealt untold damages as foot-thick tree limbs fell from the canopy like enormous glass Cadillacs. The crackle, pop, followed by crystalline shatter in the cold dead air is a sound I won’t forget. With the falling trees came down power lines and the lights went out.

It got worse. The disconnected Texas power grid failed. As homes and empty office buildings required more heating in the “extreme” cold, the rolling blackouts began to shed load. Except… they didn’t roll. Homes next to facilities (hospitals, fire stations, and water treatment plants) deemed critical were fine, but the rest of us were off-grid in the cold for nearly a week. The energy companies could have met capacity, but quit making energy because they would have had to sell it at a loss. Greed until the state promised them a windfall.

The infrastructure failed. Pipes burst, homes flooded, and trauma increased. While our senator and his banker wife fled to Mexico to stay in a Ritz Carlton, Texans burned their IKEA furniture and cedar fences to stay warm.

Building on past lessons, we’ve made all the preparations for today; external faucets capped, plants covered, and I built a cabinet out of foam board insulation for our external hot water heater. And now we wait… we wait to see if the Libertarian Capitalist systems my state has put into place will hold up. Waiting to see if the power goes out. Waiting for the impending disaster.

If you’ve ever had a child, you might know this feeling. You’ve taken the classes, assembled the crib, child-proofed the outlets, and then you wait… you wait for your life to change. While the miracle of childbirth is a beautiful event, any mother can tell you it’s not without some drawbacks. From prolonged labor, painful contractions, episiotomies, and beyond… every birth is a dice-roll of potentially life-threatening complications. A friend of mine who had three kids described it well; “Having a baby is like knowing you’ll be in a car accident.”

That feeling of pregnant, expectant waiting dominates a lot of my life right now as I wait for all the larger meta narratives in our country to unravel. I’m waiting for a mid-term election, one where I feel the fabric of democracy hangs by a thread. I’m waiting for an opposition party that has a fucking plan, but I don’t see one yet. I’m waiting for a particular person to leave office… or (preferred) die of natural causes. I’m waiting for the full release of the Epstein files, so the victims of billionaire pedophilia and human trafficking can have justice. I’m waiting for the government to stop its reign of cruelty on its own people, but masked fascists killed another innocent person in broad daylight today. I’m waiting for the economy to work for most Americans, not only the wealthy. I’m waiting for either the tech bubble to pop or for the robots to take my job… either way I’d like this story line to wrap up soon but I must ask, is there a third option? I’m waiting for the next big thing and praying it’s something that makes the world more loving and kind, but a new global religion would be a lot to deal with right now.

From: Boagworld

Generative Imagery: Stop Settling for Stock

Stop settling for 'almost right' stock photos. A practical guide to generative imagery tools, when to use them, and how to get consistent results.

From: Adactio

Web Day Out × State Of The Browser

If you’re the kind of person who likes Web Day Out, you’re probably also the kind of person who likes State Of The Browser.

Web Day Out is all about what you can in web browsers right now, with an emphasis on immediately practical techniques and technologies. State Of The Browser is similar, but with room for fun demos that push the boundaries.

State Of The Browser is on Saturday, 28 February.

Web Day Out is on Thursday, 12 March.

It would be a shame if you had to choose between these two excellent events.

Well, you don’t have to!

If you buy a ticket for Web Day Out you can get a whopping 50% off the ticket price for State Of The Browser. Or if you can’t make it in person, your Web Day Out ticket gets you a free online ticket!

You might be thinking, “Well, much as I’d love to go to both events, I don’t think I can convince my boss to give me two conference days.” Worry ye not! State Of The Browser is on a Saturday, so unless you’re working an extremely extended work week, you still only need to take one day away from your desk to go to two events.

So don’t delay: get your ticket for Web Day Out. Then you’ll get an email with details on how to get your 50% discount for State Of The Browser (or your free online ticket, whichever you prefer).

But wait! What if you already bought a ticket for State Of The Browser? Check your email. You’ve been sent a very, very generous discount code for Web Day Out to thank you for getting your ticket nice and early.

I’ll see you at State Of The Browser in London …and then I’ll see you at Web Day Out in Brighton!

From: Chris Coyier

Just in case I haven’t made my feelings clear lately on the current United States of America administration, I shall blog. It’s the little things that make me think Donald Trump is a vindictive prick who, among his catalog of things he hates, is Black people. For instance, he’s chosen to change what days are […]

January 20, 2026, 5:26 pm >>

From: Chris Coyier

Worry Bird

I think the Worry Bird is a cute idea. You use it to, ya know, worry into, by rubbing your thumb into the satisfying little divot to do so. Of course, us web workers tend to turn our worry into superfluous personal website redesigns. [feels urge growing]

From: Adactio

Trad travels

For the past few years, I’ve been taking a trip to Spain at the end of September for the Cáceres Irish Fleadh. Last year I convinced my friends Liam and Monica to come along and they had a great time.

Like me, Liam just loves playing in sessions. Also like me, Liam likes to spend the gloomy short days of January thinking about travelling somewhere …and then playing in sessions there.

I told him I’d put together a list of potential trips for the discerning session hound. I figured I might as well share it here too…

First of all, there are Irish music festivals. Alas, most festivals don’t happen in the sunny climes of Spain. As you’d expect, most of them are in Ireland.

I’m heading to Carlingford at the end of this month for a weekend of Féile na Tána. I haven’t been before but it looks good. There’ll be the usual amalgam of workshops, concerts, and sessions.

Myself and Jessica will fly in to Belfast, then take the train down to Newry and get to Carlingford from there. You could fly into Dublin and get the train up to Dundalk, but the only Gatwick flights to Dublin are Ryan Air, and I’d rather entrust my instrument to EasyJet.

At the end of March we’re heading to Tullamore Trad Fest. That’s another one we haven’t been to before. Again, there’ll be workshops, concerts, and sessions.

Tullamore is just an hour away from Dublin by train and has plenty of accommodation options. We’ve booked into a nice-looking B&B.

There’s no avoiding Ryan Air for this trip and I want to take my good mandolin, so I’ve gone ahead and booked a separate seat for it. I don’t want to take any chances with an airline that actively seeks to elevate misery.

The festival I heartily recommend is Belfast Trad Fest at the end of July. It’s super convenient to get to with EasyJet flights from Gatwick—go to Belfast city airport, which is right downtown.

The festival offers a really good accommodation deal in modern student flats. The workshops are top-notch, and best of all, it has a really well-organised session trail. You can easily play in sessions all afternoon and evening.

This year, for the first time ever, Belfast trad fest is immediately followed by the all-Ireland fleadh, which promises to be pandemonium. I’ve never been to the fleadh before but I’m going to stick around Belfast for it.

You could head to the Willie Clancy Festival in Miltown Malbay at the start of July (the website seems to be having some issues right now). But good luck finding accommodation. The event is so big now that unless you’re camping, there’s not much chance of finding a place to stay. If you make it there though, non-stop sessions await. Non-stop chaos awaits too. That’s part of the deal. Great workshops though!

There are other festivals I haven’t been to but I’ve heard great things about. The Pádraig O’Keeffe Festival in Kerry in October sounds fantastic, especially if you like your polkas and slides. But it’s in Castleisland, which doesn’t have much in the way of accommodation. So unless you’ve got transport, it’s going to be tricky.

There’s a trad fest in Kilkenny in March. I’ve never been but they’ve got a session trail. You’d need to fly into either Dublin or Cork and then get on a bus. Either way, it’s Ryan Air from Gatwick.

I’ve also never been to the Ennis Trad Fest in county Clare in November but I’ve heard good things. Accommodation for the 2026 event is already in short supply though.

But you don’t need a festival to play in sessions. In fact, the kind of sessions you end up in at festivals have a different vibe to the usual sessions, simply because they’re formed of a hodge-podge of visiting players.

There a few spots in Ireland where you’re guaranteed a session pretty much any night of the week.

I love Galway. There are afternoon sessions in Taafe’s and Tigh Cóilí as well as evening sessions in the Crane and other places. You’d need to fly into Dublin and get the train from there. It takes about two hours.

Galway is busy in the summer time and accommodation can be pricy, but if you go off-season you can find some cheaper options.

Ennis has music most nights. There’s a regular bus service between Ennis and Shannon airport that’s nice and quick. You’d need to fly Ryan Air from Gatwick though.

And then there’s Belfast again. Even when the trad fest isn’t happening, Belfast has sessions seven nights a week. Check out the Belfast session guide Instagram account for up-to-date details.

I recommend staying in The Flint, but make sure you ask for a room on the top floor far away from the nightclub if you’re there on a weekend.

So, to recap, here are some festivals to check out:

And then for year-round session action, you can visit:

From: Chris Coyier

The Breakaway Moment

I know I’ve mentioned a ton of times: while I enjoy playing videos games sometimes, a little, I enjoy watching other people play them more. Even as a little kid. Like an awesome play date would be going over to a friends to watch them play. Perfect world, the friend would only play when I […]

From: Dave Rupert

The best version of my site so far...

You might have noticed that I did a big design refresh on my entire site… unless you’re on RSS I guess. I’ll talk about aspects in detail, but at a high level there’s been three big changes:

  1. A monospace font
  2. Named CSS grid lines
  3. Juicier multi-page view transitions

But my most favorite part is that today (when you set html { --hue-rotate: 15 }), my light theme looks like a stick of butter. And that brings me joy.

What didn’t change

Before I talk about what changed, here’s a quick list of the parts of my site that didn’t change:

Why change the parts you’re happy with, eh? Knowing what you want to change versus what you don’t want to change makes the whole process go faster.

All-in on a monospace font

My type system always falls apart. I start with a good setup and I’m guaranteed to ruin it over time. Whenever I read a site with a nice typeface and reasonable CPL, I started to feel like my system-ui based body text styles were letting me down. It didn’t feel cozy.

Then I saw Robin Rendle’s latest redesign (which is wonderful, btw) I wondered… Could I be a monospace font guy? Is that me? Do I identify as that? Is it too emo? Does it come off as a bad developer pun like bleep blorp I'm a programmer and using a computer bleep blorp?

All good questions to ask myself and exposes some insecurity I have, but I couldn’t shake the idea so I went for it.

The entire site is now set in Cascadia Mono which is a variant of Microsoft’s Cascadia Code. That decision is unintentionally on-brand for my current stage of life. Initially I wanted to use Inconsolata by Raph Levien, but it didn’t have a “numero” (№) symbol – which is a common missing glyph in a lot of indie fonts – and is an unfortunate piece of critical typographical infrastructure with my vibechecks.

In general I love the change. It feels very “me” right now. I worry about the readability of monospace fonts some, but I don’t think I was winning the Legibility Wars before.

Naming my grid lines

Improving the grid on my site is something I’ve wanted to do for nearly two years. The max-width container I had was fine before, but I relied a lot on margin overrides to change a container that felt like a hack that in my experience don’t scale.

Now I have something better with some sweet tech from Stephanie Eckles that I saw on Kevin Powell’s YouTube called “Named Grid Lines”. A not-so-well-known feature of grid is you can name the gutters in your grid template. The result is a grid that looks like this:

Full
Margin
Wide
Outdent
Content (Default)

See how all the grids collapse into one line that’s offset from the edge? That’s what I want. And then to use it, you specify the *-start and *-end line you tweak your container with a modifier class and make all the children start at a different grid line.

.foo.container > * {
	grid-column: wide-start / wide-end; 
  /* or grid-column: wide */
}

This gives me a lot of scalable control for my layout at the template level. For example, the layout of my homepage looks like this:

Header
Logo
Latest Posts
Projects
Footer

But when you click through to a single post, the template shifts to this:

Header
Title Goes Here
Content
Media
Content
Content
Media
Content
Content
Footer

I don’t have this setup, but I could write out a system of utility classes to make all this super flexible.

.full-start
.margin-start
.wide-start
.outdent-start
Default Content
.outdent-end
.wide-end
.margin-end
.full-end

That’s a lot of different layouts to craft. I look forward to more sustainable art direction for years to come. No more hacky negative margins or fixed positioned items… right?

More Multipage View Transitions

I’ve had multi-page view transitions on my site for years now. The original was a title transition from the index template to the post template where the post title would do a subtle swoop up and morph from an H3 to display-sized H1. This was great until I changed the font for my H1 (see above) and I obliterated the slight of hand magic I had before. Oops.

Now the flagship animation on my site is not typography dependent. If you navigate through my site, you’ll see that the “Dave” SVG on the homepage transitions into the main navigation on subpages. As a bonus, I get a little bit of much-needed branding on subpages. I didn’t do anything special other than naming the view transition and beefing up the stroke when the logo is in its smaller form.

The main nav is out-dented a bit by default, but using my new named columns I made the navigation go wider to match wide pages like my Bookshelf. Flexbox’s justify-content: space-between and view-transitions is doing all the heavy lifting on that animation there but I’m pleased with the effect and it feels natural (aka not synthetic and cheap).

I’m not a motion expert like Cyd Stumpel, but it feels good to have big, bold, un-ignorable view transitions on my site.

Slimmed down CSS

A redesign is always a great opportunity to clean house. I did the thing where I deleted my entire CSS and started from a naked page. Bit-by-bit I pulled back in the pieces I still needed.

I have about 40% less CSS which manifests in ~150 less lines of code to maintain and up to ~0.8 KB when compressed over the wire.

LoC Raw Min+Gzip Min+Brotli
Before 557 10.3 KB 2.76 KB 2.43 KB
After 391 5.36 KB 1.97 KB 1.76 KB

Now 0.8 KB isn’t much but because I inline my critical CSS the <head> on every page, this number matters. My entire homepage document is ~5.5 KB (Brotli), so that’s a 10%~20% performance improvement from cleaning up my CSS. How did I get these gains, you ask? Well…

One reason my CSS smaller is because I’m using modern CSS (nesting, :has(), :is(), :where(), :not(), etc). Those features seem like minor syntactic sugar but you also get more efficient selectors. For example my out-denting that I do in posts would previous be something like:

.post iframe, 
.post video, 
.post img,
.post table { }

In modern CSS that super-conjoined selector becomes something more expressive and elegant:

.post :is(iframe, video, img, table) {}

Those small improvements add up, but another reason the CSS is smaller is because its doing a lot less. Other than my inverse-sized H1s in posts, I’m not managing type styles at all beyond setting the body font-size. I think this is what Andy Bell calls “Be the Browser’s Mentor, Not Its Micromanager”. My strategy here is: Don’t futz with it until you can think of something way better than what the browser already does. That seems very Dao or Web’s Grain’y.

Onward to more art direction!

This redesign opens up a bright future for my site. I’ve already started on some of this work, but I’ll share that in a future post. I mentioned above but the named grid lines alone give me a lot of easy-to-use levers for expression. I touched up some old art-directed posts and they are benefitting from the changes already.

“Make it easy to play” seems like a good ethos for a personal site and I feel like I have that in the current manifestation.

From: Boagworld

Be a contributor, not a lurker

Stop lurking. Start contributing. Simple ways to build reputation and relationships (without turning into a LinkedIn gremlin).

From: Stuff & Nonsense

Smashing Animations Part 8: Theming Animations Using CSS Relative Colour

Yours truly over at the Smashing Magazine: “CSS relative colour values are now widely supported. In this article, pioneering author and web designer Andy Clarke shares practical techniques for using them to theme and animate SVG graphics.”

Read Smashing Animations Part 8: Theming Animations Using CSS Relative Colour

From: Dave Rupert

Focus rings with nested contrast-color()?

As I was playing around with contrast-color(), I got a wild idea that you could use contrast-color() to invert its return value by nesting it: contrast-color(contrast-color(var(--some-color)). When would this be useful? Uh… Good question. I couldn’t come up with an example right away but after a bit I found one sitting right under my nose….

four buttons in one line. a secondary button, an accented primary button with a focus state, a subtle button and a transparent button

Our focus-rings in Fluent use a 1px inset white highlight and a 2px offset black focus-ring. It’s a smidge chonkier than the Chromium default. The reason we do this is to guarantee contrast against the focused-element, in the above example, a blue button. Without the addition of the white stroke, the black outline wouldn’t “pop” with enough contrast to the blue background.

To make this work, we have a --focus-inner-ring token and a --focus-outer-ring token themed for both light and dark modes.

*:focus-visible {
  box-shadow: 0 0 1px 0 var(--focus-inner-ring);
  outline: 2px solid var(--focus-outer-ring);
  outline-offset: 1px;
}

How would this change with nested contrast-color()?

*:focus-visible {
  outline: 2px solid contrast-color(var(--page-bg));
  outline-offset: 1px;
  box-shadow: 0 0 1px 0 contrast-color(contrast-color(var(--page-bg)));
}

All you would need is one token you probably already have (--page-bg) vs two tokens. Neat.

One consideration… your focus-ring isn’t always on a --page-bg. Sometimes it shows up on a --card-bg and this little trick might fall apart. As always, your mileage may vary.

Aside: This got me thinking it’d be nice to have a currentBackgroundColor like we have currentColor in CSS today. I’m not sure how much career I’ve got left to wait for that, but who knows.

On second thought…

Mulling this over a bit more… you might be better off using color-scheme and light-dark() for this instead.

 :root {
	 color-scheme: light dark;
 }
 
 *:focus-visible {
   box-shadow: 0 0 1px 0 light-dark(white, black);
   outline: 2px solid light-dark(black, white);
   outline-offset: 1px;
}

Yeah… I’d probably do that. You dodge the spotty contrast-color() support and have a singular function instead of a nested situation. It keeps it simple and readable.

If you converted this to tokens, you’d probably need four tokens to fill out the inner/outer and light/dark matrix. But I’d consider not using custom color tokens for focus-rings at all and embrace the higher contrast… or limit tokens to the outer-ring.

From: Dave Rupert

Interpolate contrast-color() to manipulate lightness

In my first post on contrast-color() I demo’d using color-mix() to change a background-color on hover, but I will be honest… mixing black and white isn’t always what you want. It would be cool and helpful to coerce contrast-color() to return either 1 or -1 so that we could adjust lightness in a color function on hover instead of only mixing white and black.

Building on the inline CSS if() statements in my last post, we can use the same trick to interpolate the result of contrast-color() into a number.

Disclaimer: All caveats from the previous post about browser support, caching quirks, and expected syntax changes still apply.

See the Pen contrast-color() powered design system colors by Dave Rupert (@davatron5000) on CodePen.

Ahh… feel that? Now our states maintains its harmonious color palette where mixing in white or black gets us a bit muddier results. We’re picking another note on the scale of the color’s lightness ramp.

The relevant CSS to make this trick work goes like this:

/* Needed for if() statement */
@property --captured-color {
  syntax: "<color>";
  inherits: true;
  initial-value: white;
}

/* https://lea.verou.me/blog/2024/contrast-color/ */
@function --contrast-color(--bg-color) {
  --l: clamp(0, (l / var(--l-threshold, 0.623) - 1) * -infinity, 1);
  result: oklch(from var(--bg) var(--l) 0 0);
}

button {
  background-color: var(--ds-button-bg);
	--captured-color: --contrast-color(var(--ds-button-bg));
  --lighter-or-darker: if(
    style(--captured-color: oklch(1 0 0)): 2.5; /* go extra lighter */
    else: -1; /* go darker */
  );  
  ...
  
	&:hover, &:focus {
		background-color: oklch(
			from var(--ds-button-bg) 
			calc(l + (0.1 * var(--lighter-or-darker))) c h 
		);
  }
}

For comparison’s sake, I web-inspected up a little apples-to-apples, side-by-side of the adjusting lightness way and the color-mixing way of algorithmic hover states where it’s 10% lightened/darkened versus 10% mix of white/black.

a side by side look at adjusting lightness vs mixing in white and black. the rest for all the buttons is on top and the hover state for all the buttons is on the bottom. The hover states for the buttons on the adjusting lightness demo are a bit warmer, but probably hard to notice to the average person.

The difference is almost imperceptible, but the hover states from the “Adjust Lightness” method feel a tad bit warmer, particularly on the bottom row with the green, blue, and purple buttons. The difference becomes more obvious if the step is greater than 10%.

Unless your customers are a bunch of color dorks, they probably won’t see it the care you put into this. But I’m willing to wager that even if they don’t see the difference, they will be able to feel the difference.

We also get a lot more control with this if() statement route. For example, I can set the lighten amount to 2.5 (+25%) instead of 1 (+10%) because that’s what felt better. If you’re algorithmically generating your color palettes, it should be easy to find the ideal values; either a step-up or step-down, perhaps. And we’re also not just limited to lightness! You could mess with chroma or whatever the b in lab() is. Find what makes sense for your system.

A part of me wants to take this even further to get more control. For example, if the color is super dark (e.g. black) and the lightness value is below 0.1, lighten by 25%, otherwise lighten by 10%. That might be possible with an if() inside the oklch() or a sin() function… but that sounds like a lot of Math and probably hurts readability. More experiments to do though.

It’s fun to embark on this new world of algorithmic color schemes in vanilla CSS. While I’m excited to play, I’m more excited to see what your beautiful brains come up with.

From: Dave Rupert

Using your design system colors with contrast-color()

One predictable pain point with contrast-color() is that it only returns black and white named colors. From a design systems perspective, that’s not ideal because you want your colors. You want your harmonious brand and the colors you and your team spent thousands of man hours in meetings deciding on. Those colors.

In fact, an earlier version of Safari had color-contrast() (confusing I know, naming is hard) which allowed you to pass in a list of best candidates to choose from. I beleive that proposal got mired in standards discussions, color contrast algorithms, and competing proposals; and contrast-color() is what survived which got simplified down to a binary result.

In the future though, we can use contrast-color() and if() together to help pick the value we want. Alas, at the time of writing no browser supports both if() and contrast-color(). But we can use Lea Verou’s --contrast-color() workaround to experiment with how this will work in Chromium today.

See the Pen contrast-color() powered design system colors by Dave Rupert (@davatron5000) on CodePen.

The CSS to get this working looks something like this:

@property --captured-color {
  syntax: "<color>";
  inherits: true;
  initial-value: white;
}

/* https://lea.verou.me/blog/2024/contrast-color/ */
@function --contrast-color(--bg-color) {
  --l: clamp(0, (l / var(--l-threshold, 0.623) - 1) * -infinity, 1);
  result: oklch(from var(--bg) var(--l) 0 0);
}

:root {
  --ds-text-white: wheat;
  --ds-text-black: darkslategray;
}

button {
  background-color: var(--ds-button-bg);
  --captured-color: --contrast-color(var(--ds-button-bg));
  
  color: if(
     style(--captured-color: oklch(1 0 0)): var(--ds-text-white);
     else: var(--ds-text-black);
  );
}

And that’s it! Using (a form of) contrast-color() you can select the proper tokens from your design system. Cool.

One quirky bit needed to make it work is defining a type for --captured-color using CSS @property, a trick I learned from Roma Komarov. To be honest I don’t fully understand the why behind Registered Custom Properties and the Computed Value Time Behavior superpower, but my simple brain created a rule “If you’re going to compare a variable to a <color> in a CSS if() statement, make sure to register the variable as a <color>.”

If/when any of the browsers start supporting both features, I expect we’ll have to update oklch(1 0 0) in the style query to white or rgb(255 255 255). At least, I hope it works that way.

One unexpected challenge that I encountered with this demo was that if I abstracted out the if statement out into its own custom function, it would break. I’m not 100% sure why but I think it’s based on how CSS functions cache results. I’ll have to dig into this more, but I’m happy the inline if statement works. Hopefully someone smarter can figure it out.

Anyways, exiting times. And can we pause for a moment and marvel at how this is all vanilla 2026 CSS?! What a world.

From: Stuff & Nonsense

The Timex x Pan Am Waterbury Automatic Ace

Talk to my family and friends, and they’ll tell you I never bloody stop talking about the IWC Big Pilot 43 watch that I bought to celebrate my 60th in November. Mechanical watches are all over my social media feeds, and the other day I did a double-take when the algorithm suggested I might like a new design from, of all companies, Timex.

The Timex x Pan Am Waterbury Automatic Ace is a 41mm brushed stainless-steel watch from a collaboration between Timex and the nostalgic Pan Am brand. I immediately thought there was something familiar in this watch’s design. But I couldn’t somehow put my finger on it.

Left: IWC Big Pilot 43. Right: Timex x Pan Am Waterbury. (Images from IWC and Timex.)

The Timex x Pan Am Waterbury bears more than a passing resemblance to the latest addition to IWC’s iconic Big Pilot line, the Big Pilot 43, which is on my wrist now. But it most closely resembles IWC’s Pilot’s Watch Mark XX. You can see just how closely Timex followed IWC when the two dials are scaled to match.

Left: Timex x Pan Am Waterbury. Right: IWC Pilot’s Watch Mark XX. (Images from IWC and Timex.)

The Timex’s hour and second hands match the IWC Mark XX, while the minute hand is straighter. Its date window is the same size, although I’m unsure why the dot—between it and the marker in the 3 o’clock position—was necessary. Placing the word “Automatic” under the 6 is neat and leaves room for the Pan Am logo above. I actually prefer this placement to IWC’s, where it’s beneath the Mark XX type. The size relationship between the words “Timex” and “The Waterbury” looks identical to that between “IWC” and “Schaffhausen.”

Close-up of the Timex x Pan Am Waterbury dial. (Image from Timex.)

Timex did a nice job of placing the Pan Am logo on the crown and using its signature blue on the inside of the strap.

Pan Am logo on the crown. (Images from Timex.)

On the dial, the line between that famous logo and the plane icon at the 12 o’clock position comes straight from Pan Am’s design history.

Linework on the Pan Am logo and Timex dial. (Images from Pan Am and Timex.)

I don’t know which typeface Timex chose for their numerals on the Waterbury dial, but it certainly isn’t the Helvetica, which Pan Am briefly switched to between 1970 and 1973.

Helvetica and the short-lived Pan Am brand redesign. (Image from Timex.)

Oh, and if you’re curious how Helvetica looks on a watch dial, IWC used it for the numerals on its 1993-released Mark XII.

Helvetica on the IWC Mark XII. (Image from Chrono24.)

I suppose that, being a collaboration with Pan Am, the question to answer is whether this is a successful pilot’s watch design? I’d say it is. It’s not overly large, but it is legible. The skinny minute hand isn’t as obvious as IWC’s, and there’s that inexplicable dot next to the date window, but as an homage to the pilot’s watch, it’s nice. Is it more than an homage to IWC’s iconic Big Pilot design? I’d say so.

But I like it. Hell, I might just buy one for fun to wear places and times when I wouldn’t be comfortable wearing the real thing.

From: Dave Rupert

Algorithmic hover states with contrast-color()

Firefox 146 added support for contrast-color() joining Safari 26 in the First Implementor’s Club. For those unfamiliar, contrast-color(<color>) is a new CSS function that will take a <color> as input and returns either white or black depending on which has the most contrast.

The quintessential example is choosing a foreground text color with the best contrast.

button {
	--button-bg: red;
	background: var(--button-bg);
	color: contrast-color(var(--button-bg)); 
	/* @returns black (5.25:1 WCAG AA Pass) 
			not white (3.99:1 WCAG AA Fail) */
}

If someone changes --button-bg to purple, the foreground color automatically resolves to the either white or black, whichever has more contrast. It avoids having to set an extra token for color and takes the guess work out of picking an accessible foreground color.

I think this is going to be an incredible boon to design systems where I don’t control what --button-bg is, but I do care about providing accessible experiences. And I think that’s the goal of this feature; to have “smart defaults” that lead to more accessible websites, easier algorithmically-driven color systems, and better “theme a whole website from a single color picker” demos.

Sure contrast-color() can do foreground colors, but what about backgrounds?

We’re having conversations at work about algorithmically driven rest/hover/active states for Buttons. In the current Baseline you can use color-mix() to lighten/darken colors on :hover

button {
	background-color: var(--button-bg);
	color: contrast-color(var(--button-bg));

	&:hover, &:focus {
		background-color: color-mix(
			in srgb,
			var(--button-bg) 90%,
			black 10%
		)
	}
}

The code above will dim your button on :hover 10% by mixing in black. But what if our Buttons are already dark (black, navy, etc)? In that situation we want to lighten the background-color instead of dimming. We can glue on new classes like button.lighten-on-hover or button.invert-hover and that works… until we get to light and dark theme modes of our Button where you probably want to lighten/darken oppositely depending on the mode…

Ugh. In that situation you’d have @media (prefers-color-scheme: dark), [data-theme="dark"] styles in your Button styles and people are mad now because the Button styles are too complex. There’s got to be a better way!

Well, do I have good news for you…

See the Pen contrast-color() powered lighten/darken bg on hover by Dave Rupert (@davatron5000) on CodePen.

Per my previous conversations, I wondered if we could use contrast-color() to programmatically lighten/darken an button based on its current background-color. If the Button is black, and the contrast-color is white, let’s mix in white (and vice versa):

:root {
	color-scheme: light dark;
	--button-bg: light-dark(navyblue, lightpurple);
}

button {
	background-color: var(--button-bg);
	color: color-contrast(var(--button-bg));

	&:hover, &:focus {
		background-color: color-mix(
			in srgb,
			var(--button-bg) 75%, 
			contrast-color(var(--button-bg)) 10%
		)
	}
}

Huzzah! Now our Button’s hover states go in the desired direction and our foreground color is intrinsically styled based on its own background-color. Nice. From a design systems perspective I’m pretty excited about the possibility to remove a bunch of state-based tokens from our collection.

Now available in… everywhere?

This approach only works in Safari and Firefox. However, if I use Lea Verou’s method of polyfilling contrast-color(), we can pop in a custom @function --contrast-color() that works in Chromium 139+. The final working solution looks like this:

/* @function supported in Chromium */
@function --contrast-color(--bg-color) {
  --l: clamp(0, (l / var(--l-threshold, 0.623) - 1) * -infinity, 1);
  result: oklch(from var(--bg-color) var(--l) 0 h);
}

button {
  /* contrast-color() supported in Safari & Firefox */
  --button-fg: contrast-color(var(--button-bg));
  
  @supports not (color: contrast-color(red)) {
    --button-fg: --contrast-color(var(--button-bg));
  }
  
  background: var(--button-bg);
  color: var(--button-fg);
  
  &:hover,
  &:focus{
    background-color: color-mix(
      in srgb,
      var(--button-bg) 75%,
      var(--button-fg) 10%
    );
  }
}

Depending on your browser matrix, this may work for you. It’s probably a smidge too new for us to roll out to customers, right now but for personal sites heck yeah.

This is interesting tech and I’m excited to dig in more. And spoiler alert, this is the first post in a small little series I have already written up for you.

From: Boagworld

Stop Lurking. Start Getting Known.

A practical, low-effort system for building your reputation (without turning it into a second job).

From: Boagworld

What I’m seeing for UX as we move into 2026

Not predictions. Just what I'm noticing among the UX professionals I work with right now.

From: Stuff & Nonsense

Snow mode has just gotten even chillier

Although we’ve had a smattering of snow here in the Rhineland—where I’m basing myself for a couple of months—at home, an “arctic blast” means snow is threatening. Last week, I added a snow mode to my websites, but my pioneer characters still looked toasty and warm, and unaffected by the wintery conditions. So, it was time for them to get chilly.

My blog page animated graphic without snow.
Graphic with snow but characters still look warm.

I’ve been writing about CSS relative colour properties for Smashing Magazine, but until those articles land, here’s the short version.

Instead of specifying my characters’ skin tones in the SVG using a fill value:

<path fill="#F7F1ED" class="skin-highlight" d="[…]"/>
<path fill="#F7BEA1" class="skin-mid" d="[…]"/>
<path fill="#BA7E5E" d="[…]" class="skin-dark" />

And changing the colours via those class attributes, I removed the fill attributes altogether and replaced them with inline styles, which include custom properties:

<path style="fill: var(--skin-mid);" d="[…]"/>
<path style="fill: var(--skin-mid);" d="[…]"/>
<path style="fill: var(--skin-dark);" d="[…]"/>

Now, before you rush to your keyboard to tell me that inline CSS is bad, when used with custom properties, it’s very, very good indeed. As for those custom properties, they’re not just plain ol’ colour values; they’re a colour system. To start with, yes, I have those normal skin colours:

--skin-highlight-base: #F7F1ED;
--skin-mid-base: #F7BEA1;
--skin-dark-base: #BA7E5E;

I used them to turn Hex into OKLCH so I could manipulate each channel separately:

--skin-highlight: oklch(from var(--skin-highlight-base)
calc(l + var(--env-l))
calc(c * var(--env-c))
calc(h + var(--env-h))
/ calc(alpha * var(--env-a)) );

Those --env-* variables define how much each colour channel shifts. These are my placeholders, which leave the original colours untouched:

.outlaw {
--env-l: 0;
--env-c: 1;
--env-h: 0;
--env-a: 1; }

Snow mode is a toggle, so I then defined a new set of variables just for when it’s active:

.snow-mode .outlaw {
--chilly-l: -0.04;
--chilly-c: 0.35;
--chilly-h: -38;
--chilly-a: 1; }

Rather than changing the base environment values, I introduced a second set specifically for cold conditions. Then swapped the environment variables for chilly ones:

--skin-highlight: oklch(
from var(--skin-highlight-base) calc(l + var(--chilly-l)) calc(c * var(--chilly-c)) calc(h + var(--chilly-h)) /
calc(alpha * var(--chilly-a))
);

Then, I registered those properties to make them animatable:

@property --chilly-l {
syntax: "";
inherits: true;
initial-value: 0; }

@property --chilly-c {
syntax: "";
inherits: true;
initial-value: 1; }

@property --chilly-h {
syntax: "";
inherits: true;
initial-value: 0; }

@property --chilly-a {
syntax: "";
inherits: true;
initial-value: 1; }

And added a transition so the characters start off looking warm and then get progressively colder:

@media (prefers-reduced-motion: no-preference) {
.outlaw {
transition:
--chilly-l 15s ease,
--chilly-c 10s ease,
--chilly-h 10s ease,
--chilly-a 10s ease; }
}
Characters getting chilly.

I love adding surprise behaviours—especially ones that reinforce the idea that these characters are reacting to their environment. So now, when someone hovers over a chilly character, they also shiver:

@media (prefers-reduced-motion: no-preference) {
.snow-mode .outlaw:hover {
--shiver-duration: 0.5s;
--shiver-x: 1.5px;
--shiver-y: 0.4px;
animation: shiver var(--shiver-duration) ease-in-out infinite;
transform-origin: center bottom; }
Graphic with snow and characters looking chillier over time.

These are subtle changes, but they add to the fun. Most importantly, by changing the way I set up colour for my animated graphics, I can have much more fun more easily in the future.

Check out the new chilly characters on my home and blog pages.

From: Rachel Andrew

2025 in review

I concluded my 2024 review post by saying that I hoped to make the move back to the North of England in 2025. The event that defined 2025 (other than my 50th birthday!) is that I managed to do just that, and I’m writing this post from a little town in Northumberland, where I’ve been […]

From: Boagworld

Giving Users A Voice Through Virtual Personas

Turn scattered user research into AI-powered personas that give anyone consolidated multi-perspective feedback from a single question.

From: Zeldman

Cold Storage

Good UX is what companies do when they have to. A company that has your stuff locked away doesn’t have to.

The post Cold Storage appeared first on Jeffrey Zeldman Presents.

From: Dave Rupert

Twenty Twenty-Five

2025 was… a year. And I made it to the end of that year. If you’re reading this, I imagine you did too and let’s celebrate that. But also not one without loss; of loved ones, of health, of relationships, of jobs, of liberties, of pursuits of happiness. Let’s mourn those.

My year was mundane by most accounts. I worked, I family’d, and with the remaining life force I focused on myself. A couple failed side projects and half-baked game ideas in there but welcomingly “unproductive” relative to what I normally subject myself to. On a handful of fronts this year has been about scaling back in what I burden myself with, in material posessions, in finances, in obligations, and elsewhere. Ideally, I can clear the plate of duties that demand my limited attention. To be so bored that I read a magazine.

Resolutions resolved

I set some slightly different goals last year. Let’s check on last year’s goals:

  • 🟢 Seize work opportunities - I’ll call this a success. Released a design system and token system. An executive-level mandate caused us to pivot the entire design language using the tokens. Success. Other big products are beginning to use our team’s work, we’re recognized for the accessibility of our product… which is great.
  • 🔴 Hunker down and be creative - In the interest of binaries, I’ll say no. I think I gravitated to work and mind-numbing recovery, not creativity. I wasn’t very productive beyond work and family life. I think given “the situation” in the homeland, that’s okay.
  • 🟠 Slow down to 1x mode - I still watch and listen way too much in 2x but at a certain point it does feel natural. Certain content gets the 1x treatment, but not enough. I did slow down though, generally speaking. Less books, less blog posts, less side projects. And that’s okay.
  • 🔴 Join a club - I made attempts to join two different writing clubs, but it didn’t work out. One met on an inconvenient night and I guess I failed the application for the other one. I joined a Discord for a Gunpla group… but never went. Closest I got to joining a club is a dad band that plays after our kids’ band practices.
  • 🟢 Understand myself - I’m progressing on my health journey to untangle the knot of anxiety, weight, and ADHD. I’ve done all the important appointments and follow-ups. I’ve done the diet. I’ve done the exercise. I’ve got new medications all lined up. Waiting for something to change.

A month-by-month breakdown

  • Jan
    • New pain meds
    • New ADHD meds
  • Feb
    • Launched internal design system
    • Shipped cross-product/platform token system
  • Mar
    • Landscaping project
    • Trip to Arizona
    • Renaissance Faire
  • Apr
    • Cheer competition in New Orleans
    • New car
    • 45th Birthday
  • May
    • New ADHD meds
  • Jun
    • Trip to Grand Canyon
  • Jul
    • Shipped design system redesign
    • Trip to San Diego
  • Aug
    • Back to school
  • Sept
    • Volunteered at Austin-Oita 夏祭り
    • New BP meds
  • Oct
    • Trip to Santa Barbara
  • Nov
    • The Beths
    • Rainer Maria and Cap’n Jazz
    • Launched Grid-Paper
  • Dec
    • New BP meds
    • New GLP-1 meds
    • Christmas in Nebraska

The school rush and kid activities fill most non-working hours. It’s a lot of work right now but we signed up for it by having children. Speaking of children, my daughter’s cheer team won a national championship, which is an incredible accomplishment and experience for her. And my son started playing guitar this year which makes the whole family happy. Both kids are 10+ now which feels like we’re entering a new era in parenting; more autonomy, different problems, deeper conversations, movies with curse words, and more attitude. It’s new territory.

An average amount of books

I had a sub-goal of reading less this year and I succeeded! That feels good.

I encountered a lot of mediocre books this year but there were some bangers in there like The Dawn of Everything, The Wrong Stuff, and The Sirens’ Call. It’s possible I’ve maxed out on books though. My appetite to seek out new books to read in the last two months has been super low. They’re all starting to blur into a large mush. I have a backlog of manga to read… perhaps next year is the year I get back into comics?

An average amount of blogging

I published 53 posts in 2025 which averages to a post-a-week, but there’s some hot streaks in there skewing the stats. It’s less than the year before which (again) I’ll count as a win. Behind the scenes there’s dozens of half-finished posts, but it takes so much effort to finish a technical post about CSS or web components who knows when those will see the light of day.

Here’s a smattering of posts that either made the rounds or I’m proud of:

I’m sure I left something out but no need to overthink it. You can peruse the archive if you want.

Living in the zone of shit

American politics drove a lot of my daily vibes this year. Day-after-day of bullshit executive orders, tariffs, lies, DOGE, fuckups, coverups, corruption, kidnappings, gulags, military occupation of democratic US cities under false pretenses, murders at sea, billionaires, institutional collapse, and everything else is exhausting. The economic anxiety weighed heavily on me; we even panic bought a car! But watching groceries get more expensive, budgets get tighter, all while the President and his cronies launch crypto grifts to launder money from billionaires and foreign governments in an open influence peddling scheme is infuriating.

I had to step back from news a bit for my own mental health, but also it’s getting repetitive. Regime does stupid/illegal thing, PERSON gets DESTROYED by THING (but never does), consequences never happen, the world is unjust. I know the strategy is to exhaust, but I hit peak outrage years ago and this feels like a long, unshakable hangover of bad decisions. My trust in any form of government erodes like sand cliffs.

Mix in a highly speculative tech hype cycle which makes up a disproportionate amount of the economy and stock market valuation… and it’s hard to shake off a sense of dread.

Focusing on my physical and mental health

All my extra spoons went to wrangling my physical and mental health. Sometimes that manifested as staring at an iPad on my recliner after long day at work, but it also involved a lot of doctors visits. This has been a year and a half long journey (since good healthcare kicked in) of prioritizing myself. And while the news isn’t all great, I’m getting a clearer picture of the brain and body I’m dealing with. There’s a long road ahead and I don’t actually know when/if it gets better, but having a pathway forward means a lot right now.

I was unconsolably grumpy for nearly two months straight. It could be burnout. It could be cheese-moving. It could be depression manifesting differently. What I learned from going through that spell was good people and great music are the secret to being happy. At least for me. And I need to make sure I’m building that into the regular rhythms of my life.

2026: No New Projects

Next year has the potential to be good. If a certain elderly statesman, for example, passed away from age-related illnesses… that might change the mood considerably. But speaking to what’s within my sphere of control, I think there’s capacity for goodness.

For 2026, I’m adopting a mantra of “No new projects.” There will be new projects of course; they fit all the interest, novelty, challenge, urgency, and passion (INCUP) requirements that motivate ADHD brains. The spirit of “No new projects” is to finish more projects than I start. In the last month or so I’ve been aggressive on closing out old lingering to-dos; home improvements, organizing, taxes, managing devices, etc. and I want to continue that work of clearing out all those nagging unfinished bits. I want to buy back precious Brain RAM so I feel less overwhelmed all the time.

“No new projects” helps me be more present and realize when I’m creating work for myself. When I buy a new device, or an instrument, or think about building my own home server array… “No new projects” puts a hurdle in the way of that decision so that I don’t DDoS myself with a backlog of small jobs pursuing an impulse.

I tend to externalize, but 2026 also feels highly dependent on what happens in tech in the next year. A change in my job? A robot taking my job? A mass layoff? A bubble bursting? An industry collapse? A retreat to a smaller web? A new and unexpected technological breakthrough? As I hinted earlier, it feels like the entirety of tech has hitched itself to a highly speculative bet and we all have to wait and see what happens. The lack of clarity and concrete vision for the future of human-centered computing and labor creates a feeling of insecurity for me. A trillion dollar hurricane. Displacement.

But we can write. And we can dream. And we can imagine a future where humans connect.

From: Stuff & Nonsense

A new gold mine graphic animation

Of all the “pioneering” graphic animations I’ve made this year, the one I disliked the most was on my contact page. That was one of the first ones I’d produced, and it was before I’d really got into the process. Anyway, it’s gone, replaced with a new gold mine graphic.

This time, I set my Magnificent 7 pioneers in the entrance to a gold mine. There’s dust in the air, gold shimmering, and oil lamps glowing and swinging.

New gold mine graphic with characters
New gold mine graphic with characters

I started with a loose pencil sketch.

Pencil sketch of my gold mine
Pencil sketch of my gold mine

I moved the artwork into Sketch to make my vectors. I kept the elements I knew I wanted to animate separate so I could add them to my graphic more easily later:

  • Background buckets swaying
  • Dust particles in the air
  • Lamps glowing and swinging
  • Pile of gold shimmering

CSS animations make the buckets sway, and lamps swing, then a little vanilla JS spawns and animates the dust particles and gold shimmers. Here’s the gold mine graphic on its own, so you can see all the components.

New gold mine graphic without characters
New gold mine graphic without characters

As I said before, I’ve been having way too much fun with my website since I implemented the new pioneer characters, so I doubt this will be the last time I add new features. In fact, I guarantee it won’t be.

From: Stuff & Nonsense

Let it snow

Winter’s definitely arrived, and there’s a chill wind blowing. We haven’t had snow in the village yet, but it’s falling on my website, courtesy of a new ‘snow mode.’

My winter blog page graphic animation

Visit my home page or blog to see that winter’s set in. On the home page, snow now covers the cacti and craggy rocks. On my blog, it’s settled on the buildings. And, unless animations have been turned off, snowflakes drift down from the sky. Brrrrr.

Adding snow to my existing animated graphics was surprisingly easy. I added three layers to my SVGs:

  1. Falling snow
  2. Settled snow
  3. Chilliness overlay
Settled snow layer
Chilliness overlay layer

That overlay lies on top of the background elements. It has a blue fill colour and a blending mode that cools whatever’s behind it. I think it’s incredible how much of a difference a colour blend can make to how the artwork feels. Then, alongside the button which starts/stops all animations, I added another which toggles the snow.

Snow mode on
Snow mode off

Toggle snow mode on and off to see the effect of these layers.


As you might’ve noticed, I’ve been having way too much fun with my website since I implemented the new pioneer characters, and in my mind, there’s nowt wrong with that.

From: Dave Rupert

Vibe Check №41

🎵 Christmas time is here. Happiness and cheer. Fun for all… that children call… their favorite time of year.

School’s out. The work laptop’s closed. Now is a good time to recount the vibes. I wanted to get out this vibecheck before embarking on the annual recap that way it’s less moodier than years prior.

Fixing my mood with music

Last vibe check I was super grumpy. Thankfully, I was able to start shaking off that cloud by fixing my mood with music. I am not kidding when I say I got to see three of my favorite bands in the span of a month.

the beths on stage

The first was my current favorite band The Beths. According to Spotify Wrapped I’m a Top 0.2% global fan. They came through Austin and played an incredible set at Emo’s. All the hits. I was enchanted for one evening.

Then a week or so later I saw my friend Richard’s band Heartswarm play at The Aristocrat. I have a lot of friends who play music and in a town like Austin I was feeling remorse for not enjoying that more at every chance I get.

Then, a couple nights later, I saw one of my all time favorite emo bands when Rainer Maria open for my other absolute most favorite (midwest) emo band Cap’n Jazz. The show was so great and the audience was an even 50/50 split between dads over 45 and queer kids under 21. What a cross-section of society! And because my friend Richard is friends with Mike Kinsella, I got to hang out with the him a bit. Cool dude and an honor to finally meet in person.

A couple weeks after that, I took my son and his friend to their first hardcore punk show featuring Dark Thoughts opening for Béton Armé. First time hearing all these bands but Dark Thoughts was awesome. Béton Armé had incredible energy. But the real surprise was Houston hardcore punk/ska band Liberty & Justice. Being from Houston I wondered if we knew similar people in the punk scene. I didn’t summon up enough courage to ask though because it’s been decades since I lived there, but after texting some friends back home I learned the lead singer is good friends with my old neighbor and grew up in the next town over. Small world.

Coding vibes

Despite a heavy workload at work and home projects piling up, I summoned some energy to work on some coding projects at night.

A tennis app for my wife

My wife likes to obsess over tennis scores and ratings; not limited to hers and the team she captains, but for anyone she knows in the United States. She was having trouble accessing the site she uses (tennisrecord.com) and I thought we were potentially IP-banned because she uses it so much. the app is kind of a terrible user experience… so why not try to make a good one?

One constraint I added to the project was that I had to vibe code it. Partly because that’s the approximate amount of spoons I had for this project, but also to practice wrangling these machines a bit better.

Vibe coding was –per usual– a rollercoaster. I told it what I wanted (a multi-page Vite app that uses Netlify functions to connect to the USTA API) and it seemed to like that. The agent generated a PRD.md. I read the PRD. It looked good. I made some edits. I ran the plan…

It did not follow the plan. It went off and scaffolded out the entire application and most of the views. While super impressive in such a short amount of time, generally speaking, that’s not what you want? With software I find you want to step down a path iteratively and make sure you’re not repeating the same mistakes. It would benefit LLMs to maintain a tight context window instead of doing a full blow-out on the first prompt… but that’s not what LLMs do, is it? They drive down a road until it ends and tend to go overboard; they build out features you didn’t even ask for. Also worth nothing they charge per token used.

For example it didn’t understand how to write and use web components. It wrote thousands of lines of JavaScript in an imperative way, which is the opposite of what I asked for and the antithesis of the web components ethos which tends to be highly declarative and template driven. After a half-dozen repeated failures I tried the prompt “Use Lit” and seemed to understand that (sometimes). I need to re-read the chatlogs because I was able to turn the corner on quality but it required a lot of hand-holding and babysitting the machine. It excelled at short tasks like “Rename X to Y” but to be honest “Find & Replace in Project” isn’t a hard task for me. I think where it can be good is tedious work like changing API structures (renaming functions, etc) and then extrapolating that change out to the rest of the project.

Ultimately the project died in an unceremonious way when the USTA denied my application for an API key. Boo. I will never know if all those API endpoints that weren’t in the documentation actually worked or if Copilot just invented them. Also impacting the project was the fact that Quiet UI disappeared from the internet, which is a special kind of setback for doc-dependent LLMs. Oh well. I’d rank it a mixed success. I got through my personal quality-via-the-LLM barrier, but trying to corral the stateless machine wasn’t the most enjoyable experience and I didn’t ship the app.

An app for analog drawing

I loved graph paper as a kid. I used to buy giant pads of it and make scale architectural models of my house. The algorithm surfaced some cool isomorphic dungeon drawing videos for me but the process of sourcing some graph paper let me down. I wanted to print out a couple sheets of graph paper but I kept getting skeezed out by my options on image search. Low-res JPEGs with shitty logos splattered all over. No sense of how big it’d actually be when I printed it out.

screenshot of my grid paper app with some configurable settings in a header and a grid covering the entire background

So I spent an evening making my own little Grid Paper app. I’m pleased with the results. It supports grids, dot-grids, isomorphic grids, perspective grids, and dual-hex grids. I have a branch locally that adds normal hex grids and more fidelity but it’s a complete refactor so it’ll take some time to finish out.

All said, I’m happy with the time vs effort results on this project. A couple nights worth of work.

Retrogaming

I got a neat little Anbernic retro-handheld emulator for Christmas last year but to be honest I hadn’t played it much. The system was lacking a lot of the first-party blockbuster games I loved. Y’know what I’m talking about… the sbarro brothers, the sanics, the pokey-mens, the mega-dudes; those sorts of games.

I mentioned this to a friend and he helped me… ahem… backup some games I had. And that was enough of a spark to inspire me to swap out the default operating system to a custom one called Knulli and I made it feel neat-o by installing the Techdweeb theme.

I’m loving it so much more. I’ve been playing through a game where you capture these little critters and use them in ethically-questionable battles against other children and adults. So that’s fun and been a great way to relax that isn’t doomscrolling or YouTube rabbit holes.

Statistical Breakdown

📖 Reading

SapiensAt HomeSlow DownControl FreakIt's Only DrowningA Libertarian Walks Into a Bear
  • Sapiens ★★★½ - This book very much fits into my historical graphic novel wheelhouse. It suffers some of the common problems with the real-book-to-comic genre (long speeches, hammy conversation setups, etc) and I struggled at the beginning, but towards the middle I latched on and enjoyed it enough to get the second book from the Library… which I didn’t read. One eyebrow-raising bit is that it somewhat opens the door to “These people have different DNA”-type phrenology or supremacy narratives. Woof.

  • At Home DNF - I did not finish this book, but I did enjoy it. I probably prefer a more linear history lesson on a single topic, but Bill Bryson does something unique and ties together a tapestry of historical anecdotes based on common objects found in his home. I may pick this up again in the future when things slow down and my mind can wander more.

  • Slow Down ★★★★½ - Comrades! Degrowth is a topic I’m interested in. How do we break away from the “always grow” cycle of Capitalism and it’s climate death march. Kōhei Saitō suggests communism, leaning on the contemporary writings of Marx that didn’t make it in Das Kapital that were focused around ecological sustainability as opposed to revolution.

  • Control Freak ★★ - I’m always up for some video game history and CliffyB’s has played a role in some of gaming’s biggest moments. The book starts with a classic nerd coming-of-age at the dawn of the internet story that is familiar, his father’s passing, but before digging into his time at Epic games, the story takes a sudden turn recounting his own sexual abuse. Then it hops back into video games like nothing happened. The book is soaked in CliffyB’s non-malignant but very apparent narcissism. Name drops. Affairs. Divorce. Matching Lambos. Markers of success CliffyB seems to wear like self-deprecating badges of honor. I don’t mean to take from CliffyB’s successes (Unreal Tournament, Gears of War, Fortnite, etc) and those portions of the book are interesting in their own right, but overall… it felt like a very personal story rather than a general nerds-to-riches type story.

  • It’s Only Drowning ★★★½ - Author David Litt decides to take up surfing late-in-life. To achieve this goal he must befriend his twenty-something brother-in-law. It’s a story of self-realization and challenging yourself to achieve a difficult goal as well as bridging an awkward familial/generational/political gap. I think it also embodies the male loneliness epidemic; a desire to have relationships with people who aren’t our spouse, to be invited, and to belong.

  • A Libertarian Walks Into a Bear [In progress]

📝 Blogging

I had a secret theme –that I don’t if anyone picked up on– but I was trying to share things I like. A couple got serious, but most of them were simple posts about a game or YouTube series I like. I think this also helped put me in a better moo.

These posts are easier technical posts. They don’t get as many hits… but they also don’t get stuck in months-long quality assurance and demo-building limbo.

📺 Media Diet

Movies

Podcasts

  • Systems of Harm (S2) - I’m late to it but been enjoying season two of Systems of Harm.
  • Nice Try (S1) - A podcast about failed utopias.
  • Beyond that the usual If Books Could Kill & Maintenance Phase routine.

YouTubes

  • Been really into Rust vods.

🎙 Recording

Chris and I wrapped up our 14th season of Shop Talk. 695 episodes of showing up every week. Can’t believe we’ll be at 700 soon.

⌨️ Open source

  • 🎉 Fluent Web Components v3 is in Release Candidate - It’s been a lot of work (138 beta versions) to get here. But we’re happy with the progress as well as the capabilities.

👾 Video games

  • Retro gaming: As said above, I got into retro-gaming. I’m happy to mine this vein for awhile.
  • Puzzle games (see blog).

From: Meyerweb

Targeting by Reference in the Shadow DOM

A new way to allow elements inside a Shadow DOM to be targeted for accessibility or other reasons.

From: Stuff & Nonsense

Smashing Animations Part 7: Recreating Toon Text With CSS And SVG

Yours truly over at the Smashing Magazine: “In this article, pioneering author and web designer Andy Clarke shows his techniques for creating Toon Text titles using modern CSS and SVG.”

Read Smashing Animations Part 7: Recreating Toon Text With CSS And SVG

From: Stuff & Nonsense

Designing banners for the Academy of Scoring Arts

While the smart people finish the Academy of Scoring Arts website’s CMS development, I’ve been rummaging through my design files and rediscovered several concepts that didn’t make it into the final design.

Old Academy of Scoring Arts website banner

Like 20,110,000* others, the Academy of Scoring Arts website was topped by a full-width banner with a faded background image, intro text, and a big ol’ button. The image was somewhat relevant; the text did, at least, explain what the website is about; and the button was, well, big. But by now, most people have trained their brains to scroll straight past banners like this to get to the real content.

What I wanted instead was something that reflected the messages I cared about communicating—community, connections between musicians, and musicality.

I’m a big admirer of Erik Nitsche’s work. He’s best known for the annual reports and posters he designed for General Dynamics, but it’s his album covers—those mixes of colour, shape, and distinctive typography—that I return to most often.

Album covers by Erik Nitsche

Dozens of Nitsche’s covers went into my research folder, but the piano-key graphic from The Amazing Bud Powell, Vol. 5 stood out. Early in the design process, with only placeholder graphics needed for first concepts, there was very little difference between my version and Nitsche’s original.

Erik Nitsche inspired placeholder design

At this stage, graphics like these are valuable talking points as I get to know a client and their likes and dislikes. The feedback was clear: the Academy is less jazz-oriented and more orchestral. More importantly, the graphic didn’t convey a sense of community or connection. That sent me in a different direction.

While visiting an abstract art exhibition in the summer, I saw work by Juan Gris, Wassily Kandinsky, Joan Miró, and Pablo Picasso. Gris’s cubist paintings resonate with me more than Picasso’s, so experimentation began with a graphic inspired by his 1913 painting Still Life With a Guitar.

Juan Gris inspired design

These sketches used flat colour and no texture—enough to test the idea with the team without over-committing. The increased energy landed well, but the concept itself didn’t. It still felt too literal. The idea was worth pushing further, though. To make it more abstract and energetic, I looked to Kandinsky. His paintings are full of movement, and that sense of motion felt right for a community of composers.

Wassily Kandinsky inspired design

Drawing abstract lines and shapes, with added shading and transparency, created more depth. The result was closer to what I had in mind. From there, I also explored a looser, more free-flowing direction inspired by Joan Miró.

Joan Miro inspired design
Joan Miro inspired design

These were by far my favourite artist-inspired designs. The Academy team weren’t convinced and asked me to explore a different direction, including images of their members to emphasise the community aspects of their work. I still wanted to communicate connections, so I added lines connecting the people and made parts of them pop out of the shapes to loosen the composition and give it more energy.

People in circles (final)
People in irregular shapes (final)

This was the direction the Academy team felt best reflected their brand and what they aimed to communicate to their members.


Looking back through my folders, I’m reminded how many ideas never make it past a first iteration—and that’s never a failure. Design decisions are often subjective, so every attempt becomes a conversation. Those conversations matter, because they’re how I move past my own preferences and get closer to what a client is trying to express. In the end, it’s those conversations that shape the final result far more than any single idea.


* May not be entirely accurate, but what the hell.

From: Stuff & Nonsense

Updates to my Toon Text styles gallery and generator

I mentioned last week that as well as expanding my Toon Text styles gallery, I’d added a Toon Text generator to help me (and you) create text in the style of those classic cartoon title cards. Now, I’ve launched a major update to both.

Toon Text demonstrates how to style text to resemble cartoon title cards using CSS properties, including background-clip, filters, text-shadow, text-stroke, and more. I’m building the collection as I love experimenting with combining those properties.

The Toon Text generator lets you use those properties to create Toon Text from presets or from scratch and see the results instantly.

Toon Text
Go to Toon Text

Updates to Toon Text

As my collection grows, I wanted to add filtering to the page based on how I tag each example. There’s now navigation which filters the examples by tag, for example filter. JavaScript automatically populates this navigation from my tags and displays how many examples are tagged.

Previously, I’d added buttons which navigated to the Toon Text generator. Now, JavaScript reads the computed styles of each example and passes them to the generator to use as starting points for creating new Toon Text. It even passes the title text.

Toon Text generator
Go to Toon Text generator

Updates to the Toon Text generator

As I mentioned, navigating from the Toon Text gallery to the generator now allows you to use its styles as starting points. I’ve also added new presets and a sticky contenteditable preview box.

I’ll no doubt refine both of these over time, but for now, here’s my updated Toon Text styles gallery and Toon Text generator. You might also like my more accessible text splitting tool, Splinter.js. which I also introduced today.

From: Stuff & Nonsense

Splinter.js — I made a more accessible text splitting tool

Sometimes I don’t want to style a whole word or heading. I want to style individual letters—to nudge a character into place, give one glyph extra weight, or animate a few letters independently. Sadly, some splitting solutions don’t deliver an always accessible result. With the help of a developer pal, I've written my own text splitter, Splinter.js.

In plain HTML and CSS, there’s only one reliable way to do that: wrap each character in its own span element. I could do that manually, but that would be fragile, hard to maintain, and would quickly fall apart when copy changes. Instead, when I need per-letter control, I use a text-splitting library like splt.js (although other solutions are available). This takes a text node and automatically wraps words or characters, giving me extra hooks to animate and style without messing up my markup.

The problem

It’s an approach that keeps HTML readable and semantic, while giving me the fine-grained control I need to recreate the uneven, characterful typography you see in classic cartoon title cards. However, this approach comes with accessibility caveats, as most screen readers read text nodes in order. So this:

<h2>Hum Sweet Hum</h2>

Reads as you’d expect:

“Hum Sweet Hum”

But this:

<h2>
<span>H</span>
<span>u</span>
<span>m</span>
[…]
</h2>

That can be interpreted differently depending on the browser and screen reader. Some will concatenate the letters and read the words correctly. Others may pause between letters, which in a worst-case scenario might sound like:

“H…” “U…” “M…”

Splinter.js
Go to Splinter.js

My solution, Splinter.js

To activate my Toon Text splitter, add a data-split="toon" attribute to the element you want to split:

<h2 data-split="toon">Hum Sweet Hum</h2>

First, Splinter.js separates each word into individual letters and wraps them in a span element with a toon-char class and aria-hidden attributes applied:

<span class="toon-char" aria-hidden="true">H</span>
<span class="toon-char" aria-hidden="true">u</span>
<span class="toon-char" aria-hidden="true">m</span>

The script then takes the initial content of the splintered element and adds it as an aria-label attribute to help maintain accessibility:

<h2 data-split="toon" aria-label="Hum Sweet Hum">
<span class="toon-char" aria-hidden="true">H</span>
<span class="toon-char" aria-hidden="true">u</span>
<span class="toon-char" aria-hidden="true">m</span>
</h2>

Lines of text separated by <br> elements are wrapped in a span element with a toon-line class attribute applied:

<h2 data-split="toon" aria-label="Hum Sweet Hum">
<span class="toon-line">
<span class="toon-char" aria-hidden="true">H</span>
<span class="toon-char" aria-hidden="true">u</span>
<span class="toon-char" aria-hidden="true">m</span>
</span>
[…]
</h2>

With those class attributes applied, I can then style individual characters as I choose.


My goal is make a text splitter which is more accessible than others I’ve found. If you’re an accessibility expert, I’d love to hear your thoughts and suggestions for how to improve Splinter.js.

I also wanted to make Splinter.js small, really small. The minified script file weighs in at only 1.3Kb. If you’re a Javascript expert, I’d love to see your improvements. Splinter.js is available on GitHub.

So here’s Splinter.js, a lightweight and (hopefully) more accessible text splitting tool.

From: Zeldman

Accessibility is a human right, cruelty a human wrong.

Once more for the folks in the back. Calibri is easier than Times New Roman for folks with certain visual disabilities to read. That’s why the Biden Administration chose Calibri for their digital communications: to include more people and make life just a wee bit easier for the disabled. And who in their right mind could […]

The post Accessibility is a human right, cruelty a human wrong. appeared first on Jeffrey Zeldman Presents.

From: Stuff & Nonsense

I made a tool to generate Toon Text

Partway through writing an upcoming article for Smashing Magazine, I decided it would be helpful to have a tool to generate text styled like that in my beloved cartoon titles. So I made one.

My Toon Text tool enables you to add colours, strokes, and multiple text shadows. You can change the paint order, apply letter-spacing, and preview your text using a few sample fonts. Then, you can copy the CSS to your clipboard to use in a project.

I’ll no doubt refine it over time, but for now, here’s my Toon Text generator. You might also like my growing collection of Toon Text examples, inspired by classic Hanna-Barbera title cards.

From: Stuff & Nonsense

Unfinished Business #138: Would you like a glass of champagne?

In this episode of Unfinished Business, Andy and Rich talk about retainers and maintenance contracts, and Andy asks Richard’s advice on how to sell them to new clients. As he’s prone to do, Andy also talks about Wrexham football club.


Sponsored by Contract Killer

Most web design contract templates are stuffed with boilerplate content your clients will never read. Contract Killer covers everything—payments, revisions, scope, and timelines—in plain, human language. Trusted by designers for over a decade. Peer-reviewed, fully customisable, and built to keep projects on track, and your invoices paid.

Buy Contract Killer


Also available on YouTube

For anyone who can’t get enough Unfinished Business, we publish the show in video format on YouTube.

Watch “Unfinished Business” on YouTube

Sponsor Unfinished Business

The best way to promote your product or service to the Unfinished Business audience of creative professionals, designers, and developers. Sponsors get one exclusive two-minute ad per episode, live read by me or Rich, which feels personal and relatable. We can use your script or ad-lib, and you’ll also receive a link on each episode’s post, as well as a thank-you on our Bluesky and Mastodon accounts. Interested? We’d love to hear from you.

Support Unfinished Business on Patreon

We also have three monthly membership plans so you can support Unfinished Business on Patreon. $5, $10, and $20 if you’re feeling especially generous. All money goes towards podcast editing and hosting. Support Unfinished Business on Patreon.

From: Stuff & Nonsense

A new workshop space for my side projects

You know what it’s like. You decide to make a fun little side project. No need to integrate it into your main codebase. It doesn’t have to have compatible CSS or HTML, so no worries. Then you make another one. Same deal. Then another. Oh. All of a sudden, you have several projects, and there are annoying differences between them.

That was me. I made my collection of classic cartoon toon titles cards. Then I added my new toon text collection and created a tool for making cartoon-style text. I also had the hosted examples from my magazine articles, and when I looked at them together, the differences were too much for me to ignore.

Space for creative code experiments and passion projects

So for the past few evenings, I’ve been bringing all these little projects together into what I’m calling my “workshop”. It’s essentially a landing page linking to the various projects.

I also created unified headers and footers, as well as a stripped-down stylesheet. The overall CSS architecture is a little more complicated than I’d like, but it works for now:

  1. Top level stylesheet for all workshop components (workshop.css)
  2. Second-level stylesheet for specific projects (styles.css)
  3. Embedded CSS on specific pages, for unique elements

Hopefully, this will make new projects and updates to existing ones easier. Plus, I feel happier that everything feels more integrated into my overall website design.


Go to my workshop.

From: Stuff & Nonsense

Getting creative with the Measure

Yours truly over at CSS Tricks: “I spend an unhealthy amount of time on the typography in my designs, and if you’ve read any traditional typography books, you might remember “the measure.” If not, it’s simply the length of a line of text. But measure means more than that, and once you understand what it represents, it can change how you think about layout entirely.”

Read Getting creative with the Measure.