Saying “No” In an Age of Abundance - Jim Nielsen’s Blog
In an age of abundance, restraint becomes the only scarce thing left, which means saying “no” is more valuable than ever.
I’m as proud of the things I haven’t generated as the things I have.
In an age of abundance, restraint becomes the only scarce thing left, which means saying “no” is more valuable than ever.
I’m as proud of the things I haven’t generated as the things I have.
Jemima runs through just some of the exciting new additions to CSS:
Replacing 150+ lines of JavaScript with just a few CSS features is genuinely wild. We’re able to achieve the same amount of complexity that we’ve always had, but now it’s a lot less work to do so.
And Jemima will be opening the show at Web Day Out in Brighton on the 12th of March if you want to hear more of this!
We’ve arrived at an industrialised process, one that’s like an assembly line for applications. Frameworks like React have become the machinery of that assembly line. They enable us to build efficiently, to build at scale, to build predictably. But they also constrain what we build.
But what aren’t we building? What new kinds of experiences, what new kinds of applications, what new kinds of interaction could we create if we were deeply exploring and engaging with the capabilities of the platform? I don’t know, because we’re not building them. We’re building what the frameworks enable us to build, what the assembly line can produce efficiently.
Collectively, as an industry and as a profession, consciously or not, we’ve chosen this maxima that we’re stuck on. We can build what React or Vue or Next or name your framework/library enables us to do.
I share John’s despair at this situation, but I don’t share his belief that large language models will save us.
If you’re building software, it’s generally a good idea to avoid the Not-Invented-Here syndrome. This is when you insist on writing absolutely everything from scratch even if it would make more sense to use a third-party provider.
Need your app to take payments? Don’t try to become your own payment provider—use an existing provider instead.
Need your app to send email? Don’t try to code all that up yourself—just use an existing service.
This same thinking seems to apply to JavaScript libraries too. If you don’t use a library or framework, you’ll just end up writing your own library or framework instead, right?
Except that’s not the way that JavaScript frameworks work. At least not any more.
There was a time when JavaScript libraries really did abstract away browser differences that you probably didn’t want to deal with yourself. In the early days of jQuery—before querySelector existed—trying to work with the DOM could be a real pain. Libraries like jQuery helped avoid that pain.
Maybe it was even true in the early days of Angular and React. If you were trying to handle navigations yourself, it probably made sense to use a framework.
But that’s not the case any more, and hasn’t been for quite a while.
These days, client-side JavaScript frameworks don’t abstract away the underlying platform, they instead try to be an alternative. In fact, if you attempt to use web platform features, your JavaScript framework will often get in the way. You have to wait until your framework of choice supports a feature like view transitions before you get to use it.
This is nuts. Developers are choosing to use tools that actively get in the way of the web platform.
I think that most developers have the mental model of JavaScript frameworks completely backwards. They believe that the framework saves them time and effort (just like a payment provider or an email service). Instead these frameworks are simply limiting the possibility space of what you can do in web browsers today.
When you use a JavaScript framework, that isn’t the end of your work, it’s just the beginning. You still have to write your own code that makes use of that framework. Except now your code is restricted to only what the framework can do.
And yet most developers still believe that using a JavaScript framework somehow enables them to do more.
Jim Nielsen has a great framing on this. JavaScript libraries aren’t like payment providers or email services. Rather, it’s the features built into web browsers today that are like these third-party providers. When you use these features, you’re benefiting from all the work that the browser makers have put into making them as efficient as possible:
Browser makers have teams of people who, day-in and day-out, are spending lots of time developing and optimizing new their offerings.
So if you leverage what they offer you, that gives you an advantage because you don’t have to build it yourself.
Want to do nifty page transitions? Don’t use a library. Use view transitions.
Want to animate parts of the page as the user scrolls? Don’t use a library. Use scroll-driven animations.
Want to make something happen when the user clicks? Don’t use a library. For the love of all that is holy, just use a button.
If you agree that using a button makes more sense than using a div, then I encourage you to apply the same thinking to everything else your app needs to do.
Take advantage of all the wonderful things you can do in web browsers today. If instead you decide to use a JavaScript framework, you’re basically inventing from scratch.
Except now all of your users pay the price because they’re the ones who have to download the JavaScript framework when they use your app.
This is a nifty initiative:
This site lets you rank the proposals you care about, giving us data we can use when reviewing which proposals should be taken on for 2026.
For the record, here’s my top ten:
- Cross-document view transitions
- Speculation Rules API
img sizes="auto" loading="lazy"- Customizable/stylable
select- Invoker commands
- Interoperable rendering of HTML
fieldset/legend- Web Share API
- CSS scroll-driven animations
- CSS
accent-colorproperty- CSS
hanging-punctuationproperty
Grrr…
Chrome, Edge and Firefox updates usually reach 95% of users within three months. But Safari updates are tied to a new release of the underlying operating system, so they take around 19 months to reach the same usage, and some updates may even need a new device.
This is so shameful. And glad as I am to see new features landing in Safari, as long as they hobble updates like this it’s all just pissing in the wind.
An excellent appraisal of the importance of the rule of least power.
A handy one-pager for front-end web developers:
Here are ways to keep track of what you can use, of what’s new in web browsers, and ways you can influence the development of the platform by making your voice heard.
This is a very smart way to handle feedback about a product.
Remember when every company rushed to make an app? Airlines, restaurants, even your local coffee shop. Back then, it made some sense. Browsers weren’t as powerful, and apps had unique features like notifications and offline access. But fast-forward to today, and browsers can do all that. Yet businesses still push native apps as if it’s 2010, and we’re left downloading apps for things that should just work on the web.
This is all factually correct, but alas as Cory Doctorow points out, you can’t install an ad-blocker in a native app. To you and me, that’s a bug. To short-sighted businesses, it’s a feature.
(When I say “ad-blocker”, I mean “tracking-blocker”.)
Straightforward smart sensible advice that you can apply to any feature on a website.
Logical properties, container queries, :has, :is, :where, min(), max(), clamp(), nesting, cascade layers, subgrid, and more.
This seems to be the attitude of many of my fellow nerds—designers and developers—when presented with tools based on large language models that produce dubious outputs based on the unethical harvesting of other people’s work and requiring staggering amounts of energy to run:
This is the future! I need to start using these tools now, even if they’re flawed, because otherwise I’ll be left behind. They’ll only get better. It’s inevitable.
Whereas this seems to be the attitude of those same designers and developers when faced with stable browser features that can be safely used today without frameworks or libraries:
I’m sceptical.
Develop a simple, focused app that does what it says on the tin — not one where the tin talks back at you.
It’s a shame that the newest Safari release is overshadowed by Apple’s shenanigans and subsequent U-turn because there’s some great stuff in there.
I really like what they’re doing with web apps added to the dock:
Safari adds support for the
shortcutsmanifest member on macOS Sonoma. This gives you a mechanism in the manifest file for defining custom menu commands that will appear in the File menu and the Dock context menu.
Lots of new features landing in Safari, and it’s worth paying attention to the new icon requirements now that websites can be added to the dock:
To provide the best user experience on macOS, supply at least one opaque, full-bleed
maskablesquare icon in the web app manifest, either as SVG (any size) or high resolution bitmap (1024×1024).
🎶 What a good year for the style sheets! 🎶
These updated definitions makes sense to me:
- Newly available. The feature is marked as interoperable from the day the last core browser implements it. It marks the moment when developers can start getting excited and learning about a feature.
- Widely available. The feature is marked as having wider support thirty months or 2.5 years later. It marks the moment when it’s safe to start using a feature without explicit cross-browser compatibility knowledge.
Pirijan talks us through the design principles underpinning Kinopio, a tool I like very much:
- Embrace Smallness by Embracing Code as a Living Design System
- Building for Fidget-Ability, hmmm
- Embrace Plain Text
- A Single Interface for Mobile and Desktop
- Refine by Pruning
This is the kind of press release I like.