What are Web Components?
At their core, Web Components let you create your own HTML elements.
They’re built on three browser features:
Custom Elements: define reusable HTML elements
Shadow DOM: encapsulate markup and styles
Templates & slots: reuse structure and allow composition
Together, they let you build components that behave like native HTML—just with your own logic.
The key idea is simple:
Build once, use anywhere—without worrying about conflicts or framework lock-in.
Why they’re useful (especially in CMS projects)
Web Components solve a familiar problem: reusable UI that doesn’t fall apart at scale.
They give you:
Reusability: one component across multiple projects
Encapsulation: styles and logic don’t leak
Framework independence: works in React, Vue, or plain HTML
Maintainability: smaller, modular pieces are easier to reason about
In a system like Umbraco, this maps directly to how content is structured.
Why use Lit?
You can build Web Components with vanilla APIs—but it gets repetitive quickly.
Lit keeps things lightweight while smoothing over the rough edges:
Reactive properties (UI updates automatically)
Simple templating
Minimal boilerplate
It’s essentially a thin layer on top of web components, just enough framework to stay productive.
Atomic design
Web Components work best when structured consistently. A simple, proven approach is atomic design:
Atoms: small, single-purpose
Molecules: combinations of smaller components
Organisms: full sections
Templates: page-level layout and structure
Pages: real content + data
The important part isn’t the naming—it’s the direction: small → composed → larger. No circular dependencies, no surprises.
Adapting atomic design for Umbraco
In practice, especially in CMS-driven projects, the original model doesn't always map cleanly.
With Umbraco, it is very common to work with blocks via the Block List property editor. In this context, the core unit of composition isn't a "template" or "page", but a "block".
So we adapt the structure slightly:
atoms → molecules → organisms → blocks
Why replace templates/pages with blocks?
Because in Umbraco:
Pages are usually built from Block List items.
Each block has its own content model.
Each block is rendered independently via a partial view.
That makes the block the most important level in the system.
What "blocks" represent
A block is:
A CMS-defined content structure
A server-rendered entry point (Razor)
A web component on the front end
In the below example:
Umbraco controls the data
The web component controls the UI and behaviour
A simple component
Here’s a stripped-down example of a heading:
Use it anywhere:
Composition, properties, and slots
Components become powerful when you combine them.
Key patterns:
Properties: pass data (heading="...")
Slots: allow overrides (slot="icon")
Composition: build bigger pieces from smaller ones
This keeps components flexible without making them fragile.
Events (keeping things decoupled)
Components shouldn’t know about the app—they should just emit signals.
Styling (without the usual headaches)
Shadow DOM gives you scoped styles by default.
Using Web Components in Umbraco (Block List)
This is where Web Components really fit.
In our projects, we:
Use the Block List editor to structure pages
Map each block to a Web Component
Pass data from Razor into the component
What this gives you
The CMS controls content
The component controls behaviour and UI
This separation makes both sides easier to manage.
Build and delivery (only what you need)
Instead of loading one large bundle, we load components per page.
Page request:
Determine required blocks
Load matching component scripts
Components upgrade in the browser
This keeps performance predictable—even as the system grows.
Why this approach works
Combining Umbraco + Web Components gives you:
Flexible content editing (Block List)
Reusable UI (components)
Clear separation between content and presentation
It’s a setup that scales well across teams and projects.
Final thoughts
Web Components aren’t trying to replace frameworks - they are about using the platform more effectively.
In an Umbraco context, they are a natural fit:
Blocks map cleanly to components
Components stay reusable and isolated
Front-end development becomes faster and more predictable
If you’re building block-based CMS solutions, Web Components are worth serious consideration. When combined with Lit and a clear structure, they give you a setup that is simple to reason about, easy to scale, and hard to outgrow.
We’ve been using this approach across Umbraco projects to build scalable, component-driven front ends. If you’re exploring something similar, it’s a pattern worth investing in early.