Web components were introduced in 2011, but if you ask most frontend developers, they aren’t their first choice for composing UI layouts. This is partly due to an increase in JavaScript frameworks, component-driven development enthusiasts, and other esoteric factors over the years.
Two key drawbacks of web components are:
- Web components don’t follow native HTML behaviour.
- Issues with backward-compatability and SEO
Now, in comes Shoelace, a UI library built on web component technology that offers the same experience as any JavaScript framework but with better perks. It defines all your standard UX components: tabs, modals, accordions, auto-completes, and much, much more. They look beautiful out of the box, are accessible, and fully customizable. But rather than creating these components in React, or Solid, or Svelte, etc., it creates them with Web Components; this means you can use them with any framework.

With Shoelace, you can:
- Start building things faster (no need to roll your own buttons)
- Build multiple apps with different frameworks that all share the same UI components
- Fully customize components to match your existing designs
- Incrementally adopt components as needed (no need to ditch your framework)
- Upgrade or switch frameworks without rebuilding foundational components
A Better Developer Experience
A huge advantage of using Web Components is that you get real custom HTML elements with a familiar API. Let’s compare the markup for a Bootstrap button and a Shoelace button.
<!-- Bootstrap -->
<button type="button" class="btn btn-primary">Primary</button>
<!-- Shoelace -->
<sl-button type="primary">Primary</sl-button>
Even with this simple example, you can already see there’s less code involved. This becomes even more obvious with complex components. Let’s take a look at dialogs. Here’s a Bootstrap dialog.
<!-- Bootstrap -->
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Modal body text goes here.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
That’s a lot of markup! And there’s plenty of room for error with those aria attributes exposed.
Now let’s take a look at an equivalent Shoelace dialog.
<!-- Shoelace -->
<sl-dialog label="Dialog">
<h3 slot="header">Modal Title</h3>
Modal body text goes here.
<sl-button slot="footer">Close</sl-button>
<sl-button slot="footer" type="primary">Save Changes</sl-button>
</sl-dialog>
That’s much easier to work with! And there’s less room for error since the component handles its aria attributes internally. Pretty cool right?
Why Use It?
At this point, you’re probably wondering what sets Shoelace apart from other component libraries. For one, it’s framework agnostic, meaning you can use it in React, Vue, Angular, and any other framework you throw at it. This is perfect for teams that want to use different frameworks with the same components for a consistent UX.
Since Shoelace components are Web Components, they’re built on standards that browsers have committed to supporting for a long time. As old frameworks age and new ones emerge, you won’t have to spend time rebuilding buttons, inputs, and other low-level components. Shoelace will just keep working.
If you prefer to use the platform and avoid frameworks altogether, that’s fine too. Shoelace works great with vanilla HTML+JS!
And yes, Shoelace is open source and available under the MIT license, so it’s free to use and anyone can contribute to it!
If you’re interested in learning more about Shoelace, here are some links you’ll find useful!