Debunking Web Component Myths and Misconceptions

EisenbergEffect
13 min readMar 27, 2023

This is a re-publication and expansion of some content first published in “About Web Components” on common Web Component myths and misconceptions. I’ll continue to update this article as I find more erroneous content. My hope is that breaking out this information and expanding it will make it easier for readers to share corrections with people as they encounter them.

Unfortunately, there’s a lot of bad information on Web Components in the wild. Some of it is just old and out of date content. Some of it was incorrect from the beginning. Sadly, some of it is complete FUD or utter nonsense. Let’s take a few minutes to make sure we’ve got our facts straight.

Web Components are supported in every browser.

Some folks still seem to get confused about browser support. To be clear, Web Components v1 have been supported in every browser for over three years as of the writing of this article. Here are two things that I think may be behind the confusion:

  • Safari specifically doesn’t implement what are called “customized built-in elements”. This is the ability to inherit from base classes other than HTMLElement, such as HTMLParagraphElement. W3C members from Safari’s engineering team rejected that part of the specification based on OCP violation concerns (which I agree with) and UA challenges. Safari adamantly wants this removed from the spec since it will never be implemented. While it may be handy to inherit from some built-ins, doing so means it would be impossible to safely evolve the built-ins and standards, adding or fixing features after that point in time. In practice, there is very little need for this and there are alternative ways to get a similar end result. This should not be treated as part of the spec and will likely be dropped in the future.
  • Searching for “Web Components” on caniuse.com yields results that are dubious at best. Here are a few things that are incorrect or confusing:
    — The results show that Safari doesn’t fully implement Web Components in any of its versions. That is incorrect! See the previous bullet point for the explanation. In short: Safari doesn’t support an unnecessary, confusing, problematic proposal that will likely be removed from the spec. You don’t need it to build Web Components. Safari supports all the necessities.
    — The results show that no browser supports “HTML Imports”. You may note that I haven’t mentioned this “feature” of Web Components in any of my posts. That’s because this was part of the v0 Web Components proposal and was removed years ago. In other words, it’s not part of Web Components at all.
    — Declarative Shadow DOM is only partially supported. Again, I haven’t talked about this yet because it’s not part of v1 Web Components. This is a newer proposal that can be thought of as part of the 2nd or even 3rd iteration of Web Components. So, it’s still being implemented by browsers. I’ll be talking about this spec more in an upcoming post. In any case, you don’t need this to create Web Components.

You can use Web Components without polyfills.

When we say “Web Components are supported in every browser” that means that you don’t need to use polyfills. Every major browser supports the v1 Web Components features natively.

Web Components can be SEO friendly.

Like HTML in general, Web Components can be assembled in a way that yields great SEO results or they can be assembled in a way that doesn’t. It’s up to you. Like with all HTML, you have to think about SEO and architect for that characteristic. The main technique to keep in mind where Web Components are concerned is that you want your SEO critical content to be in the Light DOM whenever possible. Follow this rule of thumb and your SEO will be fine.

NOTE: I mentioned this in a previous post but wanted to share this thought again here as well. Many don’t find the terms “Light” and “Shadow” DOM particularly intuitive or explanatory. Instead, it may be useful to think of the “Light” DOM as the “Semantic” DOM. The “Shadow” DOM can then be thought of as the “Render” DOM. Shadow DOM is a private document that describes how the element will render itself, without affecting semantics. Most native component models have similar concepts, e.g., Logical vs. Visual trees.

Beyond the practice of properly leveraging both Light and Shadow DOM for good SEO, you can leverage Declarative Shadow DOM (DSD), which places the entire Shadow DOM into the document flow, making it easily parse-able and crawlable as well.

Finally, it’s important to note that both Google and Bing’s crawlers do execute JavaScript. So, even if you have non-declarative Shadow DOM, and poorer Light DOM SEO practices, your Web Component code will be getting executed, and your Shadow DOM will be instantiated along with that.

