Scoping Styles
Prerequisites: Cascade layers
Global CSS means any rule can affect any element. Several techniques scope styles to part of the page.
@scope
@scope (.card) to (.card-content) {
:scope { border: 1px solid #ddd; }
img { border-radius: 8px; }
a { color: inherit; }
}
- Rules apply only to elements inside
.card— the scope root (:scopeselects the root itself). to (.card-content)sets a lower boundary: elements inside.card-contentaren't affected. This is "donut scope" — style a component's frame without touching the content slotted inside it.- Selectors inside keep low specificity (
imgstays 0,0,1).
Scope proximity
When two scoped rules conflict with equal specificity, the one whose scope root is closer in the DOM wins — before source order is considered:
<style>
@scope (.light) { p { color: rgb(0, 0, 0); } }
@scope (.dark) { p { color: rgb(255, 255, 255); } }
</style>
<div class="dark">
<div class="light"><p id="inner">Inner</p></div>
<p id="outer">Outer</p>
</div>
<script>
for (const id of ["inner", "outer"]) {
console.log(id, getComputedStyle(document.getElementById(id)).color);
}
</script>
inner rgb(0, 0, 0)
outer rgb(255, 255, 255)
The inner paragraph is black although the .dark rule comes later: the
.light root is nearer. With plain descendant selectors
(.dark p vs .light p), source order would have made it white.
@scope works in all major browsers (Chrome and Edge 118, Safari 17.4,
Firefox 146).
Other scoping techniques
| Technique | How it scopes |
|---|---|
| Naming conventions (BEM) | Unique class names by convention (next lessons) |
| CSS Modules | The build tool rewrites class names to be unique per file |
| Framework scoped styles | Vue <style scoped>, Svelte, Angular add attributes to selectors |
| Shadow DOM | True encapsulation for web components — outside styles don't match inside |
| Utility classes | Styles live on the element, so nothing leaks |
Styling inside shadow DOM
From inside a component, :host, :host(.variant), and ::slotted()
style the host and slotted children. From outside, ::part(name) and
custom properties are the only ways in — design components to expose
tokens like --button-bg for theming. See the HTML
course's web components lessons.