title: The Web Component Success Story
url: https://jakelazaroff.com/words/the-web-component-success-story/
hash_url: f4d2d42eba58062be910407690ae447c
archive_date: 2024-01-31
og_image: https://jakelazaroff.com/og/the-web-component-success-story.png
description: Web components won't take web development by storm, or show us the One True Way to build websites. What they will do is let us collectively build a rich ecosystem of dynamic components that work with any web stack.
favicon: https://jakelazaroff.com/favicon.ico
language: en_US

<p>Tom MacWright wrote a short post wondering <a class="link" href="https://macwright.com/2024/01/24/on-web-components" data-astro-cid-bi7aps5f>why we don’t see prominent applications using web components</a><a class="tooltip" data-tooltip href="https://macwright.com/2024/01/24/on-web-components" data-astro-cid-bi7aps5f>  <span class="title" data-astro-cid-bi7aps5f>On Web Components</span>  <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://macwright.com/css/favicon.png" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>macwright.com/2024/01/24/on-web-components</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>.</p>
<p>That’s a fair question!
It’s easy to see the success of frameworks like React and Rails: just look at the thousands of websites built with them.
What does the web component success story look like?</p>
<p>Contrary to some people, I don’t see web components on their own as a huge productivity boon for individual websites.
Once you’ve bought into a particular set of technologies, it makes sense to use it for as much as you can.
If you have a React app, you’d be justifiably skeptical of introducing a second way to build components!</p>
<p>Rather, the biggest benefits I see are <em>collective</em>, cutting across the industry as a whole.
I think web components can make the entire web more accessible.
They have the potential to unify currently fragmented communities, including various JavaScript frameworks <em>and</em> those who avoid them.</p>
<p>I know that’s an audacious pitch, but bear with me.</p>
<h3 id="javascript-framework-interop">JavaScript Framework Interop</h3>
<p>Whenever I write about web components, I see pushback from people in the JavaScript community who seem to think that I want replace to JavaScript frameworks.</p>
<p>If you’re in that camp, let me assuage those fears: the web component success story emphatically does <em>not</em> involve rewriting every React app using web components.
As I’ll continue to say, web components and JavaScript frameworks are <em>complementary</em> (as opposed to <em>competing</em>) technologies.
In fact, I think JavaScript framework apps will be one of the most common places in which web components are used!</p>
<p>Does that mean we’ll all start writing web components in addition to React components?
Not at all.
When I say that web components will be used in JavaScript framework apps, I’m talking about third-party libraries.</p>
<p>JavaScript frameworks are tools, all tools have tradeoffs, yada yada, let’s skip the preamble.
I want to talk about one specific weakness of JavaScript frameworks: interoperability, or the lack thereof.
Almost without exception, each framework can only render components written for that framework specifically.</p>
<p>As a result, the JavaScript community tends to fragment itself along framework lines.
Switching frameworks has a high cost, especially when moving to a less popular one; it means leaving most of the third-party ecosystem behind.</p>
<p>That switching cost stunts framework innovation by heavily favoring incumbents with large ecosystems.
It’s hard to create new frameworks, because each one has to start its own ecosystem from scratch.
We keep rebuilding the same set of primitives over and over and over again.</p>
<p>There’s a famous Joel Spolsky blog post about <a class="link" href="https://www.joelonsoftware.com/2002/06/12/strategy-letter-v/" data-astro-cid-bi7aps5f>why capitalistic tech companies contribute to open source</a><a class="tooltip" data-tooltip href="https://www.joelonsoftware.com/2002/06/12/strategy-letter-v/" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://i0.wp.com/www.joelonsoftware.com/wp-content/uploads/2016/12/11969842.jpg?fit=400%2C400&amp;ssl=1" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>Strategy Letter V</span> <span class="description" data-astro-cid-bi7aps5f>When I was in college I took two intro economics courses: macroeconomics and microeconomics. Macro was full of theories like “low unemployment causes inflation” that never quite stood u…</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://i0.wp.com/www.joelonsoftware.com/wp-content/uploads/2016/12/11969842.jpg?fit=32%2C32&amp;ssl=1" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>www.joelonsoftware.com/2002/06/12/strategy-letter-v/</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>.
Briefly: every product has <em>substitutes</em> (products that can replace it) and <em>complements</em> (products that can be used alongside it).
The big takeaway is that ”<strong>smart companies try to commoditize their products’ complements</strong>”.
In other words, they try to make it so that their own product has a proprietary advantage, while the products used alongside it are all cheap and interchangeable.</p>
<p>Back to JavaScript frameworks.
React and Svelte are substitutes, while React and Radix are complements.
As a library author, the way to commoditize your complement is to make it work with as many frameworks as possible.<sup><a class="link" href="#user-content-fn-reactnative" id="user-content-fnref-reactnative" data-footnote-ref="" aria-describedby="footnote-label" data-astro-cid-bi7aps5f>1</a></sup>
And unlike in Native Land — where people have collectively spent billions of dollars over decades developing write-once run-anywhere environments — the web has one built in.</p>
<p>Maybe you’ve heard of it?
It’s called HTML, and it works with <a class="link" href="https://custom-elements-everywhere.com" data-astro-cid-bi7aps5f>every Javascript framework</a><a class="tooltip" data-tooltip href="https://custom-elements-everywhere.com" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://custom-elements-everywhere.com/images/card.jpg" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>Custom Elements Everywhere</span> <span class="description" data-astro-cid-bi7aps5f>Making sure frameworks and custom elements can be BFFs 🍻</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://custom-elements-everywhere.com/images/favicon.ico" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>custom-elements-everywhere.com</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>.
For all their warts, the fact that web components get this interoperability for free is a <em>ridiculously powerful advantage</em>, and libraries that don’t exploit it are leaving a lot of potential users on the table.</p>
<p>Here’s a concrete example.
<a class="link" href="https://www.xyflow.com" data-astro-cid-bi7aps5f>xyflow</a><a class="tooltip" data-tooltip href="https://www.xyflow.com" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://xyflow.com/img/og/xyflow.jpg" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>Node Based UIs for React and Svelte – xyflow</span> <span class="description" data-astro-cid-bi7aps5f>Powerful open source libraries for building node-based UIs with React or Svelte. Ready out-of-the-box and infinitely customizable.</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://xyflow.com/img/favicon.ico" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>www.xyflow.com</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a> is an excellent library for making flow charts.
It was originally called React Flow, but the maintainers renamed it when they added Svelte support.
<a class="link" href="https://www.xyflow.com/blog/why-svelte-flow" data-astro-cid-bi7aps5f>They had to put in a ton of work just to support that <em>one</em>  extra framework</a><a class="tooltip" data-tooltip href="https://www.xyflow.com/blog/why-svelte-flow" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://xyflow.com/img/og/xyflow.jpg" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>Why Svelte Flow? – xyflow</span> <span class="description" data-astro-cid-bi7aps5f>xyflow - Customizable library for rendering workflows, diagrams and node-based UIs.</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://xyflow.com/img/favicon.ico" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>www.xyflow.com/blog/why-svelte-flow</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>!
And if you use Vue, Angular, Solid, Qwik or Ember, you’re still out of luck.</p>
<p>React has enjoyed continued success because it has a moat of fantastic third-party libraries: Radix, React Aria, React Three Fiber, Framer Motion and xyflow, among many others.
Web components have the potential to give us that same ecosystem — but for <em>every</em> framework.</p>
<h3 id="islands-of-interactivity">Islands of Interactivity</h3>
<p>Of course, plenty of websites don’t use JavaScript frameworks.
Hypermedia-centric approaches (read: how websites were built before circa 2010) are making a resurgence, led by libraries such as htmx.</p>
<p>Many websites like this still incorporate highly dynamic elements.
Often, these take the form of rich widgets that are missing from HTML, like menus and combo boxes.
Sometimes they’re even more complicated, like interactive diagrams in articles.
The modern term for these dynamic regions within an otherwise static page is “islands of interactivity”, but the pattern has existed for a long time.</p>
<p>Embedding these islands within the larger page has always been kinda awkward.
The process remains mostly unchanged from the days of jQuery plugins, relying on a complex choreography of HTML classes, CSS selectors and JavaScript function calls.
The bulk of the setup happens in a separate JavaScript file, far away from the HTML where the component will live on the page.</p>
<p>Web components invert that process.
They allow islands to be instantiated in the same way as any other element: by writing a tag name in the page’s markup.
As I wrote in <a class="link" href="https://jakelazaroff.com/words/the-website-vs-web-app-dichotomy-doesnt-exist/" data-astro-cid-bi7aps5f>The Website vs. Web App Dichotomy Doesn’t Exist</a><a class="tooltip" data-tooltip href="https://jakelazaroff.com/words/the-website-vs-web-app-dichotomy-doesnt-exist/" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://jakelazaroff.com/og/the-website-vs-web-app-dichotomy-doesnt-exist.png" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>The Website vs. Web App Dichotomy Doesn't Exist | jakelazaroff.com</span> <span class="description" data-astro-cid-bi7aps5f>A one-dimensional spectrum can't sufficiently capture the tradeoffs involved in web development.</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://jakelazaroff.com/favicon.ico" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>jakelazaroff.com/words/the-website-vs-web-app-dichotomy-doesnt-exist/</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>, web components allow developers to declaratively add dynamic behavior to HTML itself.</p>
<p>What makes web components particularly good companions for hypermedia-oriented libraries is the way they interact with other parts of the page.
While JavaScript framework components tend to do so by invoking callback functions, web components instead embrace one of the web’s core idioms: events. <sup><a class="link" href="#user-content-fn-target" id="user-content-fnref-target" data-footnote-ref="" aria-describedby="footnote-label" data-astro-cid-bi7aps5f>2</a></sup>
Indeed, Carson Gross’s essay <a class="link" href="https://htmx.org/essays/hypermedia-friendly-scripting/#events" data-astro-cid-bi7aps5f>Hypermedia-Friendly Scripting</a><a class="tooltip" data-tooltip href="https://htmx.org/essays/hypermedia-friendly-scripting/#events" data-astro-cid-bi7aps5f>  <span class="title" data-astro-cid-bi7aps5f>&lt;/&gt; htmx ~ Hypermedia-Friendly Scripting</span>  <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://htmx.org/favicon.ico#events" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>htmx.org/essays/hypermedia-friendly-scripting/#events</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a> neatly outlines this use case:</p>
<blockquote>
<p>A JavaScript-based component that triggers events allows for hypermedia-oriented JavaScript libraries, such as htmx, to listen for those events and trigger hypermedia exchanges. This, in turn, makes any JavaScript library a potential hypermedia control, able to drive the Hypermedia-Driven Application via user-selected actions.</p>
</blockquote>
<p>As an example, here’s a TIL I wrote on <a class="link" href="https://til.jakelazaroff.com/htmx/load-modal-content-when-shoelace-dialog-opens/" data-astro-cid-bi7aps5f>using htmx and the Shoelace web component library to load the content of a dialog when it opens</a><a class="tooltip" data-tooltip href="https://til.jakelazaroff.com/htmx/load-modal-content-when-shoelace-dialog-opens/" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://til.jakelazaroff.com/og/htmx/load-modal-content-when-shoelace-dialog-opens.png" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>[htmx] Load modal content when a Shoelace dialog opens | Today I Learned</span> <span class="description" data-astro-cid-bi7aps5f>A collection of useful things I've learned.</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://til.jakelazaroff.com/favicon.ico" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>til.jakelazaroff.com/htmx/load-modal-content-when-shoelace-dialog-opens/</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>.
Notice how the whole process — from instantiating the dialog component, to requesting the content when the modal opens, to inserting it into the appropriate place in the DOM — is controlled declaratively via markup.</p>
<p>There are also <a class="link" href="https://www.zachleat.com/web/a-taxonomy-of-web-component-types/#html-web-components" data-astro-cid-bi7aps5f>HTML web components</a><a class="tooltip" data-tooltip href="https://www.zachleat.com/web/a-taxonomy-of-web-component-types/#html-web-components" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://v1.screenshot.11ty.dev/https%3A%2F%2Fwww.zachleat.com%2Fopengraph%2Fweb%2Fa-taxonomy-of-web-component-types%2F/opengraph/_x202401_0/" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>An Attempted Taxonomy of Web Components—zachleat.com</span> <span class="description" data-astro-cid-bi7aps5f>A post by Zach Leatherman (zachleat)</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://www.zachleat.com/img/rel-icon-192.jpg#html-web-components" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>www.zachleat.com/web/a-taxonomy-of-web-component-types/#html-web-components</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>, which work by progressively enhancing existing markup rather than by rendering new DOM elements.
Colocating logic in this way, sometimes called <a class="link" href="https://htmx.org/essays/locality-of-behaviour/" data-astro-cid-bi7aps5f>locality of behavior</a><a class="tooltip" data-tooltip href="https://htmx.org/essays/locality-of-behaviour/" data-astro-cid-bi7aps5f>  <span class="title" data-astro-cid-bi7aps5f>&lt;/&gt; htmx ~ Locality of Behaviour (LoB)</span> <span class="description" data-astro-cid-bi7aps5f>htmx gives you access to AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext

    htmx is small (~14k min.gz’d), dependency-free, extendable, IE11 compatible &amp; has reduced code base sizes by 67% when compared with react</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://htmx.org/favicon.ico" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>htmx.org/essays/locality-of-behaviour/</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>, is a different lens on <a class="link" href="https://speakerdeck.com/didoo/let-there-be-peace-on-css?slide=62" data-astro-cid-bi7aps5f>a concept with which JavaScript developers should already be familiar</a><a class="tooltip" data-tooltip href="https://speakerdeck.com/didoo/let-there-be-peace-on-css?slide=62" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://files.speakerdeck.com/presentations/ecd310041a6841e0b4680dd85771a6fb/slide_61.jpg?8848622" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>Let There Be Peace On CSS</span> <span class="description" data-astro-cid-bi7aps5f>In the last few months there's been a growing friction between those who see CSS as an untouchable layer in the "separation of concerns" paradigm, and those who have simply ignored this golden rule and found different ways to style the UI (typically applying CSS styles via JavaScript).