In short, SEO is not a problem assuming you are designing properly for it, which is something good SEO has always required.

Web Components can be accessible.

Similar to SEO, you have to architect for accessibility. Web Components aside, if you don’t write your HTML in an accessible way, then it may not be accessible. The same goes for Web Components. Think about and architect for accessibility from the beginning.

Having said that, I want to acknowledge that accessibility is difficult and takes a lot of time. This is one of the reasons why FAST exists. One of things it provides is a library called @microsoft/fast-foundation that specifically aids in the development of accessible versions of the most foundational Web Components (e.g. button, menu, tree-view, select, combobox, etc.)

You can share styles between Web Components.

A common concern I hear from folks is that they can’t share existing styles with Web Components due to Shadow DOM encapsulation; or that they can’t share any form of common styles. However, this is probably just a misunderstanding. The standards support this, and most Web Component libraries make this very easy as well. All you need to do is create a style sheet and add it to the adoptedStyleSheets collection of the Web Component. The sheet can be shared across any Web Component that needs its styles. With CSS Script Modules, this is incredibly easy.

import sheet from './styles.css' assert { type: 'css' };

shadowRoot.adoptedStyleSheets = [sheet];

If you aren’t using constructible styles, then you can also just create a style element, insert the CSS text, and then add the style element to your element’s Shadow DOM. It’s a bit more work but doable. Most Web Component libraries do this automatically for you, so it’s no effort at all.

You can use global styles in Web Components

You don’t have to use Shadow DOM when you create a custom element. You can easily create custom elements that render to the Light DOM, using global CSS like everything else.

However, you can also leverage global styles in Shadow DOM.

Because of the ability to add any style sheet to the adoptedStyleSheets of a shadow root, you can simply create sheets from the document.styleSheets collection and use them in your Shadow DOM. Here’s a blog post that goes into detail and provides code examples.

You can use custom fonts in a Web Component.

There’s no issue using custom fonts in a Web Component. What you can’t do is define your @font-face configuration inside of a Shadow Root. Instead, in the connectedCallback of your Web Component, run a small bit of code that does a one-time injection of the @font-face configuration into the document. Then just use the fonts as normal in your component’s CSS.

NOTE: You should strongly consider whether you really need a Web Component to bring custom fonts along with it. Usually, you will want to leave the font selection up to the consumer of the component. If you want to designate certain parts of your component to receive a developer-selected font, then consider using a CSS Custom Property for font-family so that the developer can easily set that to the font they want.

You can pass any data type to a Web Component.

Many people forget that HTML elements have both an attribute and a property interface. While it’s true that a Web Component can only receive string data through its attributes, that’s not true of its properties. Like any JavaScript object, you can set a Web Component’s properties to any type of data.

myAvatar.person = new Person(); // It's just JavaScript after all.

In addition to this, popular Web Component libraries make it easy to bind any type of data to a component via their template system.

You can create Web Components without classes.

Classes are basically just special syntax over functions. If you really don’t want to use class syntax for Web Components, you can do this:

function MyElement() {
return Reflect.construct(HTMLElement, [], MyElement);
}

Object.setPrototypeOf(MyElement.prototype, HTMLElement.prototype);
Object.setPrototypeOf(MyElement, HTMLElement);

customElements.define('my-element', MyElement);

Personally, I prefer this though:

class MyElement extends HTMLElement {}
customElements.define('my-element', MyElement);

Web Components can support both eager and lazy slotting.

Some proponents of proprietary JavaScript frameworks have pointed out that Shadow DOM slots eagerly render their content and that this makes Web Components inferior to their approaches, which lazily render slots. This point is quite irrelevant because HTML has had built-in support for lazy rendering for years. That’s one of the scenarios that the template element is used for. Whenever you want a Web Component to support lazy slotting, just have it respond to template elements by cloning them and appending their content on demand. This allows the Web Component author to choose whether they want eager, lazy, or both behaviors. Regardless of whether the component you are using supports this, you the consumer can also use this technique directly with templates as well. Web Platform FTW!

