Skip to content

useMediaQuery

This is a CSS media query hook for React. It listens for matches to a CSS media query. It allows the rendering of components based on whether the query matches or not.

Some of the key features:

  • โš›๏ธ It has an idiomatic React API.
  • ๐Ÿš€ It's performant, it observes the document to detect when its media queries change, instead of polling the values periodically.
  • ๐Ÿ“ฆ 1 kB gzipped.
  • ๐Ÿ’„ It's an alternative to react-responsive and react-media that aims for simplicity.
  • ๐Ÿค– It supports Server-side rendering.

Simple media query

You should provide a media query to the first argument of the hook. The media query string can by any valid CSS media query, e.g. 'print'.

import React from 'react';
import useMediaQuery from '@material-ui/core/useMediaQuery';

export default function SimpleMediaQuery() {
  const matches = useMediaQuery('(min-width:600px)');

  return <span>{`(min-width:600px) matches: ${matches}`}</span>;
}
(min-width:600px) matches: false

Using Material-UI's breakpoint helpers

You can use Material-UI's breakpoint helpers as follows:

import { useTheme } from '@material-ui/core/styles';
import useMediaQuery from '@material-ui/core/useMediaQuery';

function MyComponent() {
  const theme = useTheme();
  const matches = useMediaQuery(theme.breakpoints.up('sm'));

  return <span>{`theme.breakpoints.up('sm') matches: ${matches}`}</span>;
}
theme.breakpoints.up('sm') matches: false

Using JavaScript syntax

json2mq is used to generate media query string from a JavaScript object.

import React from 'react';
import json2mq from 'json2mq';
import useMediaQuery from '@material-ui/core/useMediaQuery';

export default function JavaScriptMedia() {
  const matches = useMediaQuery(
    json2mq({
      minWidth: 600,
    }),
  );

  return <span>{`{ minWidth: 600 } matches: ${matches}`}</span>;
}
{ minWidth: 600 } matches: false

Server-side rendering

An implementation of matchMedia is required on the server, we recommend using css-mediaquery. We also encourage the usage of the useMediaQueryTheme version of the hook that fetches properties from the theme. This way, you can provide a ssrMatchMedia option once for all your React tree.

@media (min-width:600px) matches: false

Migrating from withWidth()

The withWidth() higher-order component injects the screen width of the page. You can reproduce the same behavior with a useWidth hook:

/**
 * Be careful using this hook. It only works because the number of
 * breakpoints in theme is static. It will break once you change the number of
 * breakpoints. See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
 */
function useWidth() {
  const theme = useTheme();
  const keys = [...theme.breakpoints.keys].reverse();
  return (
    keys.reduce((output, key) => {
      // eslint-disable-next-line react-hooks/rules-of-hooks
      const matches = useMediaQuery(theme.breakpoints.only(key));
      return !output && matches ? key : output;
    }, null) || 'xs'
  );
}
width: xs

API

useMediaQuery(query, [options]) => matches

Arguments

  1. query (String): A string representing the media query to handle.
  2. options (Object [optional]):
    • options.defaultMatches (Boolean [optional]): As window.matchMedia() is unavailable on the server, we return a default matches during the first mount. The default value is false.
    • options.noSsr (Boolean [optional]): Defaults to false. In order to perform the server-side rendering reconciliation, it needs to render twice. A first time with nothing and a second time with the children. This double pass rendering cycle comes with a drawback. It's slower. You can set this flag to true if you are not doing server-side rendering.
    • options.ssrMatchMedia (Function [optional]) You might want to use an heuristic to approximate the screen of the client browser. For instance, you could be using the user-agent or the client-hint https://caniuse.com/#search=client%20hint. You can provide a global ponyfill using custom properties on the theme. Check the server-side rendering example.

Returns

matches: Matches is true if the document currently matches the media query and false when it does not.

Examples

import React from 'react';
import useMediaQuery from '@material-ui/core/useMediaQuery';

export default function SimpleMediaQuery() {
  const matches = useMediaQuery('print');

  return <span>{`@media (min-width:600px) matches: ${matches}`}</span>;
}