This debate is getting more and more intense every day, bringing division in a community that used to be immune to this kind of “wars”.

This talk is my attempt to bring peace between the two fronts. To help these two opposite factions to understand and listen to each other, see the counterpart's points of views. To find the good things they have in common, and learn something from that.

## This talk has been presented at London CSS Meetup + Design Exchange Nottingham (DXN) + Front End London (FEL) + State of The Browser ##

Video of the talk: https://www.youtube.com/watch?v=bb_kb6Q2Kdc</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://d1eu30co0ohy4w.cloudfront.net/assets/favicon-bdd5839d46040a50edf189174e6f7aacc8abb3aaecd56a4711cf00d820883f47.png" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>speakerdeck.com/didoo/let-there-be-peace-on-css?slide=62</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>.</p>
<h3 id="no-more-silos">No More Silos</h3>
<p>These sound like separate problems, but they’re actually two sides of the same coin.
With web components, the library that works in every JavaScript framework <em>also</em> works as an island of interactivity on a static webpage.
Even HTML web components fit into both niches.</p>
<p>Brad Frost has called for <a class="link" href="https://bradfrost.com/blog/post/a-global-design-system/" data-astro-cid-bi7aps5f>a global design system</a><a class="tooltip" data-tooltip href="https://bradfrost.com/blog/post/a-global-design-system/" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://bradfrost.com/wp-content/uploads/2023/11/CleanShot-2023-11-02-at-13.53.24.png" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>A Global Design System</span> <span class="description" data-astro-cid-bi7aps5f>TL;DR: This is a call to action to create a Global Design System that provides the world's web designers &amp; developers a library of common UI components. A Global Design System would improve the quality and accessibility of the world's web experiences, save the world's web designers and developer</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://bradfrost.com/favicon.ico" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>bradfrost.com/blog/post/a-global-design-system/</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>: “a common library containing common UI components currently found in most design systems”.
The proposal is to create a cohesive, unstyled, accessible and internationalizable set of components — like <a class="link" href="https://www.radix-ui.com/primitives" data-astro-cid-bi7aps5f>Radix</a><a class="tooltip" data-tooltip href="https://www.radix-ui.com/primitives" data-astro-cid-bi7aps5f> <img class="thumbnail" src="https://radix-ui.com/social/primitives.png" alt="" data-astro-cid-bi7aps5f> <span class="title" data-astro-cid-bi7aps5f>Radix Primitives</span> <span class="description" data-astro-cid-bi7aps5f>Unstyled, accessible, open source React primitives for high-quality web apps and design systems.</span> <span class="href" data-astro-cid-bi7aps5f> <img class="favicon" src="https://www.radix-ui.com/favicon.png" alt="" data-astro-cid-bi7aps5f> <span class="url" data-astro-cid-bi7aps5f>www.radix-ui.com/primitives</span> <svg xmlns="http://www.w3.org/2000/svg" class="arrow"> <use href="/icons.svg#share"></use> </svg> </span> </a>, but for the entire web rather than for a single JavaScript framework.
It’s an ambitious goal, and from where I stand web components are by far the best way to achieve it.</p>
<p>Web components won’t take web development by storm, or show us the One True Way to build websites.
They don’t need to dethrone JavaScript frameworks.
We probably won’t even all learn how to write them!</p>
<p>What web components <em>will</em> do — at least, I hope — is let us collectively build a rich ecosystem of dynamic components that work with any web stack.
No more silos.
That’s the web component success story.</p>