You can use Web Components with any front-end framework.

Web Components are just HTML elements. Any framework that knows how to create elements, set attributes, dispatch/handle events, etc. can work with Web Components.

You can use Web Components in React.

Contrary to what seems to be the popular thought, you can use Web Components in React. Here are the basic React docs on this.

I think the confusion stems from the fact that React’s message has been that it doesn’t “officially” support Web Components. From what I can tell, the team is planning to “fix” this in React 19 and has already addressed it in the experimental releases.

You might be wondering why the React team is hesitant to say they officially support Web Components. To be blunt, React has always treated the DOM in an antagonistic way, quite different from the friendlier approaches that almost every other modern JavaScript framework uses. React’s system doesn’t recognize the difference between an HTML attribute, a property, and a boolean attribute. These are all core HTML implementation details that have been part of the basic programming model for 20+ years. But because React doesn’t distinguish between these cases, it has a hard time natively interoperating with Web Components that have properties and boolean attributes in addition to standard attributes. Additionally, React doesn’t properly support the DOM’s event system. It creates a synthetic event system. This causes issues not just for Web Components, but also for many non-React libraries. The changes being made (hopefully) for React 19 will address these issues.

However, you don’t need to wait for the React team. There are several ways to use Web Components in React today without having to deal with the above-mentioned issues.

  1. You could use something like @skatejs/val to handle the interop between Web Components and React’s virtual DOM.
  2. You could use something like FAST’s React Wrapper library, that automatically turns any Web Component into a React component.
  3. You can always use the Web Component directly, knowing that you can just handle properties and events manually using refs.

All three of these are viable options that I have seen used in large-scale React/Web Component hybrid systems. Bottom line: yes, you can use Web Components in React.

NOTE: In some cases, you may run into trouble with these techniques in an existing React application. If so, make sure your transpiler is configured correctly. create-react-app has an unfortunate default configuration that is not friendly to modern Web Components. You will want to eject and properly configure things. You can read more about that here.

You can use Web Components with any server-side framework.

Web Components are just HTML elements. Any server-side framework that can output HTML can usually output custom element tags as well. That’s all there is to it. Naturally, you can generate templates and Declarative Shadow DOM too. Those are also just HTML elements.

Web Components have a fast startup time.

Somewhere I read a blog post that indicated Web Components might not have a fast startup time. The author had no basis for their statement but was merely conjecturing. In my experience working with dozens of teams at Microsoft from 2020 through the end of 2022, and many teams outside of Microsoft, Web Components have great startup time (see the section titled “Performance” in “About Web Components” for some explanation on why). Back when I advised and trained the MSN team on Web Components, we found that by moving MSN from React to FAST Web Components, MSN was able to improve startup time by 30–50%. Here’s a blog post written by someone who was on the team at the time when the conversion was being investigated.

Shadow DOM is efficient.

Some folks have raised a concern that Shadow DOM might not be efficient or that it might be too heavy for use at scale. In the last 8 years that I’ve been putting Shadow DOM-based solutions into production, I can tell you that this has not been a problem. Surprisingly, some performance tests we did at Microsoft showed that in some cases, Declarative Shadow DOM could be even faster than Light DOM. Other tests we performed on standard Shadow DOM scenarios showed that the use of Shadow DOM was critical for performance optimization of the browser in codebases with lots of components and large quantities of CSS. It turns out, if your app needs to scale, then you need Shadow DOM to make the browser perform. As mentioned previously, this is because Shadow DOM gives the browser more information about component boundaries, enabling it to optimize better.

You can server-side render Web Components.

