# useMediaQuery Subscribes to window.matchMedia changes with SSR support. ## Import ```tsx import { useMediaQuery } from '@coinbase/cds-web/hooks/useMediaQuery' ``` ## API ### Parameters The `useMediaQuery` hook accepts a single parameter: - `query: string` - A CSS media query string to subscribe to. Can include: - **Viewport dimensions**: `(min-width: 768px)`, `(max-width: 767px)`, `(width: 1024px)` - **User preferences**: `(prefers-color-scheme: dark)`, `(prefers-reduced-motion: reduce)` - **Device features**: `(orientation: portrait)`, `(pointer: coarse)`, `(hover: hover)` - **Complex queries**: Combined with `and`, `not`, or `,` operators ### Returns Returns a `boolean` that indicates whether the media query matches: - `true` - The media query conditions are currently met - `false` - The media query conditions are not met - Automatically updates when the media query state changes - Uses MediaQueryProvider's default values during server-side rendering ## Examples ### Basic usage Use the `useMediaQuery` hook to call `window.matchMedia` with SSR support. It must be used within a MediaQueryProvider component. This hook is ideal for conditional rendering based on viewport size, user preferences, or other media features. It subscribes to a single state shared by all media queries to ensure Suspense works correctly. [See the MediaQueryProvider docs here →](/components/other/MediaQueryProvider) :::warning Do not use `useMediaQuery` for responsive styles. Use CSS media queries or [the `StyleProps` API](/getting-started/styling#responsive-styles) for responsive styles. ::: ```tsx live () => { const Page = () => { const isMobile = useMediaQuery('(max-width: 767px)'); const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); return ; }; const App = () => ( ); return ; }; ``` ### SSR support The `useMediaQuery` hook integrates with the MediaQueryProvider `defaultValues` to provide consistent behavior between server and client rendering. On the client the native `window.matchMedia` API is used. On the server the hook solves the `window.matchMedia` queries by comparing to the MediaQueryProvider `defaultValues`. The comparison against `defaultValues` during SSR is limited: it cannot solve highly complex media queries. If a complex query cannot be solved during SSR the hook will simply return `false`, and the query can still be solved by `window.matchMedia` on the client. :::tip You can populate the MediaQueryProvider `defaultValues` with user preferences, cookies, etc. to ensure the correct styles are applied on the server. ::: #### Simple queries that can be solved during SSR - Simple media queries - `width`, `min-width`, `max-width`, `height`, `min-height`, and `max-height` with pixel or em units - `prefers-contrast` and `prefers-color-scheme` - Logical `and` operator #### Complex queries that cannot be solved during SSR - Multiple comma-delimited values - Logical `not` and `or` operators - Mathematical `<=` and `>=` operators - Complex or nested queries - Other media types or features [See the MediaQueryProvider SSR docs here →](/components/other/MediaQueryProvider#ssr-support) ### Complex queries on the client Complex queries cannot be solved during SSR. They are solved on the client by calling `window.matchMedia`. ```tsx live () => { const isPortrait = useMediaQuery('(orientation: portrait)'); const isHighDPI = useMediaQuery('(min-resolution: 2dppx)'); const isTouch = useMediaQuery('(pointer: coarse)'); const isMediumHeight = useMediaQuery('(min-height: 600px) and (max-height: 900px)'); const complexQuery = useMediaQuery( `((width >= 1200px) and (orientation: landscape)), (width < 560px) or ((width > 768px) and (width < 900px))`, ); return ; }; ```