# Astro Client-Side Component Directives: load, visible, media, idle, and only Compared

> Understand Astro client directives load visible media idle and only. Learn how to control framework component hydration for optimal performance and user experience in your web applications.

- Repository: [Astro/astro](https://github.com/withastro/astro)
- Tags: deep-dive
- Published: 2026-03-06

---

**Astro's `client:` directives control precisely when framework components hydrate on the browser, ranging from immediate page-load execution to conditional triggers based on viewport visibility, CSS media queries, browser idle time, or skipping server-side rendering entirely.**

Astro's island architecture ships zero JavaScript by default, requiring you to explicitly opt-in to client-side interactivity using hydration directives. In the withastro/astro source code, these strategies are defined in [`packages/astro/src/types/public/elements.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/types/public/elements.ts) and implemented through the server-side directive extraction logic in [`packages/astro/src/runtime/server/hydration.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/runtime/server/hydration.ts).

## client:load: Immediate Page-Load Hydration

**`client:load`** hydrates the component immediately after the page's JavaScript bundle executes.

The directive is defined in [`packages/astro/src/types/public/elements.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/types/public/elements.ts) as part of the `AstroClientDirectives` interface. During SSR, the `extractDirectives` function in [`packages/astro/src/runtime/server/hydration.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/runtime/server/hydration.ts) records the directive name (`load`) and its value (always `true`). The client build generates an entry point that calls the renderer's hydrate function instantly upon bundle load, ensuring the component is interactive as soon as possible.

Use this for critical UI requiring immediate interactivity, such as navigation menus or carousels that must animate right away.

```astro
<Counter client:load />

```

## client:visible: Viewport-Triggered Hydration

**`client:visible`** uses an `IntersectionObserver` to import and hydrate the component only when it enters the browser viewport.

The directive accepts an optional configuration object via the `ClientVisibleOptions` type, allowing you to specify a `rootMargin`. During SSR, `extractDirectives` stores the directive name (`visible`) and any provided options. The renderer emits client code that registers the `IntersectionObserver` and lazily loads the component when the element becomes visible.

This is ideal for below-the-fold content like "related posts" widgets or heavy charts that aren't needed until the user scrolls to them. It reduces initial bundle size and improves First Contentful Paint.

```astro
<HeavyChart client:visible="{ rootMargin: '200px' }" />

```

## client:media: Media Query-Conditional Hydration

**`client:media`** hydrates the component only when the specified CSS media query evaluates to true in the browser, using `matchMedia`.

Defined as `'client:media'?: string` in `AstroClientDirectives`, this directive requires a string argument containing the media query. In `extractDirectives`, Astro validates that the value is a string; otherwise it throws the `MissingMediaQueryDirective` error defined in [`packages/astro/src/core/errors/errors-data.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/errors/errors-data.ts). The generated client code registers a listener to conditionally import the component when the query matches.

Use this for responsive UI patterns like sidebars that should only load on desktop screens, or for respecting `prefers-reduced-motion` without shipping unnecessary code to all users.

```astro
<Sidebar client:media="(min-width: 1024px)" />

```

## client:idle: Idle-Time Hydration

**`client:idle`** defers hydration until the browser's main thread is idle using `requestIdleCallback` (with a polyfill fallback).

Declared as `'client:idle'?: IdleRequestOptions | boolean` in [`packages/astro/src/types/public/elements.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/types/public/elements.ts), this directive accepts either a boolean or an options object to customize the timeout. The `extractDirectives` function captures these options, and the renderer wraps the component import in a `requestIdleCallback` call, respecting any user-provided timeout settings.

Use this for non-essential UI that can wait until critical work completes, such as newsletter signup forms or chat widgets. This keeps the critical path short and improves perceived performance.

```astro
<NewsletterForm client:idle="{ timeout: 2000 }" />

```

## client:only: Client-Exclusive Rendering

**`client:only`** skips server-side rendering entirely, emitting only a placeholder comment (`<!--client-only-->`) and hydrating exclusively on the client.

Because Astro cannot infer the correct renderer without SSR, this directive requires a framework hint string (e.g., `"react"`, `"vue"`, `"svelte"`). Defined as `'client:only'?: boolean | string` in [`packages/astro/src/types/public/elements.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/types/public/elements.ts), the directive triggers the `NoClientEntrypoint` error from [`packages/astro/src/core/errors/errors-data.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/errors/errors-data.ts) if the hint is missing. During SSR, `extractDirectives` records the directive but does not attempt to render the component.

Use this for components relying on browser-only APIs like `window`, `document`, or WebGL that would error during SSR, or when minimizing server bundle size is prioritized over immediate interactivity.

```astro
<Map client:only="leaflet" />

```

## How Astro Processes Hydration Directives Internally

The hydration strategy follows a consistent pipeline across all directives:

1. **Parsing**: The compiler identifies props starting with `client:` and captures them via `extractDirectives` in [`packages/astro/src/runtime/server/hydration.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/runtime/server/hydration.ts).
2. **Validation**: Directive names are checked against the supported set from active renderers; invalid names raise hydration errors.
3. **SSR Handling**: For `client:load`, `visible`, `media`, and `idle`, Astro renders static markup as a placeholder. For `client:only`, only a placeholder comment is emitted.
4. **Client Build**: The renderer generates a client entry point implementing the specific loading strategy (eager import, `IntersectionObserver`, `matchMedia`, `requestIdleCallback`, or direct import).
5. **Runtime**: The browser executes the appropriate strategy based on the recorded directive and its value.

## Summary

- **`client:load`**: Hydrates immediately when the page JavaScript loads. Use for critical interactive UI.
- **`client:visible`**: Hydrates when the component enters the viewport via `IntersectionObserver`. Use for scroll-triggered content.
- **`client:media`**: Hydrates only when a CSS media query matches via `matchMedia`. Use for responsive, conditional UI.
- **`client:idle`**: Hydrates when the main thread is idle via `requestIdleCallback`. Use for non-essential, low-priority components.
- **`client:only`**: Skips SSR entirely and hydrates only on the client with a required framework hint. Use for browser-only APIs.

## Frequently Asked Questions

### What is the difference between client:load and client:idle?

**`client:load`** imports and hydrates the component immediately after the page's JavaScript bundle executes, potentially blocking the main thread. **`client:idle`** uses `requestIdleCallback` to defer hydration until the browser has completed more critical work, making it better for non-essential components that don't require immediate interactivity.

### When should I use client:only instead of client:load?

Use **`client:only`** when your component depends on browser-only globals like `window` or `document` that would cause errors during server-side rendering, or when you want to eliminate the component from the server bundle entirely. Use **`client:load`** when you need the component to hydrate immediately but still require its static markup during SSR for SEO or initial paint.

### Can I use multiple client directives on the same component?

No, Astro does not support combining multiple `client:` directives on a single component. Each directive represents a distinct hydration strategy, and you must choose the one that best fits your component's loading requirements. If you need complex conditional logic, handle it inside the component after initial hydration.

### How does client:visible improve page performance?

**`client:visible`** improves performance by preventing the browser from downloading and executing a component's JavaScript until the user actually scrolls to it. This reduces initial bundle size, improves First Contentful Paint, and conserves bandwidth for below-the-fold content that may never be viewed.