Styling in Astro
In React you reach for CSS Modules, styled-components, emotion, or Tailwind. You wire up global CSS through _app.tsx or a layout component. Class toggling means clsx(...) or a ternary on className.
Astro keeps the same CSS you already know — no new syntax to learn. What changes is where styles live and how they are scoped. A <style> block inside a .astro file is automatically scoped to that component by the compiler. Global CSS comes in through <style is:global> or a stylesheet import. And Tailwind works exactly as it does in Next, once you add the integration.
This module walks through each approach anchored to what you already know from React.
Module lessons
Section titled “Module lessons”| Lesson | What you will learn |
|---|---|
| Scoped Styles | <style> auto-scoped vs CSS Modules |
| Global Styles | is:global and stylesheet imports vs _app.tsx |
| CSS Variables and class:list | define:vars and class:list vs clsx / inline styles |
| Tailwind | Adding Tailwind to Astro vs Tailwind in Next |
A styled component at a glance
Section titled “A styled component at a glance”// Card.jsx (CSS Modules)import styles from './Card.module.css';import clsx from 'clsx';
export default function Card({ title, featured }) { return ( <div className={clsx(styles.card, featured && styles.featured)}> <h2 className={styles.title}>{title}</h2> </div> );}---// Card.astroconst { title, featured } = Astro.props;---<div class:list={["card", { featured }]}> <h2 class="title">{title}</h2></div>
<style> .card { border: 1px solid #e2e8f0; border-radius: 8px; padding: 1rem; } .title { font-size: 1.25rem; margin: 0; } .featured { border-color: #6366f1; background: #eef2ff; }</style>Notice what disappears: no CSS Module import, no clsx import, no .module.css file. The <style> block travels with the component and the compiler handles scoping automatically.
Runnable example
Section titled “Runnable example”---
const title = "Astro Styling Overview";
const featured = true;
---
<html lang="en">
<head><meta charset="utf-8" /><title>Styling</title></head>
<body>
<div class:list={["card", { featured }]}>
<h2 class="title">{title}</h2>
<p>Styles are scoped to this component automatically.</p>
</div>
</body>
</html>
<style>
body { font-family: sans-serif; padding: 2rem; background: #f8fafc; }
.card { border: 2px solid #e2e8f0; border-radius: 8px; padding: 1.5rem; max-width: 360px; }
.title { font-size: 1.4rem; margin: 0 0 .5rem; }
.featured { border-color: #6366f1; background: #eef2ff; }
</style>