komal.nakrani
Browse Themes
ThemesCategoriesDocsBlogTips & Tricks
Components & Islands••By Komal Nakrani

Fix: Missing Value for client:media Directive in Astro

Astro's 'Missing value for client:media directive' needs a media query, like client:media="(max-width: 768px)". Syntax, examples and when to use it instead of CSS.

#Astro#Errors#Client Directives

Astro shows “Missing value for client:media directive” when you write client:media without a media query. The directive hydrates a component only when a CSS media query matches, so it needs to know which query. Write it with parentheses, the same as in CSS: client:media="(max-width: 768px)". The full message reads: “Media query not provided for client:media directive.”

Key Takeaways

  • client:media always takes a CSS media query as its value.
  • Include the parentheses: "(max-width: 768px)", not "max-width: 768px".
  • It controls when JavaScript loads, not whether the HTML shows. Hide the HTML with CSS.
  • Typical use: a mobile-only menu drawer or a desktop-only widget.

The fix

---
import MobileMenu from '../components/MobileMenu.tsx';
---
<!-- Wrong -->
<MobileMenu client:media />

<!-- Right -->
<MobileMenu client:media="(max-width: 768px)" />

Any valid media query works:

<DesktopSearch client:media="(min-width: 1024px)" />
<AnimatedHero client:media="(prefers-reduced-motion: no-preference)" />

Hydration vs visibility

client:media only decides when the component’s JavaScript loads and runs. The server-rendered HTML is still in the page on every screen size. If the component should be invisible on desktop, hide it with CSS too:

<div class="mobile-only">
  <MobileMenu client:media="(max-width: 768px)" />
</div>

<style>
  @media (min-width: 769px) {
    .mobile-only { display: none; }
  }
</style>

Use the same breakpoint in both places. If the CSS hides at 769px but the directive hydrates up to 900px, tablets download JavaScript for a hidden component.

If the window is resized so the query starts matching, Astro hydrates the component then. It doesn’t un-hydrate when the query stops matching.

Keeping breakpoints in sync

Breakpoints defined in two places drift. Keep the query in one constant:

// src/data/breakpoints.ts
export const mobile = '(max-width: 768px)';
---
import { mobile } from '../data/breakpoints';
---
<MobileMenu client:media={mobile} />

Does it need a framework at all?

Mobile navigation is a common use, and it rarely needs React. A <button> that toggles aria-expanded and a hidden attribute, written in an Astro component <script>, works on every screen size with a few hundred bytes. The Astro components guide has the pattern, and lazy-loading islands compares client:media with client:visible and client:idle. For the CSS side of responsive layouts, see the Astro styling guide. The directives reference has the formal definition.

FAQ

Can I pass a variable to client:media?

Yes. client:media={query} with a string variable works, as shown above.

Does client:media work with Astro components?

No. Client directives only apply to framework components (React, Vue, Svelte, Solid, Preact). Astro components render on the server only.