Styling & CSS

Astro was designed to make styling and writing CSS a breeze. Write your own CSS directly inside of an Astro component or import your favorite CSS library like Tailwind. Advanced styling languages like Sass and Less are also supported.

Styling an Astro component is as easy as adding a <style> tag to your component or page template. When you place a <style> tag inside of an Astro component, Astro will detect the CSS and handle your styles for you, automatically.

<style>
  h1 { color: red; }
</style>

Astro <style> CSS rules are automatically scoped by default. Scoped styles are compiled behind-the-scenes to only apply to HTML written inside of that same component. The CSS that you write inside of an Astro component is automatically encapsulated inside of that component.

<style>
-  h1 { color: red; }
+  h1.astro-HHNQFKH6 { color: red; }
-  .text { color: blue; }
+  .text.astro-HHNQFKH6 { color: blue; }
</style>

Scopes styles don’t leak and won’t impact the rest of your site. In Astro, it is okay to use low-specificity selectors like h1 {} or p {} because they will be compiled with scopes in the final output.

Scoped styles also won’t apply to other Astro components contained inside of your template. If you need to style a child component, consider wrapping that component in a <div> (or other element) that you can then style.

While we recommend scoped styles for most components, you may eventually find a valid reason to write global, unscoped CSS. You can opt-out of automatic CSS scoping with the <style is:global> attribute.

<style is:global>
  /* Unscoped, delivered as-is to the browser.
     Applies to all <h1> tags on your site. */
  h1 { color: red; }
</style>

You can also mix global & scoped CSS rules together in the same <style> tag using the :global() selector. This becomes a powerful pattern for applying CSS styles to children of your component.

<style>
  /* Scoped to this component, only. */
  h1 { color: red; }
  /* Mixed: Applies to child `h1` elements only. */
  article :global(h1) {
    color: blue;
  }
</style>
<h1>Title</h1>
<article><slot /></article>

This is a great way to style things like blog posts, or documents with CMS-powered content where the contents live outside of Astro. But be careful: components whose appearance differs based on whether or not they have a certain parent component can become difficult to troubleshoot.

Scoped styles should be used as often as possible. Global styles should be used only as-needed.

Added in: v0.21.0

The Astro <style> can reference any CSS variables available on the page. You can also pass CSS variables directly from your component front matter using the define:vars directive.

---
const foregroundColor = "rgb(221 243 228)";
const backgroundColor = "rgb(24 121 78)";
---
<style define:vars={{ foregroundColor, backgroundColor }}>
  h1 {
    background-color: var(--backgroundColor);
    color: var(--foregroundColor);
  }
</style>
<h1>Hello</h1>

📚 See our directives reference page to learn more about define:vars.

There are two ways to resolve external global stylesheets: an ESM import for files located within your project source, and an absolute URL link for files in your public/ directory, or hosted outside of your project.

📚 Read more about using static assets located in public/ or src/.

You can import stylesheets in your Astro component front matter using ESM import syntax. CSS imports work like any other ESM import in an Astro component, which should be referenced as relative to the component and must be written at the top of your component script, with any other imports.

---
// Astro will bundle and optimize this CSS for you automatically
// This also works for preprocessor files like .scss, .styl, etc.
import '../styles/utils.css';
---
<html><!-- Your page here --></html>

CSS import via ESM are supported inside of any JavaScript file, including JSX components like React & Preact. This can be useful for writing granular, per-component styles for your React components.

You can also use the <link> element to load a stylesheet on the page. This should be an absolute URL path to a CSS file located in your /public directory, or an URL to an external website. Relative <link> href values are not supported.

<head>
  <!-- Local: /public/styles/global.css -->
  <link rel="stylesheet" href="/styles/global.css" />
  <!-- External  -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.24.1/themes/prism-tomorrow.css">
</head>

Because this approach uses the public/ directory, it skips the normal CSS processing, bundling and optimizations that are provided by Astro. If you need these transformations, use the Import a Stylesheet method above.

Astro comes with support for adding popular CSS libraries, tools and frameworks to your project like Tailwind and more!

📚 See the Integrations Guide for instructions on installing, importing and configuring these integrations.

Astro supports CSS preprocessors such as Sass, Stylus, and Less through Vite.

npm install -D sass

Use <style lang="scss"> or <style lang="sass"> in .astro files

npm install -D stylus

Use <style lang="styl"> or <style lang="stylus"> in .astro files

npm install -D less

Use <style lang="less"> in .astro files.

You can also use all of the above CSS preprocessors within JS frameworks as well! Be sure to follow the patterns each framework recommends:

  • React / Preact: import Styles from './styles.module.scss';
  • Vue: <style lang="scss">
  • Svelte: <style lang="scss">

Astro comes with PostCSS included as part of Vite. To configure PostCSS for your project, create a postcss.config.js file in the project root. You can import plugins using require().

// ./postcss.config.js

module.exports = {
  plugins: [
    require('postcss-preset-env'),
    require('autoprefixer'),
  ],
};

.jsx files support both global CSS and CSS Modules. To enable the latter, use the .module.css extension (or .module.scss/.module.sass if using Sass).

import './global.css'; // include global CSS
import Styles from './styles.module.css'; // Use CSS Modules (must end in `.module.css`, `.module.scss`, or `.module.sass`!)

Vue in Astro supports the same methods as vue-loader does:

Svelte in Astro also works exactly as expected: Svelte Styling Docs.

⚠️WARNING⚠️: Be careful when bypassing Astro’s built-in CSS bundling! Styles won’t be automatically included in the built output, and it is your responsibility to make sure that the referenced file is properly included in the final page output.

For advanced use cases, CSS can be read directly from disk without being bundled or optimized by Astro. This can be useful when you need complete control over some snippet of CSS, and need to bypass Astro’s automatic CSS handling.

This is not recommended for most users.

---
// Advanced example! Not recommended for most users.
import rawStylesCSS from '../styles/main.css?raw';
---
<style is:inline set:html={rawStylesCSS}></style>

See Vite’s docs for full details.

For advanced use cases, you can import a direct URL reference for a CSS file inside of your project src/ directory. This can be useful when you need complete control over how a CSS file is loaded on the page. However, this will prevent the optimization of that CSS file with the rest of your page CSS .

This is not recommended for most users. Instead, place your CSS files inside of public/ to get a consistent URL reference.

⚠️WARNING⚠️: Importing a smaller CSS file with ?url may return the base64 encoded contents of the CSS file as a data URL, but only in your final build. You should either write your code to support encoded data URLs (data:text/css;base64,...) or set the vite.build.assetsInlineLimit config option to 0 to disable this feature.

---
// Advanced example! Not recommended for most users.
import stylesUrl from '../styles/main.css?url';
---
<link rel="preload" href={stylesUrl} as="style">
<link rel="stylesheet" href={stylesUrl}>

See Vite’s docs for full details.