Media queries in React for responsive design with hook and component APIs
—
The Component API provides declarative conditional rendering using React components. This is ideal for showing/hiding UI elements based on media queries with clean JSX syntax.
React functional component for conditional rendering based on media queries. Supports both direct children and render prop patterns.
/**
* React component for conditional rendering based on media queries
*/
const MediaQuery: FC<MediaQueryProps>;
interface MediaQueryProps extends MediaQueryAllQueryable {
/** React component to render when media query matches */
component?: ReactNode;
/** Content to render - can be ReactNode or render function */
children?: ReactNode | ((matches: boolean) => ReactNode);
/** Raw CSS media query string */
query?: string;
/** CSS styles to apply to the wrapper element */
style?: CSSProperties;
/** CSS class name to apply to the wrapper element */
className?: string;
/** Device property overrides for SSR/testing */
device?: MediaQueryMatchers;
/** Alias for device prop (deprecated) */
values?: Partial<MediaQueryMatchers>;
/** Callback fired before media query match state changes */
onBeforeChange?: (matches: boolean) => void;
/** Callback fired when media query match state changes */
onChange?: (matches: boolean) => void;
}Props:
MediaQueryAllQueryable (width, height, orientation, etc.)component?: React component to render when media query matcheschildren?: Content to render, either as ReactNode or render function (matches: boolean) => ReactNodequery?: Raw CSS media query string (alternative to property-based queries)style?: CSS styles applied to wrapper elementclassName?: CSS class name applied to wrapper elementdevice?: Device property overrides for server-side rendering or testingvalues?: Deprecated alias for device proponBeforeChange?: Callback fired before match state changesonChange?: Callback fired when match state changesUsage Examples:
import React from "react";
import MediaQuery from "react-responsive";
// Basic conditional rendering
const BasicExample = () => (
<div>
<MediaQuery minWidth={1224}>
<p>This content shows on desktop screens (≥1224px)</p>
</MediaQuery>
<MediaQuery maxWidth={768}>
<p>This content shows on mobile screens (≤768px)</p>
</MediaQuery>
</div>
);
// Using render prop pattern
const RenderPropExample = () => (
<div>
<MediaQuery minWidth={768}>
{(matches) =>
matches ? (
<p>Desktop/Tablet view</p>
) : (
<p>Mobile view</p>
)
}
</MediaQuery>
<MediaQuery orientation="landscape">
{(isLandscape) => (
<div className={isLandscape ? "landscape" : "portrait"}>
<p>Orientation: {isLandscape ? "Landscape" : "Portrait"}</p>
</div>
)}
</MediaQuery>
</div>
);
// Using CSS query strings
const QueryStringExample = () => (
<div>
<MediaQuery query="(min-resolution: 2dppx)">
<img src="high-res-image.png" alt="High DPI image" />
</MediaQuery>
<MediaQuery query="(max-width: 767px) and (orientation: portrait)">
<p>Mobile portrait mode</p>
</MediaQuery>
</div>
);
// Nested media queries
const NestedExample = () => (
<div>
<MediaQuery minWidth={1224}>
<p>Desktop content</p>
<MediaQuery minWidth={1824}>
<p>Large desktop additional content</p>
</MediaQuery>
</MediaQuery>
</div>
);
// With styling and classes
const StyledExample = () => (
<div>
<MediaQuery
minWidth={768}
style={{ backgroundColor: "lightblue", padding: "1rem" }}
className="desktop-container"
>
<p>Styled desktop content</p>
</MediaQuery>
</div>
);
// With device overrides for SSR
const SSRExample = () => (
<MediaQuery minWidth={1224} device={{ width: 1400 }}>
<p>This will render on server with forced desktop width</p>
</MediaQuery>
);Responsive Layout Components:
import MediaQuery from "react-responsive";
// Create reusable responsive layout components
const Desktop = ({ children }: { children: React.ReactNode }) => (
<MediaQuery minWidth={992}>
{children}
</MediaQuery>
);
const Tablet = ({ children }: { children: React.ReactNode }) => (
<MediaQuery minWidth={768} maxWidth={991}>
{children}
</MediaQuery>
);
const Mobile = ({ children }: { children: React.ReactNode }) => (
<MediaQuery maxWidth={767}>
{children}
</MediaQuery>
);
// Usage
const ResponsiveLayout = () => (
<div>
<Desktop>
<div className="desktop-layout">Desktop Layout</div>
</Desktop>
<Tablet>
<div className="tablet-layout">Tablet Layout</div>
</Tablet>
<Mobile>
<div className="mobile-layout">Mobile Layout</div>
</Mobile>
</div>
);Conditional Component Rendering:
const ConditionalComponents = () => (
<div>
{/* Show different navigation components based on screen size */}
<MediaQuery minWidth={768}>
<DesktopNavigation />
</MediaQuery>
<MediaQuery maxWidth={767}>
<MobileNavigation />
</MediaQuery>
{/* Show different image sizes based on resolution */}
<MediaQuery minResolution="2dppx">
<img src="image@2x.jpg" alt="High DPI" />
</MediaQuery>
<MediaQuery maxResolution="1dppx">
<img src="image.jpg" alt="Standard DPI" />
</MediaQuery>
</div>
);Interactive Media Query Components:
const InteractiveExample = () => {
const [showDetails, setShowDetails] = useState(false);
return (
<div>
<MediaQuery minWidth={768}>
{(isDesktop) => (
<div>
<h2>Product Information</h2>
{isDesktop && <button onClick={() => setShowDetails(!showDetails)}>
{showDetails ? "Hide" : "Show"} Details
</button>}
{(showDetails || !isDesktop) && (
<div className="product-details">
<p>Detailed product information...</p>
</div>
)}
</div>
)}
</MediaQuery>
</div>
);
};Change Detection:
const ChangeDetectionExample = () => {
const [matchHistory, setMatchHistory] = useState<string[]>([]);
const handleMediaQueryChange = (matches: boolean) => {
const timestamp = new Date().toLocaleTimeString();
setMatchHistory(prev => [
...prev,
`${timestamp}: Desktop ${matches ? "matched" : "unmatched"}`
]);
};
return (
<div>
<MediaQuery
minWidth={1024}
onChange={handleMediaQueryChange}
onBeforeChange={(matches) => {
console.log("About to change to:", matches);
}}
>
<p>Desktop content with change tracking</p>
</MediaQuery>
<div>
<h3>Match History:</h3>
{matchHistory.map((entry, index) => (
<p key={index}>{entry}</p>
))}
</div>
</div>
);
};import { ReactNode, CSSProperties, FC } from "react";
interface MediaQueryProps extends MediaQueryAllQueryable {
component?: ReactNode;
children?: ReactNode | ((matches: boolean) => ReactNode);
query?: string;
style?: CSSProperties;
className?: string;
device?: MediaQueryMatchers;
values?: Partial<MediaQueryMatchers>;
onBeforeChange?: (matches: boolean) => void;
onChange?: (matches: boolean) => void;
}
const MediaQuery: FC<MediaQueryProps>;Install with Tessl CLI
npx tessl i tessl/npm-react-responsive