Even without specialized syntax, you can do a lot of what the usual frontend framework does—with similar conciseness—just by using
Even without specialized syntax, you can do a lot of what the usual frontend framework does—with similar conciseness—just by using
Every day, a new marketing email, Medium post, or VC who will leave Twitter when they’re cold in a body bag tells us that machine learning (ML, which they call AI because it sounds more expensive) is going to change the way we work. Doesn’t really matter what your job is. ML is going to read, write, code, and paint for us.
Naturally, the excitement around ML has found its way into the design systems community. There’s an apparent natural synergy between ML and design systems. Design systems practitioners are tantalized by the promise of even greater efficiency and scale. We wish a machine would write our docs for us.
We are all, every single one of us, huge fucking nerds.
Here’s an aggregator of components from multiple design systems.
Call me Cassandra:
The way that industry incorporates design systems is basically a misappropriation, or abuse at worst. It is not just me who is seeing the problem with ongoing industrialization in design. Even Brad Frost, the inventor of atomic design, is expressing similar concerns. In the words of Jeremy Keith:
[…] Design systems take their place in a long history of dehumanising approaches to manufacturing like Taylorism. The priorities of “scientific management” are the same as those of design systems—increasing efficiency and enforcing consistency.
So no. It is not just you. We all feel it. This quote is from 2020, by the way. What was then a prediction has since become a reality.
This grim assessment is well worth a read. It rings very true.
What could have become Design Systemics, in which we applied systems theory, cybernetics, and constructivism to the process and practice of design, is now instead being reduced to component libraries. As a designer, I find this utter nonsense. Everyone who has even just witnessed a design process in action knows that the deliverable is merely a documenting artifact of the process and does not constitute it at all. But for companies, the “output” is all that matters, because it can be measured; it appeals to the industrialized process because it scales. Once a component is designed, it can be reused, configured, and composed to produce “free” iterations without having to consult a designer. The cost was reduced while the output was maximized. Goal achieved!
A library of UX components is one common part of a design system, but the system itself is something bigger. A good system is also a shared set of strategies for solving visual and interactive communication challenges, a playbook rather than a script.
I like this way of putting it:
The problem is that treating a design system as a pantry full of widgets is, in and of itself, a failure of both craft and imagination. Think of it like a language: if a writer’s only engagement with it is grabbing words from the dictionary and heaping them together until “message” is achieved, things are going to suck. Language is more than a bag of words.
I’ve seen the pendulum swing back and forth many times over my years building on the web. I too feel like there’s something in the air right now, and people are finally acknowledging that most single page apps are crap.
So now the world of web components has egg on its face because the zeitgeist at the time of its design didn’t have such a strong focus on SSR/HTML-first/ progressive enhancement. Had web components been designed in the current zeitgeist, things would almost certainly be different.
I get it. React feels good and it’s sticky. But all frameworks eventually fizzle out.
Thanks to Web Components, large companies are realizing you don’t need to rebuild buttons and other UI primitives every few years. Teams don’t need to argue about frameworks anymore. You can have your cake and eat it too!
I think this may be the best long-term argument for web components:
Any org that goes all in on a single framework will eventually find themselves swimming upstream to hire talent to maintain legacy code and avoid framework rot. But you can reduce this burden (and the associated costs) by using Web Components in your design system.
Dave rounds up some of the acronymtastic ways of scoping your CSS now that we’ve got a whole new toolkit at our disposal.
If your goal is to reduce specificity, new native CSS tools make reducing specificity a lot easier. You can author your CSS with near-zero specificity and even control the order in which your rules cascade.
A stylesheet for when you’re nostalgic for the old Mac OS.
In each case you could use native HTML elements:
Or you could use
In the case of a dropdown, it’s less clear-cut. Personally, I’d use a
select element. While it’s currently impossible to style the open state of a
select element, you can style the closed state with relative ease. That’s good enough for me.
Personally, I think chasing pixel-perfect consistency across platforms isn’t even desirable, but I get it. I too would like to have more control over styling
select elements. That’s one of the reasons why the work being done by the Open UI group is so important.
But there’s one more component: a button.
Again, you could use the native
button element, or you could use a
div or a
Now, in this case, I must admit that I just don’t get it. Why wouldn’t you just use the native
button element? It has no styling issues and the browser gives you all the interactivity and accessibility out of the box.
I’ve been trying to understand the mindset of a developer who wouldn’t use a native
button element. The easy answer would be that they’re just bad people, and dismiss them. But that would probably be lazy and inaccurate. Nobody sets out to make a website with poor performance or poor accessibility. And yet, by choosing not to use the native HTML element, that’s what’s likely to happen.
I think I might have finally figured out what might be going on in the mind of such a developer. I think the issue is one of control.
When I hear that there’s a native HTML element—like
select—that comes with built-in behaviours around interaction and accessibility, I think “Great! That’s less work for me. I can just let the browser deal with it.” In other words, I relinquish control to the browser (though not entirely—I still want the styling to be under my control as much as possible).
But I now understand that someone else might hear that there’s a native HTML element—like
select—that comes with built-in behaviours around interaction and accessibility, and think “Uh-oh! What if there unexpected side-effects of these built-in behaviours that might bite me on the ass?” In other words, they don’t trust the browsers enough to relinquish control.
I get it. I don’t agree. But I get it.
But I don’t think it’s a great mindset for the web. The web is filled with uncertainties—browsers, devices, networks. You can’t possibly account for all of the possible variations. On the web, you have to relinquish some control.
Still, I’m glad that I now have a bit more insight into why someone would choose to attempt to retain control by using
This is a terrific resource! A pattern library of interactive components: tabs, switches, dialogs, carousels …all the usual suspects.
Each component has an example implementation along with advice and a checklist for ensuring its accessible.
It’s so great to have these all gathered together in one place!
This is a great case study of switching from a framework mindset to native browser technologies.
Though this is quite specific to Jack’s own situation, I do feel like there’s something in the air here. The native browser features are now powerful and stable enough to make the framework approach feel outdated.
And if you do want to use third-party dependencies, Jack makes a great case for choosing smaller single-responsibility helpers rather than monolithic frameworks.
Replacing lit-html would be an undertaking but much less so than replacing React: it’s used in our codebase purely for having our components (re)-render HTML. Replacing lit-html would still mean that we can keep our business logic, ultimately maintaining the value they provide to end-users. Lit-Html is one small Lego brick in our system, React (or Angular, or similar) is the entire box.
We noticed a trend: students who pick a UI framework like Bootstrap or Material UI get off the ground quickly and make rapid progress in the first few days. But as time goes on, they get bogged down. The daylight grows between what they need, and what the component library provides. And they wind up spending so much time trying to bend the components into the right shape.
I remember one student spent a whole afternoon trying to modify the masthead from a CSS framework to support their navigation. In the end, they decided to scrap the third-party component, and they built an alternative themselves in 10 minutes.
This tracks with my experience. These kinds of frameworks don’t save time; they defer it.
The one situation where that works well, as Josh also points out, is prototyping.
If the goal is to quickly get something up and running, and you don’t need the UI to be 100% professional, I do think it can be a bit of a time-saver to quickly drop in a bunch of third-party components.
I’ve noticed a strange mindset amongst front-end/full-stack developers. At least it seems strange to me. But maybe I’m the one with the strange mindset and everyone else knows something I don’t.
It’s to do with trust and suspicion.
I’ve made no secret of the fact that I’m suspicious of third-party code and dependencies in general. Every dependency you add to a project is one more potential single point of failure. You have to trust that the strangers who wrote that code knew what they were doing. I’m still somewhat flabbergasted that developers regularly add dependencies—via npm or yarn or whatever—that then pull in even more dependencies, all while assuming good faith and competence on the part of every person involved.
It’s a touching expression of faith in your fellow humans, but I’m not keen on the idea of faith-based development.
And yet, the mindset I’ve noticed is that many developers are suspicious of browser features but trusting of third-party libraries.
When I write and talk about using service workers, I often come across scepticism from developers about writing the service worker code. “Is there a library I can use?” they ask. “Well, yes” I reply, “but then you’ve got to understand the library, and the time it takes you to do that could be spent understanding the native code.” So even though a library might not offer any new functionality—just a different idion—many developers are more likely to trust the third-party library than they are to trust the underlying code that the third-party library is abstracting!
Developers are more likely to trust, say, Bootstrap than they are to trust CSS grid or custom properties. Developers are more likely to trust React than they are to trust web components.
On the one hand, I get it. Bootstrap and React are very popular. That popularity speaks volumes. If lots of people use a technology, it must be a safe bet, right?
But if we’re talking about popularity, every single browser today ships with support for features like grid, custom properties, service workers and web components. No third-party framework can even come close to that install base.
And the fact that these technologies have shipped in stable browsers means they’re vetted. They’ve been through a rigourous testing phase. They’ve effectively got a seal of approval from each individual browser maker. To me, that seems like a much bigger signal of trustworthiness than the popularity of a third-party library or framework.
So I’m kind of confused by this prevalent mindset of trusting third-party code more than built-in browser features.
Is it because of the job market? When recruiters are looking for developers, their laundry list is usually third-party technologies: React, Vue, Bootstrap, etc. It’s rare to find a job ad that lists native browser technologies: flexbox, grid, service workers, web components.
I would love it if someone could explain why they avoid native browser features but use third-party code.
Until then, I shall remain perplexed.
This is exactly the pattern of usage I’ve been advocating for with web components—instead of creating a custom element from scratch, wrap an existing HTML element and use the custom element to turbo-charge it, like Zach is doing:
By enhancing native HTML instead of replacing it, we can provide a solid baseline experience, and add progressive enhancement as the cherry on top.
I completely agree with Dan that when it comes to design systems, completeness is an over-rated—and even counter-productive—goal:
Some organizations seem to hold up the ideal that, once a design system exists, everything in an interface can and should be built with it. Not only is that an unrealistic goal for most enterprises, but it can often be a toxic mindset that anything less than 100% coverage is misuse of a design system at best or utter failure at worst.
Just like jQuery dominated the front end yesterday, React dominates it today. There will be something new that dominates it tomorrow. Your design system team will continue doing the same work and incurring more and more costs to keep up with framework churn. And let’s not forget the cost of updating tomorrow’s legacy apps, who are consumers of your soon to be legacy design system.
This is how a web component should be designed! Zach has made a custom element that wraps around an existing HTML element, turbocharging its powers. That’s the way to think about web components—as a progressive enhancement.
I remember Lara telling me a great quote from the Clarity conference a few years back: “A design system needs to be correct before it’s complete.” In other words, it’s better to have one realistic component that’s actually in production than to have a pattern library full of beautiful but unimplemented components. I feel like Robin is getting at much the same point here, but he frames it in terms of correctness and usefulness:
If we want to be correct, okay, let’s have components of everything and an enormous Figma library of stuff we need to maintain. But if we want to be useful to designers who want to get an understanding of the system, let’s be brief.