Directives
Client Directives
Section titled “Client Directives”Control how framework components (React, Vue, Svelte, etc.) are hydrated on the client.
client:load
Section titled “client:load”Hydrate immediately on page load. Highest priority.
<InteractiveNav client:load />Use for: Navigation, modals, forms, anything above the fold.
client:idle
Section titled “client:idle”Hydrate once the page is done with initial load (uses requestIdleCallback).
<AnalyticsWidget client:idle />Use for: Low-priority UI that doesn’t need immediate interaction.
client:visible
Section titled “client:visible”Hydrate when the component enters the viewport (uses IntersectionObserver).
<ChartComponent client:visible />Use for: Below-the-fold content, lazy-loaded widgets.
Can customize the observer:
<HeavyComponent client:visible={{ rootMargin: "200px" }} />client:media
Section titled “client:media”Hydrate when a CSS media query matches.
<MobileMenu client:media="(max-width: 768px)" />Use for: Components only needed at certain viewport sizes.
client:only
Section titled “client:only”Skip server rendering. Render only on the client.
<BrowserOnlyChart client:only="react" />Must specify the framework: "react", "vue", "svelte", "solid-js", "lit", "preact"
Use for: Components using browser-only APIs (canvas, WebGL, localStorage at render time).
Server Directives
Section titled “Server Directives”server:defer
Section titled “server:defer”Defer component rendering to after initial page load. The page ships immediately with fallback content, then the component renders on the server and streams in.
<UserProfile server:defer> <LoadingSkeleton slot="fallback" /></UserProfile>Use for: Personalized content, slow data fetches, authenticated content.
Template Directives
Section titled “Template Directives”class:list
Section titled “class:list”Build class strings from arrays, objects, and values:
<div class:list={[ 'base-class', { active: isActive, hidden: !show }, conditionalClass && 'applied',]} />set:html
Section titled “set:html”Inject raw HTML (like innerHTML):
<div set:html={rawHtmlString} />set:text
Section titled “set:text”Set text content (safely escaped):
<p set:text={userInput} />is:global
Section titled “is:global”Make <style> apply globally instead of scoped:
<style is:global> body { margin: 0; } .prose h1 { font-size: 2rem; }</style>is:inline
Section titled “is:inline”Skip processing for script/style tags:
<!-- No bundling, no deduplication --><script is:inline> console.log('Runs as-is for each component instance');</script>
<style is:inline> /* Not scoped, not processed */</style>is:raw
Section titled “is:raw”Skip Astro template processing for child content:
<div is:raw> {/* This won't be treated as a JS expression */} <p>Rendered literally including {curly braces}</p></div>define:vars
Section titled “define:vars”Pass component variables to <script> or <style> tags:
---const textColor = 'navy';const message = 'Hello';---
<style define:vars={{ textColor }}> h1 { color: var(--textColor); }</style>
<script define:vars={{ message }}> console.log(message); // 'Hello'</script>Transition Directives
Section titled “Transition Directives”Used with View Transitions.
transition:name
Section titled “transition:name”Unique identifier for animating between pages:
<h1 transition:name="page-title">{title}</h1><img transition:name={`hero-${id}`} src={image} />transition:animate
Section titled “transition:animate”Override the default animation:
<div transition:animate="slide">Slides in</div><div transition:animate="fade">Fades in</div><div transition:animate="none">No animation</div>transition:persist
Section titled “transition:persist”Keep a component alive across page navigations (no re-render):
<AudioPlayer transition:persist /><video transition:persist />