useMediaQuery React hook in TypeScript
v1.0.0Added in 1.0.0
A React useMediaQuery hook that is SSR-safe, plus hooks for phone widths, touch screens and the current Tailwind breakpoint.
Resize the window, switch to the phone frame or change your system settings: the readout follows along live. Type any media query into the playground to test it.
useMediaQuery is a free React hook in the React hooks and utilities category, written in TypeScript for React 19. It installs as source with npx wingo-ui@latest add use-media-query.
Add to a project
Requirements: React 19, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add use-media-queryUsage
Import useMediaQuery from @/hooks/use-media-query.
import { useBreakpoint, useIsMobile, useIsTouch, useMediaQuery } from "@/hooks/use-media-query"
export function PhotoGrid({ photos }: { photos: string[] }) {
const isMobile = useIsMobile()
const isTouch = useIsTouch()
const breakpoint = useBreakpoint()
const landscape = useMediaQuery("(orientation: landscape)")
const columns = isMobile ? (landscape ? 3 : 2) : breakpoint === "2xl" ? 5 : 4
return (
<ul className="grid gap-2" style={{ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` }}>
{photos.map((src) => (
// touch screens have no hover, so the caption is always visible there
<li key={src} className="group relative">
<img src={src} alt="" className="aspect-square w-full rounded-xl object-cover" />
<span className={isTouch ? "absolute bottom-2 left-2" : "absolute bottom-2 left-2 opacity-0 group-hover:opacity-100"}>View</span>
</li>
))}
</ul>
)
}API
query*default"(min-width: 1024px)"stringuseMediaQuery(query, serverFallback?): any CSS media query. Returns true while it matches and re-renders when that flips.
serverFallbackdefaultfalsebooleanWhat useMediaQuery returns on the server and during hydration, before the browser can answer. Pick the value your server layout assumes.
returnsbooleanWhether the query matches right now; serverFallback until the component has hydrated.
Parts
useIsMobile
hookTrue below 768px (Tailwind md). The switch point where popovers, selects and menus become bottom sheets. Signature: () => boolean.
useIsTouch
hookTrue when the primary pointer is coarse (a finger). Use it for 44px targets and to skip hover-only affordances. Signature: () => boolean.
useBreakpoint
hookThe widest Tailwind breakpoint that matches, with one subscription for all of them. Signature: (serverFallback?: Breakpoint) => "base" | "sm" | "md" | "lg" | "xl" | "2xl".
matchesMedia
functionThe same check outside render, for event handlers and effects. False on the server. Signature: (query: string) => boolean.
useIsApple
hookWhether the device is a Mac, iPhone or iPad, for shortcut notation (⌘K vs Ctrl+K) and for binding mod to the meta key. The hook is false on the server and during hydration. Signature: () => boolean.
isApple
functionThe same check as useIsApple outside render, for event handlers that bind mod to the meta key. False on the server. Signature: () => boolean.
BREAKPOINTS
constantThe Tailwind breakpoint widths in px: sm 640, md 768, lg 1024, xl 1280, 2xl 1536. useBreakpoint reads them.
MOBILE_QUERY
constant"(max-width: 767.98px)", what useIsMobile watches: below Tailwind md, where overlays become bottom sheets.
TOUCH_QUERY
constant"(pointer: coarse)", what useIsTouch watches: the primary pointer is a finger.
HOVER_QUERY
constant"(hover: hover) and (pointer: fine)": a mouse or trackpad that can hover, for hover-only effects.
REDUCED_MOTION_QUERY
constant"(prefers-reduced-motion: reduce)": the system asks for less motion.
DARK_SCHEME_QUERY
constant"(prefers-color-scheme: dark)": the system theme is dark.
Breakpoint
typeWhat useBreakpoint returns: "base" | "sm" | "md" | "lg" | "xl" | "2xl".
Examples
Responsive columns
useBreakpoint picks how many listing cards fit per row.
Sheet or popover
useIsMobile and useIsTouch decide how overlays and row actions behave.
Any media query
useMediaQuery with a custom query and a server fallback.
Dependencies
No dependencies beyond React.
Files
- hooks/use-media-query.ts
FAQ
Is the useMediaQuery hook free?
Yes. The source is free and needs no account: copy it from the Code tab or install it with the CLI.
How do I install useMediaQuery?
Run npx wingo-ui@latest add use-media-query. With shadcn, run npx shadcn@latest add https://wingo-ui.com/r/use-media-query.json.
See also
Used in
More React hooks and utilities
Articles using this component
- Minimum Touch Target Size: WCAG, iOS, Android and Tailwind
Mobile UI in React11 min read
- React Use Mobile Hook: SSR-Safe, No Hydration Mismatch
Next.js and Tailwind CSS9 min read
- Shadcn Responsive Dialog: Card on Desktop, Sheet on Phones
Mobile UI in React10 min read