Skip to content

useMediaQuery

This React hook 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 supports server-side rendering.

Basic media query

You should provide a media query to the first argument of the hook. The media query string can be any valid CSS media query, e.g. '(prefers-color-scheme: dark)'.

(min-width:600px) matches: false
Press Enter to start editing

⚠️ You can't use 'print' per browsers limitation, e.g. Firefox.

Using Material UI's breakpoint helpers

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

<span class="token keyword">import</span> <span class="token punctuation">{</span> useTheme <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@mui/material/styles'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> useMediaQuery <span class="token keyword">from</span> <span class="token string">'@mui/material/useMediaQuery'</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">MyComponent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> theme <span class="token operator">=</span> <span class="token function">useTheme</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> matches <span class="token operator">=</span> <span class="token function">useMediaQuery</span><span class="token punctuation">(</span>theme<span class="token punctuation">.</span>breakpoints<span class="token punctuation">.</span><span class="token function">up</span><span class="token punctuation">(</span><span class="token string">'sm'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span><span class="token punctuation">{</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">theme.breakpoints.up('sm') matches: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>matches<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
theme.breakpoints.up('sm') matches: false

Alternatively, you can use a callback function, accepting the theme as a first argument:

<span class="token keyword">import</span> useMediaQuery <span class="token keyword">from</span> <span class="token string">'@mui/material/useMediaQuery'</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">MyComponent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> matches <span class="token operator">=</span> <span class="token function">useMediaQuery</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">theme</span><span class="token punctuation">)</span> <span class="token operator">=></span> theme<span class="token punctuation">.</span>breakpoints<span class="token punctuation">.</span><span class="token function">up</span><span class="token punctuation">(</span><span class="token string">'sm'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span><span class="token punctuation">{</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">theme.breakpoints.up('sm') matches: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>matches<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

⚠️ There is no default theme support, you have to inject it in a parent theme provider.

Using JavaScript syntax

You can use json2mq to generate media query string from a JavaScript object.

{ minWidth: 600 } matches: false
Press Enter to start editing

Testing

You need an implementation of matchMedia in your test environment.

For instance, jsdom doesn't support it yet. You should polyfill it. Using css-mediaquery to emulate it is recommended.

<span class="token keyword">import</span> mediaQuery <span class="token keyword">from</span> <span class="token string">'css-mediaquery'</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">createMatchMedia</span><span class="token punctuation">(</span><span class="token parameter">width</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token parameter">query</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
    <span class="token literal-property property">matches</span><span class="token operator">:</span> mediaQuery<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span>query<span class="token punctuation">,</span> <span class="token punctuation">{</span>
      width<span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token function-variable function">addListener</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token function-variable function">removeListener</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'MyTests'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
  <span class="token function">beforeAll</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
    window<span class="token punctuation">.</span>matchMedia <span class="token operator">=</span> <span class="token function">createMatchMedia</span><span class="token punctuation">(</span>window<span class="token punctuation">.</span>innerWidth<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Client-side only rendering

To perform the server-side hydration, the hook needs to render twice. A first time with defaultMatches, the value of the server, and a second time with the resolved value. This double pass rendering cycle comes with a drawback: it's slower. You can set the noSsr option to true if you use the returned value only client-side.

<span class="token keyword">const</span> matches <span class="token operator">=</span> <span class="token function">useMediaQuery</span><span class="token punctuation">(</span><span class="token string">'(min-width:600px)'</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token literal-property property">noSsr</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

or it can turn it on globally with the theme:

<span class="token keyword">const</span> theme <span class="token operator">=</span> <span class="token function">createTheme</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  <span class="token literal-property property">components</span><span class="token operator">:</span> <span class="token punctuation">{</span>
    <span class="token literal-property property">MuiUseMediaQuery</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token literal-property property">defaultProps</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">noSsr</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

Server-side rendering

Try relying on client-side CSS media queries first. For instance, you could use:

If none of the above alternatives are an option, you can proceed reading this section of the documentation.

First, you need to guess the characteristics of the client request, from the server. You have the choice between using:

  • User agent. Parse the user agent string of the client to extract information. Using ua-parser-js to parse the user agent is recommended.
  • Client hints. Read the hints the client is sending to the server. Be aware that this feature is not supported everywhere.

Finally, you need to provide an implementation of matchMedia to the useMediaQuery with the previously guessed characteristics. Using css-mediaquery to emulate matchMedia is recommended.

For instance on the server-side:

<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> ReactDOMServer <span class="token keyword">from</span> <span class="token string">'react-dom/server'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> parser <span class="token keyword">from</span> <span class="token string">'ua-parser-js'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> mediaQuery <span class="token keyword">from</span> <span class="token string">'css-mediaquery'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> createTheme<span class="token punctuation">,</span> ThemeProvider <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@mui/material/styles'</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">handleRender</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> deviceType <span class="token operator">=</span> <span class="token function">parser</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>headers<span class="token punctuation">[</span><span class="token string">'user-agent'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span>device<span class="token punctuation">.</span>type <span class="token operator">||</span> <span class="token string">'desktop'</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> <span class="token function-variable function">ssrMatchMedia</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">query</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
    <span class="token literal-property property">matches</span><span class="token operator">:</span> mediaQuery<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span>query<span class="token punctuation">,</span> <span class="token punctuation">{</span>
      <span class="token comment">// The estimated CSS width of the browser.</span>
      <span class="token literal-property property">width</span><span class="token operator">:</span> deviceType <span class="token operator">===</span> <span class="token string">'mobile'</span> <span class="token operator">?</span> <span class="token string">'0px'</span> <span class="token operator">:</span> <span class="token string">'1024px'</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> theme <span class="token operator">=</span> <span class="token function">createTheme</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    <span class="token literal-property property">components</span><span class="token operator">:</span> <span class="token punctuation">{</span>
      <span class="token comment">// Change the default options of useMediaQuery</span>
      <span class="token literal-property property">MuiUseMediaQuery</span><span class="token operator">:</span> <span class="token punctuation">{</span>
        <span class="token literal-property property">defaultProps</span><span class="token operator">:</span> <span class="token punctuation">{</span>
          ssrMatchMedia<span class="token punctuation">,</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">const</span> html <span class="token operator">=</span> ReactDOMServer<span class="token punctuation">.</span><span class="token function">renderToString</span><span class="token punctuation">(</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">ThemeProvider</span></span> <span class="token attr-name">theme</span><span class="token script language-javascript"><span class="token script-punctuation punctuation">=</span><span class="token punctuation">{</span>theme<span class="token punctuation">}</span></span><span class="token punctuation">></span></span>
      <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span><span class="token class-name">App</span></span> <span class="token punctuation">/></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span><span class="token class-name">ThemeProvider</span></span><span class="token punctuation">></span></span><span class="token punctuation">,</span>
  <span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token comment">// …</span>
<span class="token punctuation">}</span>
(min-width:600px) matches: true

Make sure you provide the same custom match media implementation to the client-side to guarantee a hydration match.

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:

width: xs
Press Enter to start editing

API

useMediaQuery(query, [options]) => matches

Arguments

  1. query (string | func): A string representing the media query to handle or a callback function accepting the theme (in the context) that returns a string.
  2. options (object [optional]):
  • options.defaultMatches (bool [optional]): As window.matchMedia() is unavailable on the server, it returns a default matches during the first mount. The default value is false.
  • options.matchMedia (func [optional]): You can provide your own implementation of matchMedia. This can be used for handling an iframe content window.
  • options.noSsr (bool [optional]): Defaults to false. To perform the server-side hydration, the hook needs to render twice. A first time with defaultMatches, the value of the server, and a second time with the resolved value. This double pass rendering cycle comes with a drawback: it's slower. You can set this option to true if you use the returned value only client-side.
  • options.ssrMatchMedia (func [optional]): You can provide your own implementation of matchMedia, it's used when rendering server-side.

Note: You can change the default options using the default props feature of the theme with the MuiUseMediaQuery key.

Returns

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

Examples

<span class="token keyword">import</span> <span class="token operator">*</span> <span class="token keyword">as</span> React <span class="token keyword">from</span> <span class="token string">'react'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> useMediaQuery <span class="token keyword">from</span> <span class="token string">'@mui/material/useMediaQuery'</span><span class="token punctuation">;</span>

<span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token keyword">function</span> <span class="token function">SimpleMediaQuery</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> matches <span class="token operator">=</span> <span class="token function">useMediaQuery</span><span class="token punctuation">(</span><span class="token string">'(min-width:600px)'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>span</span><span class="token punctuation">></span></span><span class="token punctuation">{</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">(min-width:600px) matches: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>matches<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">}</span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>span</span><span class="token punctuation">></span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>