I’ve done my time thinking about scope in CSS. I’ve done it my whole career, and did a presentation on it recently that I wrote up in full here. That was on the heels of @scope becoming a thing in CSS, which is, naturally, a part of the scope in CSS story.
I don’t entirely dislike It can do three things, all of which I find quite niche:@scope, but I guess I’m comfortable saying I’m disappointed in it.
- Donut scoping
- Proximity specificity
- DOM blasters
I covered these in my talk. They have their uses, but again: niche.
UPDATE: Actually @scope… also does what I talk about in this post. And arguably, it does it better because the purpose is more aligned with the name, and it has deeper browser support. I’ll add an additional section below showing how similar it is.
The kind of scoping that I want in CSS is the kind that we’ve been given by tools like <style scoped> in .vue files and Svelte components, and more broadly, what CSS modules does.
I want to write:
.card {
}Code language: CSS (css)
And have it turned into something like:
[data-style="apio087df"] {
/* Or, .card-apio087df */
/* But I kinda like the data-attribute approach
better because it leaves the original class alone */
}Code language: CSS (css)
(And have that attribute applied to my HTML so the new selector works.)
The reason I want that is that I don’t want to worry about a class name I’m writing conflicting with an existing class. I just don’t want to think about it. Ever, ideally.
I don’t need this on every project I touch; I want it on large-scale projects with many components and numerous style changes maintained over many years.
To me, that’s a scoped style.
I already get it with CSS modules, and that’s fine. But I’m a big fan when the web platform steps in and helps us do things we’d otherwise need a build process and tooling for. That’s what we didn’t get with @scope.
Another option is just to make all your class names unique. This works on the vast majority of projects and requires no technology we didn’t have pretty much since HTML and CSS began life.
If class name scoping is all you or I ever do, that’s OK. I can live with that.

But wait, name-only containers?
I read in the Safari 26.4 release notes that Safari is now supporting name-only containers. Like this:
/* Name a container */
.sidebar {
container-name: sidebar;
container-type: inline-size;
}
/* Write styles with that name only, no conditions */
@container sidebar {
.card {
padding: 1rem;
}
}Code language: CSS (css)
No conditions? Isn’t the whole point of a container to style based on conditions (like, 98% of the time, being how wide it is)?
Well, not if the only effect we want from this is scoping! (!!!)
Components typically already have unique names.
Because components typically live in folders and folders have to have different names, components already have a forced uniqueness constraint.

Let’s just consider three. Here’s three design system (ds) components:
<ds-card><ds-article><ds-header>
Styles in Components
Each of them has styles that get bundled into global CSS:
- ds-card.css
- ds-article.css
- ds-header.css
We’re not talking shadow DOM and web components here, I’m talking very generally about any design system of components, regardless of framework.
Both a card and an article can very easily have a title. It’s entirely reasonable to write a class like:
/* ds-card.css */
.title {
background: rebeccapurple;
color: white;
}Code language: CSS (css)/* ds-article.css */
.title {
font-weight: 300;
letter-spacing: -0.01em;
}Code language: CSS (css)Just some contrived styles there. Those will overlap and both apply because of the identical class names in use.
Usually that’s not what we want. Usually we avoid this by just career-long muscle memory of knowing this and perhaps some BEM methodology or nesting.
ds-card {
.title {
/* Title styles unique to the card */
}
}Code language: CSS (css)
That’s artificial specificity boosting just to avoid future trouble. Not the end of the world, but not ideal.
It feels nicer not to think about it, which is what we get in a CSS modules approach. The styles can’t clash because they are programmatically randomized. And we don’t have to nest either, meaning we’re not bumping up specificity just for scoping.
Scoping Styles in Components
Let’s say we use the name of the component as the CSS container-name for every component.
ds-card {
container-name: ds-card;
}
ds-article {
container-name: ds-article;
}
ds-header {
container-name: ds-header;
}Code language: CSS (css)
Now in the stylesheet for each of those components (which is again, probably bundled and put into global scope like regular CSS).
@container ds-card {
}
@container ds-article {
}
@container ds-header {
}Code language: CSS (css)
Now I can do literally anything I want inside those @container blocks and it will not globally conflict.
@container ds-card {
.title {
background: rebeccapurple;
color: white;
}
}
@container ds-article {
.title {
font-weight: 300;
letter-spacing: -0.01em;
}
}
@container ds-header {
}Code language: CSS (css)
No conflicts there. Same class name, but scoped inside the relevant containers.
That’s it! That’s the scoping power we want.
And I’m fairly certain… no side effects. The WebKit blog post uses a container-type: inline-size, which would have side effects, but in my testing, that doesn’t seem necessary.
WELL ACTUALLY (to myself), we can do this with @scope too.
Rather than this @container stuff we just looked at…
ds-card {
container-name: ds-card;
}
@container ds-card {
button {
/* I'm safe! */
}
}Code language: CSS (css)We can do the same exact thing with @scope. (Credit: Miriam)
@scope (ds-card) {
button {
/* I'm safe */
}
}Code language: CSS (css)There’s really no difference here, except that we’re not explicitly naming the scope (which, for some reason, my brain likes), we’re leaning on a scoped selector. The selector could be whatever, like a specifically named attribute or something.
Demo
Name-only container styles I belive are only support in Safari 26.4+, so here’s hoping for broader support soon.
This is related to several other ideological approaches I’m already a fan of:
Pretty satisfying to see this evolve.
Let’s see Chrome & Firefox pick up these name-only containers, and let’s see Safari pick up import type assertions plz thx.


How are @container and @scope any different from the nesting you dislike?
How is this any better than:
It’s not dramatically different. It does transcend shadow roots, allow for donut scopes, and not require you to use an actual selector for the scope, so there are some differences.