Web-Development
| Tobias Gerlach

CSS Web Components: The Architecture for the Post-JavaScript Era

CSS Web Components Astro Web Architecture No-JS

👋

Those who know me know that I’ve been on the web since 2001. I’ve seen the rise of Flash, the “Web 2.0” hype, and – let’s be honest – the absolute dominance of JavaScript frameworks in the last decade. But you know what? IMO, we are currently experiencing one of the most exciting turning points in the history of web development.

For a long time, we misused the DOM merely as a “render target” for our complex React or Vue apps. But since around 2024, the wind has been turning. We are moving back to the roots, but with superpowers. It’s called “HTML First” or “Transitional Web,” and the star of this show is CSS Web Components.

In this article, I want to dive deep into the technology with you. We’ll look at how we can use modern browser APIs to build performant, robust, and privacy-friendly UIs – almost completely without JavaScript. This not only saves your users’ battery life but is IMO also an act of digital sustainability.

What are “CSS Web Components” anyway?

First, we need to clear up a misunderstanding. When we talk about “Web Components” here, we don’t necessarily mean the full W3C spec with Shadow DOM, customElements.define(), and complex JS classes.

It is rather a design pattern popularized by developers like Hawk Ticehurst and Jim Nielsen. The idea is brilliantly simple: We use Custom Elements (i.e., our own HTML tags like <marketing-card>) as semantic containers, but we leave the entire logic, layout, and interactivity to modern CSS.

Here is the difference at a glance:

FeatureStandard Web Component (Lit/Vanilla)CSS Web Component
IdentityDefined via JS (customElements.define)Undefined (Browser treats it as HTMLElement)
StylingShadow DOM (encapsulated)Light DOM (Part of the global cascade)
LogicImperative (JS Event Listeners)Declarative (CSS Selectors, :has())
HydrationNecessaryNo Hydration (works immediately)

IMO, this is the “sweet spot” for 90% of all components on marketing sites or blogs. Why load a JS runtime just to make a card colorful?

The Architecture of the “Undefined”

This is the part that really fascinates me as an old web veteran. How does the browser actually react to a tag like <marketing-card> that it doesn’t know?

The modern HTML specification is very strict here: Tags with a hyphen (e.g., <hero-banner>) are automatically considered potential Custom Elements. Even without a single line of JavaScript, the browser treats them as a generic HTMLElement. This means:

  1. No FOUC (Flash of Unstyled Content): Since no JS has to wait, the styling is there immediately.
  2. Full CSS Control: We simply style them like a div.

A little pro-tip for your CSS resets on these elements:

marketing-card,
feature-grid,
user-avatar {
  display: block; /* Default is inline */
}

There is even the :defined selector. Theoretically, you could use it to detect if JavaScript was loaded to “upgrade” the element after all. But CSS Web Components intentionally remain in the :not(:defined) state.

The “Props” API without JavaScript

In the React world, we love props. “Data in, UI out.” But did you know that HTML could always do that? Attributes are our props.

Instead of imperative logic, we use the power of CSS Variables (Custom Properties). This keeps the code extremely clean and maintainable.

The Pattern:

/* Base Definition */
marketing-card {
  --padding: 1rem;
  --bg-color: #ffffff;

  display: flex;
  background: var(--bg-color);
  padding: var(--padding);
}

/* The "Prop" Logic via Attribute Selector */
marketing-card[variant="featured"] {
  --bg-color: #f0f9ff;
  --padding: 2rem;
  border: 2px solid #0070f3;
}

In HTML, we simply use it like this: <marketing-card variant="featured">. This is declarative, readable, and requires zero computing power on the client.

👉 Live Demo on CodePen

The New CSS Engine: Who Needs JS Logic?

Now it gets technically really exciting. The browser engines (Blink, WebKit, Gecko) have received features in recent years that make many JS tasks obsolete. For me as a privacy fan, this is great: Fewer scripts often mean fewer tracking vectors and more security.

1. Container Queries (@container)

Finally, components can react to their own space, not just the viewport. A <news-card> can look different in the sidebar than in the main area without us having to toggle classes.

news-card {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card-layout {
    display: grid;
    /* Layout changes based on container width */
  }
}

2. The :has() Selector (Parent Selector)

This is IMO the absolute gamechanger. We can style a parent element based on what happens inside it. Example: Form validation. Color the whole group red if any input inside it is invalid.

form-group:has(input:invalid) {
  border-left: 4px solid red;
}

3. Anchor Positioning

Tooltips and popovers used to be hell without libraries like Popper.js. With the Anchor Positioning API, the browser calculates the positioning itself. Unfortunately, Firefox and Safari are still lagging a bit behind here (as of 2026), but polyfills help.

Astro & CSS Web Components: Best Friends

As is well known, I use Astro for almost everything. Astro is predestined for this approach because it delivers “Zero-JS” by default.

We can use an .astro file as a “component factory.” The frontmatter processes the data at build time, and pure HTML and CSS fall out.

Example FeatureCard.astro:

---
interface Props {
  title: string;
  theme?: 'dark' | 'light';
}
const { title, theme = 'light' } = Astro.props;
---

<feature-card data-theme={theme}>
  <h3>{title}</h3>
  <slot />
</feature-card>

<style>
  feature-card {
    display: flex;
    flex-direction: column;
    /* ... */
  }

  feature-card[data-theme="dark"] {
    --bg-surface: #1a1a1a;
    --text-color: #ffffff;
  }
</style>

The genius part: Since Astro scopes (isolates) the styles, we don’t get in each other’s way. If we want to use the component in Markdown, we often have to make it globally available, but for isolated UI islands, this is perfect.

A Critical Word: Accessibility (A11y)

You know, tolerance and inclusion are important to me. And here we have to be hellishly careful with CSS Web Components. A <custom-button> is initially not a button for a screen reader. It is just a <span> without meaning. It is not focusable and does not react to the Enter key.

Therefore, my urgent appeal: Use the “Wrapper Pattern”!

Wrong (Anti-Pattern): <marketing-link to="/about">About Us</marketing-link> – Here semantics are missing.

Right (Best Practice):

<marketing-link>
  <a href="/about">About Us</a>
</marketing-link>

Here the browser (and the screen reader) sees a real <a> tag. The <marketing-link> only serves as a styling hook. This is “Progressive Enhancement” in its purest form.

Conclusion

The return to native web standards is more than just a trend for me. It is a philosophical correction. We accept the browser again for what it is: a highly optimized rendering engine, not just a runtime environment for JavaScript.

For us developers, this means:

  1. Performance: Our pages load faster.
  2. Resilience: If the JS crashes, the page still looks good.
  3. Maintainability: Clear separation of HTML and CSS.

Of course, CSS reaches its limits when it comes to complex business logic (shopping carts, etc.). But for the 90% “Content UI,” we should trust the browser.

Demo on CodePen

👉 Live Demo on CodePen

What do you think? Are you ready to put your JS frameworks aside for a moment and write “naked” HTML? Feel free to write to me!

Stay curious!

AI Translated Content

This article was translated from German using Artificial Intelligence. While we strive for accuracy, some nuances may be lost. Read original

Note: This post reflects my personal opinion and does not constitute legal advice.
Did you find a mistake or do you have questions/comments on this topic? I look forward to your message!

Tobias Gerlach

Tobias Gerlach

Battle-proof Web Developer since 2001. Seen every wave – and still here. Passionate about clean code, minimalist design, state-of-the-art technologies, and digital privacy.