client:load vs client:visible vs client:idle: Which to Use
Astro has five client directives. They decide when an island loads its JavaScript. Here is what each one does, plus a simple rule for picking.
Tested on Astro 7.4

In this guide
Every island carries a client directive. A directive is a short tag you add to the part. It answers one question. When should this part’s JavaScript load? JavaScript is the code that makes a page react to clicks. Astro gives you five answers.
The five directives
| Directive | Loads JavaScript | Use it for |
|---|---|---|
client:load |
Right away | Things you see at once that must work at once |
client:idle |
When the browser has a quiet moment | Things you see at once that can wait a beat |
client:visible |
When the part scrolls into view | Anything lower down the page |
client:media |
When a media query matches | Phone-only or desktop-only features |
client:only |
Right away, with no server rendering | Parts that can’t run on the server |
client:load
<BuyButton client:load />
The JavaScript loads as soon as the page does. Use it for the few things a visitor might touch in the first second. A search box in the header. A buy button.
client:idle
<ShowHideButton client:idle />
The JavaScript loads after the page has done its main work. It is a good default for something near the top that is not urgent. You can cap the wait. client:idle={{ timeout: 500 }} loads after 500 milliseconds, even if the page is still busy.
client:visible
<ImageCarousel client:visible />
The JavaScript loads only when the part scrolls into view. If the visitor never scrolls that far, it never loads. Use it for everything below the first screen. Want to start a little early? client:visible={{ rootMargin: "200px" }} loads when the part is within 200 pixels of the viewport. The viewport is the part of the page you can see.
client:media
<SidebarToggle client:media="(max-width: 50em)" />
The JavaScript loads only when the media query matches. A media query is a rule about screen size. The classic case is a phone menu button that does not exist on desktop.
client:only
<MapWidget client:only="react" />
The server skips this part. Only the browser draws it. You must name the framework. Use it for parts that need browser-only things. A map library that needs window is one case. Show something while it loads with a fallback:
<MapWidget client:only="react">
<p slot="fallback">Loading the map...</p>
</MapWidget>
A rule for picking
- Does it react to the visitor at all? If not, no directive.
- Is it in the first screen? Must it work at once?
client:load. - Is it in the first screen, but can wait a moment?
client:idle. - Is it further down?
client:visible. - Does it only exist at some screen sizes?
client:media. - Does it break on the server?
client:only.
Most islands end up as client:visible. Using client:load on everything throws away the speed you came to Astro for.
What we checked
We built a page with four counters on Astro 7.4. Each one used a different directive. Each came out as its own <astro-island> element. The directive was written on it. A part with no directive came out as plain HTML. Want to build one yourself? See how to add a React component to Astro.
Frequently asked questions
What happens with no client directive at all?
The component turns into plain HTML on the server. It sends no JavaScript. That is the right choice for anything that does not react to the visitor.
Can I use a client directive on an Astro component?
No. Client directives are for framework components, like React or Vue. For an Astro component, add a script tag instead.
Stuck on a step?
Check the common errors guide, look up a word in the glossary, or ask the friendly people in the official Astro and EmDash Discords. How to ask so people can help.
