Styling
By Syncfusion®, Inc. · Last updated
Scoped styles and how scoping works, styling child components, :global() and is:global, global stylesheets in a layout, CSS order, inline styles, define:vars, styling with props, CSS imports, Tailwind CSS, Sass, PostCSS, CSS Modules, bundling and inlineStylesheets.
Styling in Astro
- Astro uses plain CSS. You do not need to learn a new styling language.
- You can write CSS inside a component, in a separate file, or with tools like Tailwind CSS.
- By default, a component's CSS only styles that component.
- In this lesson, you will style Asha's site and learn when styles stay local and when they go global.
Simple lesson: CSS in an Astro component styles only that component, unless you ask for more.
A Real-World Example
- Asha's post cards have
h2titles. Her page also has anh2for "Contact". - She makes card titles purple with
h2 { color: purple; }insidePostCard.astro. - In plain HTML, that rule would turn every
h2on the page purple. - In Astro, only the card titles turn purple. The "Contact" heading stays black.
Press ▶ Run. Only the card heading is purple.
What happened:
- The
<style>tag is insidePostCard.astro. - Its
h2rule reached the card's heading, but not the page's "Contact" heading. - Open HTML sent to browser. The card's tags carry an extra attribute, such as
data-astro-cid-....
What You Will Learn
In this lesson, you will learn:
- How scoped styles work, and why they are safe.
- How to style a child component or slotted content.
- How to add global styles, and where.
- How CSS order decides which rule wins.
- How to use values from the script in CSS.
- How to import CSS files and npm CSS.
- How Tailwind CSS, Sass, PostCSS and CSS Modules fit in.
- How Astro bundles your CSS for the browser.
Scoped Styles
style Tags in Components
- Write a
<style>tag anywhere in a component's template. Most people put it at the end. - Write normal CSS inside it.
- Astro removes the tag from the HTML and puts the CSS in the page's stylesheet.
How Scoping Works
- Scoped style = a rule that applies only to the component it is written in.
- Astro adds a unique attribute, such as
data-astro-cid-abc123, to every tag in the component. - It also adds that attribute to every selector in the component's CSS.
- So
h2 { ... }becomesh2[data-astro-cid-abc123] { ... }. It can only match that component'sh2.
Animation: the rule h2 color purple gets a unique attribute added. It then matches only the h2 inside the card, not the h2 outside.
h2 color: purple;
h2[data-astro-cid-x1] ... Astro adds the component's ID
PostCard (has data-astro-cid-x1) Card title
Page (no x1 attribute) Contact
The rule gets the component's ID, so it only matches tags with that ID.
Scoped styles let you use short, simple selectors like h2 and p. They can never break another component.
Styling Child Components
- Scoped styles stop at a component's edge.
- A parent's
p { }rule does not reach the<p>inside a child component. - Styles for a child belong in the child.
- If the parent must decide a child's look, pass a prop or a
class(see below).
Using :global()
:global()turns one selector back into a normal, unscoped selector.- Common use: style the HTML that arrives through a
<slot />, or HTML fromset:html. - Keep the scoped part in front, so the rule stays inside the component:
.prose :global(a) { ... }.
Press ▶ Run. The link comes through the slot. Only :global() can style it.
- Only the link inside
.proseis orange. - Without
:global(), the rule would match nothing, because the link carries the page's ID.
Simple lesson: styles are scoped by default. Use :global() for one selector that must reach in.
Global Styles
is:global
<style is:global>turns off scoping for the whole tag.- Every rule in it styles the whole page, like a normal stylesheet.
- Use it rarely. Prefer a global CSS file.
A component with is:global styles changes every page it appears on. A rule like h1 { color: red } there can surprise you far away from the component.
Importing a Global Stylesheet
- Put site-wide CSS in a file, such as
src/styles/global.css. - Import it in a component's script:
import "../styles/global.css";. - Astro adds it to every page that uses that component.
Global Styles in a Layout
- The best place for the import is your base layout.
- Every page uses the layout, so every page gets the global CSS.
- Put fonts, colours, body spacing and basic link styles there.
CSS Order and the Cascade
- Cascade = the browser's rules for picking a winner when two CSS rules clash.
- A more specific selector wins.
h2[data-astro-cid-x1]is more specific thanh2. - So a component's scoped rule usually beats a global rule for the same tag.
- When two rules are equally specific, the one loaded later wins.
Press ▶ Run. The global file sets the body. The component's scoped h1 rule beats the global h1 rule.
Simple lesson: put global CSS in a file and import it in the base layout. Scoped rules usually win over global ones.
Dynamic Styles
Inline Styles
- You can still write
style="..."on a tag. - Astro also accepts an object:
style={{ color: accent, fontSize: "1.2rem" }}. - Use inline styles for one-off values. Use classes for anything repeated.
- The bar's width comes from
progress. Change it to90and run again. - In the object form, CSS names are written in camelCase:
borderRadius, notborder-radius.
define:vars in style
define:varspasses variables from the script into a<style>tag.- Write
<style define:vars={{ accent }}>. Inside, usevar(--accent). - Astro turns each variable into a CSS custom property on the component.
Styling with Props
- Combine props and
define:varsto let the parent choose a colour. - Or combine props and
class:listto switch between ready-made classes.
- Each badge gets its own
--colorvalue. sizepicks thesmallorlargeclass.
Simple lesson: define:vars sends script values into CSS. Props let the parent choose them.
CSS Imports and Tools
Importing CSS Files
import "../styles/global.css";in a script adds the file to the page.- Astro bundles it with the rest of your CSS.
Importing CSS from npm Packages
- Some packages ship CSS. Import it by its package path:
---
import "open-props/style";
---
Linking Stylesheets from public/
- A file in
public/can be linked with a normal tag:<link rel="stylesheet" href="/theme.css" />. - Astro does not process or shrink it. Use this only for files that must stay as they are.
Adding Tailwind CSS
- Tailwind CSS = a tool where you style with small classes, such as
text-xlandp-4. - Add it with one command:
npx astro add tailwind
- It installs Tailwind, adds its Vite plugin to the config and creates
src/styles/global.csswith@import "tailwindcss";. - Import that file in your layout. Then use classes:
<h1 class="text-3xl font-bold">.
Sass, Less and Stylus
- Sass = CSS with extra features, such as variables and nesting.
- Install it:
npm install sass. Then write<style lang="scss">. - Less and Stylus work the same way: install the package, then use
lang="less"orlang="styl".
PostCSS
- PostCSS = a tool that changes CSS with plugins, such as adding browser prefixes.
- Astro runs it already. Add a
postcss.config.cjsfile to add plugins.
CSS Modules
- CSS Module = a
.module.cssfile whose class names are made unique. - Import it as an object:
import styles from "./Card.module.css";. - Use it:
<div class={styles.card}>. - Most Astro projects do not need them, because
<style>is already scoped.
In this lab, .css imports and <style> tags work. Tailwind, Sass and CSS Modules need npm packages, so try them on your own computer.
Simple lesson: plain CSS covers most needs. Add Tailwind or Sass with one install when you want them.
Style Output
Bundling and Minification
- Bundling = joining many CSS pieces into a few files.
- Minification = removing spaces and comments so files are smaller.
astro builddoes both. Each page gets only the CSS of the components it uses.
Inlining Stylesheets
- Inline stylesheet = CSS placed inside a
<style>tag in the HTML, instead of a separate.cssfile. - Small CSS loads faster inline, because the browser makes no extra request.
build.inlineStylesheetsin the config decides:"auto"(the default) = inline small stylesheets, link big ones."always"= inline all of them."never"= always use separate.cssfiles.
Simple lesson: Astro bundles, shrinks and sends each page only the CSS it needs.
TL;DR
- Scoped style =
<style>in a component. Only styles that component. - How = Astro adds a
data-astro-cid-...attribute to tags and selectors. - :global(sel) = one unscoped selector. Use it for slotted or
set:htmlcontent. - is:global = the whole
<style>tag is unscoped. - Global CSS = a file imported in the base layout.
- Cascade = more specific wins. Scoped rules usually beat global ones.
- define:vars = script values as CSS variables.
Tools:
- Tailwind =
npx astro add tailwind, - Sass =
npm install sass+lang="scss", - CSS Modules =
*.module.css.
- Tailwind =
- inlineStylesheets =
auto,alwaysornever.
Common mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| Styling a child's tags from the parent | Parent CSS reaches everything | Style inside the child, or use a prop | Nothing changes |
Styling slotted HTML without :global() | Slot content has the component's ID | Use .wrapper :global(a) | The rule matches nothing |
Using is:global everywhere | Global is simpler | Use a global CSS file, and keep components scoped | Styles clash across the site |
| Global CSS imported on one page only | Imports affect every page | Import it in the base layout | Other pages look unstyled |
color: accent in CSS with define:vars | The variable name works as is | Write var(--accent) | The colour is ignored |
<link href="/src/styles/global.css"> | src files are served | Import src CSS in a script | The file is not found |
Check Yourself
Exercises
What to Remember
- A
<style>in a component is scoped to that component. - Use
:global()for slotted orset:htmlcontent. - Import global CSS in the base layout.
define:varsand props let the parent choose styles.- Tailwind and Sass are one install away. Astro bundles and shrinks all CSS.
Next: Client-Side Scripts, where Asha adds the first interactive features.