Scoped Styles

A `<style>` Block Only Affects This Component

Scoped Styles

By default, `<style>` in an `.astro` file is scoped to that file. Same class name in another file is a different rule.

3 min read Level 1/5 #astro#css#scoped
What you'll learn
  • Use scoped styles confidently
  • Understand how the scoping works
  • Reach beyond scope with `:global(...)`

A <style> block in an .astro file is scoped to that component by default. Astro adds a hash to your selectors and elements so they only match within this file.

What That Looks Like

---
// Card.astro
---
<section class="card">
  <slot />
</section>

<style>
  .card {
    border: 1px solid #ddd;
    padding: 1rem;
    border-radius: 8px;
  }
</style>

The output:

<section class="card astro-Hx7k">…</section>
<style>
  .card[data-astro-Hx7k] { /* ... */ }
</style>

The exact mechanism varies, but the effect is the same: .card in another component won’t match this rule.

Selector Reach

A scoped rule:

  • Matches direct elements of the component
  • Matches descendants written in the same component
  • Does NOT match elements rendered by a child component

If a child component has a <button> and you want the parent’s style to reach it, you have two options:

:global(...) for One Selector

<style>
  .card :global(button) {
    background: tomato;
  }
</style>

This styles any <button> inside an element with the parent’s .card class — including buttons inside child components.

Pass Through As a Class

Cleaner: have the child component accept a class prop and apply it. Then your parent styles the same class without leaking into unrelated components.

CSS Nesting

Modern CSS nesting works:

<style>
  .card {
    padding: 1rem;

    & h2 {
      margin-top: 0;
    }

    & .badge {
      background: yellow;
    }
  }
</style>

Up Next

When you want global rules.

Global Styles →