Skip to content

Scoped styles

A <style> block in a .stator file is scoped to that component — its rules can’t leak out or bleed in.

The compiler hashes the component and appends a data-s-<hash> attribute to every element it renders, then rewrites each selector’s subject to require that attribute:

/* you write */ .card { padding: 1rem }
/* compiles to */ .card[data-s-a1b2c3] { padding: 1rem }

Only the subject (the rightmost compound) is scoped, so descendant and combinator selectors keep working:

.card .title { … } .card .title[data-s-a1b2c3] { … }

Wrap a selector (or part of one) in :global(...) to opt out of scoping — useful for styling markup you don’t own:

:global(.prose a) { text-decoration: underline }

@keyframes names are scoped per-hash automatically, and animation / animation-name references are rewritten to match — so two components can both define @keyframes spin without collision.

Scoped rules match classes composed at runtime by class:list, since the scope attribute is on the element, not the class. A reactively-toggled class picks up its scoped rule exactly like a static one.