Components and layouts
Style an Astro component
Use scoped component styles by default and make global styling an explicit decision.
A <style> tag inside an Astro component is scoped to that component by default. The rules apply to the component’s own markup and nowhere else.
Here is a card:
<article class="card">
<slot />
</article>
<style>
.card {
border: 1px solid currentColor;
padding: 1rem;
}
</style>
Astro rewrites the selector at build time. It adds a data-astro-cid-… attribute to every element in the component, and the CSS becomes something like this:
.card[data-astro-cid-j7pv25f6] {
border: 1px solid currentColor;
padding: 1rem;
}
The hash is unique per component. Another component can use .card for something completely different and the two never collide. You get to name classes for what they mean, not for where they live.
Styling a child component
Scoping follows component boundaries, and this trips people up. A parent’s .card h2 rule does not reach an h2 inside a child component, because that h2 carries the child’s attribute, not the parent’s.
Don’t fight it with more specific selectors. Give the child a prop or a class it supports on purpose. Or, if the rule belongs to the whole site, make it global.
Global styles
For resets, fonts, design tokens, and typography, write a normal stylesheet and import it from the layout:
---
import '../styles/global.css'
---
Imported CSS is bundled and applied to every page that uses the layout. This is the right place for rules that are shared by design.
If you need one global rule inside a component, use :global():
.prose :global(a) {
text-decoration: underline;
}
Here .prose is still scoped, but a matches any link inside it, including links rendered by child components or by Markdown. Keep these escapes small. A component full of :global() is a global stylesheet with extra steps.
When a rule doesn’t apply
Open the element inspector in DevTools and look at the element. Does it have the data-astro-cid attribute your rule expects? If it doesn’t, the element belongs to a different component, and that’s why the scoped rule skipped it.
Do this once on purpose and the scoping model becomes obvious. Every time a style “doesn’t work” in Astro, this inspection is my first move.
Lesson completed