Declarative Shadow DOM is a new standard that enables you to leverage Shadow DOM directly in HTML without using JavaScript, allowing it to be generated on the server. It is supported in Chromium browsers as well as the Safari. Declarative Shadow DOM can easily be polyfilled with only a few lines of JavaScript code. Both FAST and Lit now offer SSR renderers for their Web Component libraries. Furthermore, the SSR renderers of both Web Component libraries are built on a shared, work-in-progress W3C protocol, enabling them to interoperate and support HTML streaming out of the box.

Hydrating SSR’d Web Components can be highly efficient.

Some have said that hydrating SSR’d Web Components is inefficient because it would necessarily involve blowing away the entire DSD. This is not true. There is nothing in Web Components that requires this. An optimized hydration process can re-use the existing DSD, locate existing elements, and attach dynamic behaviors, without additional rendering required.

Web Component SSR can be implemented using lightweight techniques.

There is nothing in Web Components that dictates server implementation details. Web Components are a browser standard. You can implement your server any way you choose. Both Google and Microsoft are working on a shared protocol for Web Component server rendering. The protocol implementations do not use heavy libraries like JSDOM. They are string-based and streaming.

Web Components are a great solution for progressive enhancement.

Some have argued that because Web Components “require” JavaScript, that they are not suitable for progressive enhancement approaches. However, with the standardization of Declarative Shadow DOM, the server can send down Shadow DOM HTML along with encapsulated styles, allowing a Web Component to render without JavaScript, but with the added benefits of style encapsulation, Shadow DOM encapsulation, Shadow DOM performance, and more. Once your JavaScript bundles download, then the browser will automatically handle upgrading (progressively enhancing) your Web Components for you, adding the JavaScript behavior. As a reminder, both FAST and Lit now offer SSR renderers for their Web Component libraries.

Large, business-critical software has been built with Web Components.

Adobe built Photoshop with Web Components. Microsoft re-built MSN with Web Components. Google built YouTube with Web Components. Those all seem like pretty business-critical to me.

But are any other well-known companies building with Web Components?

Web Components scale to any size project.

See the previous section as well as my previous post for performance notes on Shadow DOM. From single components to design systems, to content-oriented experiences and entire applications, Web Components can handle the situation. In fact, you need them to scale beyond a certain point if you want your application to perform.

Web Components are mainstream.

Some folks claim that Web Components are niche. Hardly. At the time of this writing, over 18% of all Chrome page loads use Web Components. See above for how large companies are making significant, business-critical investments in this technology.

Beyond this, core new HTML capabilities are being built on top of Web Components. For example, the upcoming selectmenu HTML element is implemented as a Web Component in Chromium. For years, the Chromium video tag has been implemented this way as well.

NOTE: selectmenu and video aren’t implemented in JavaScript. They are implemented in C++, using the C++ side of the Web Component APIs.

Web Components are a huge area of interest.

Occasionally someone here or there will try to make it out that no one is interested in Web Components. But results from the 2022 MDN API Survey last year clearly indicate that the topic of Web Components is the highest area of interest among web developers.

Web Components are a growing area of investment by platform implementors.

So far on my blog I’ve been talking about “Web Components v1”. But after this first set of features shipped, we didn’t stop progressing the capability set. Work has continued by adding new APIs for native form elements, Declarative Shadow DOM, CSS custom states, an imperative ARIA model, and more. I’ll be talking about all these features in future posts. For now, let’s just say that Web Components are a highly active area of platform development. 😏

Wrapping Up

It’s unfortunate that so much incorrect information has been circulated about Web Components over the years. Hopefully this post can help to create clarity and will be a good resource for sharing when you encounter someone who is confused or misinformed on the subject.

If you enjoyed this look into Web Components, you might want to check out my Web Component Engineering course. I’d also love it if you would subscribe to this blog, subscribe to my YouTube channel, or follow me on twitter. Your support greatly helps me continue writing and bringing this kind of content to the broader community. Thank you!

--

--

EisenbergEffect

W3C, WICG & TC39 contributor focused on Web Standards, UI Architecture & Engineering Culture. Former Technical Fellow, Principal Architect & VP-level tech lead.