Skip to main content
Template directives are a special kind of HTML attribute available inside of any Astro component template (.astro files), and some can also be used in .mdx files. Template directives are used to control an element or component’s behavior in some way. A directive could enable some compiler feature that makes your life easier (like using class:list instead of class), or a directive could tell the Astro compiler to do something special with that component (like hydrating with client:load).

Rules

For a template directive to be valid, it must:
  • Include a colon : in its name, using the form X:Y (ex: client:load)
  • Be visible to the compiler (ex: <X {...attr}> would not work if attr contained a directive)
Some template directives can take a custom value:
  • <X client:load /> (takes no value)
  • <X class:list={['some-css-class']} /> (takes an array)
A template directive is never included directly in the final HTML output of a component.

Common Directives

class:list

class:list
Array<string | object | Array>
Takes an array of class values and converts them into a class string. Powered by the clsx library.
Accepted value types:
  • string - Added to the element class
  • Object - All truthy keys are added to the element class
  • Array - Flattened
  • false, null, or undefined - Skipped
<!-- This -->
<span class:list={[ 'hello goodbye', { world: true }, [ 'friend' ] ]} />
<!-- Becomes -->
<span class="hello goodbye world friend"></span>

set:html

set:html
string | Promise<string> | Promise<Response>
Injects an HTML string into an element, similar to setting el.innerHTML.
The value is not automatically escaped by Astro. Be sure that you trust the value, or that you have escaped it manually before passing it to the template. Forgetting to do this will open you up to Cross Site Scripting (XSS) attacks.
---
const rawHTMLString = "Hello <strong>World</strong>"
---
<h1>{rawHTMLString}</h1>
  <!-- Output: <h1>Hello &lt;strong&gt;World&lt;/strong&gt;</h1> -->
<h1 set:html={rawHTMLString} />
  <!-- Output: <h1>Hello <strong>World</strong></h1> -->
You can also use set:html on a <Fragment> to avoid adding an unnecessary wrapper element:
---
const cmsContent = await fetchHTMLFromMyCMS();
---
<Fragment set:html={cmsContent}>
set:html={Promise<string>} injects an HTML string wrapped in a Promise:
---
import api from '../db/api.js';
---
<article set:html={api.getArticle(Astro.props.id)}></article>
set:html={Promise<Response>} injects a Response:
<article set:html={fetch('http://example/old-posts/making-soup.html')}></article>
set:html can be used on any tag, including <script> tags for JSON-LD schemas:
<script type="application/ld+json" set:html={JSON.stringify({
  "@context": "https://schema.org/",
  "@type": "Person",
  name: "Houston",
  hasOccupation: {
    "@type": "Occupation",
    name: "Astronaut"
  }
})}/>

set:text

set:text
string
Injects a text string into an element, similar to setting el.innerText. The value is automatically escaped by Astro.
This is equivalent to just passing a variable into a template expression directly (ex: <div>{someText}</div>) and therefore this directive is not commonly used.

Client Directives

These directives control how UI Framework components are hydrated on the page. By default, a UI Framework component is not hydrated in the client. If no client:* directive is provided, its HTML is rendered onto the page without JavaScript.

client:load

client:load
directive
Load and hydrate the component JavaScript immediately on page load.
Priority: High
Useful for: Immediately-visible UI elements that need to be interactive as soon as possible.
<BuyButton client:load />

client:idle

client:idle
directive | object
Load and hydrate the component JavaScript once the page is done with its initial load and the requestIdleCallback event has fired.
Priority: Medium
Useful for: Lower-priority UI elements that don’t need to be immediately interactive.
<ShowHideButton client:idle />
Optional timeout parameter:
<ShowHideButton client:idle={{timeout: 500}} />
timeout
number
The maximum time to wait (in milliseconds) before hydrating the component, even if the page is not yet done with its initial load.

client:visible

client:visible
directive | object
Load and hydrate the component JavaScript once the component has entered the user’s viewport. Uses an IntersectionObserver internally.
Priority: Low
Useful for: Low-priority UI elements that are far down the page or so resource-intensive to load that you would prefer not to load them at all if the user never saw the element.
<HeavyImageCarousel client:visible />
Optional rootMargin parameter:
<HeavyImageCarousel client:visible={{rootMargin: "200px"}} />
rootMargin
string
A margin (in pixels) around the component. When specified, the component will hydrate when this margin enters the viewport, rather than the component itself.

client:media

client:media
string
Load and hydrate the component JavaScript once a certain CSS media query is met.
Priority: Low
Useful for: Sidebar toggles, or other elements that might only be visible on certain screen sizes.
<SidebarToggle client:media="(max-width: 50em)" />

client:only

client:only
string
Skips HTML server rendering and renders only on the client. Requires the component’s framework as a value.
<SomeReactComponent client:only="react" />
<SomePreactComponent client:only="preact" />
<SomeSvelteComponent client:only="svelte" />
<SomeVueComponent client:only="vue" />
<SomeSolidComponent client:only="solid-js" />

Display loading content

For components that render only on the client, you can display fallback content while they are loading:
<ClientComponent client:only="vue">
  <div slot="fallback">Loading...</div>
</ClientComponent>

Server Directives

These directives control how server island components are rendered.

server:defer

server:defer
directive
Transforms the component into a server island, causing it to be rendered on demand, outside the scope of the rest of the page rendering.
<Avatar server:defer />

Script & Style Directives

These directives can only be used on HTML <script> and <style> tags.

is:global

is:global
directive
Makes the contents of a <style> tag apply globally on the page. Disables Astro’s CSS scoping system.
<style is:global>
  body a { color: red; }
</style>

is:inline

is:inline
directive
Tells Astro to leave the <script> or <style> tag as-is in the final output HTML. The contents will not be processed, optimized, or bundled.
<style is:inline>
  /* inline: relative & npm package imports are not supported. */
  @import '/assets/some-public-styles.css';
  span { color: green; }
</style>

<script is:inline>
  /* inline: relative & npm package imports are not supported. */
  console.log('I am inlined right here in the final output HTML.');
</script>
The is:inline directive is implied whenever any attribute other than src is used on a <script> or <style> tag. The one exception is using the define:vars directive on the <style> tag.

define:vars

define:vars
object
Passes server-side variables from your component frontmatter into client <script> or <style> tags. Any JSON-serializable frontmatter variable is supported.
---
const foregroundColor = "rgb(221 243 228)";
const backgroundColor = "rgb(24 121 78)";
const message = "Astro is awesome!";
---
<style define:vars={{ textColor: foregroundColor, backgroundColor }}>
  h1 {
    background-color: var(--backgroundColor);
    color: var(--textColor);
  }
</style>

<script define:vars={{ message }}>
  alert(message);
</script>
Using define:vars on a <script> tag implies the is:inline directive, which means your scripts won’t be bundled and will be inlined directly into the HTML.

Advanced Directives

is:raw

is:raw
directive
Instructs the Astro compiler to treat any children of that element as text, ignoring all special Astro templating syntax.
---
import Katex from '../components/Katex.astro';
---
<Katex is:raw>Some conflicting {syntax} here</Katex>