The best supported, easiest to use react media query module.
$ npm install react-responsive --save
Hooks is a new feature available in 8.0.0!
importReactfrom'react'
import { useMediaQuery } from'react-responsive'
constExample = () => {
constisDesktopOrLaptop = useMediaQuery({
query:'(min-width: 1224px)'
})
constisBigScreen = useMediaQuery({ query:'(min-width: 1824px)' })
constisTabletOrMobile = useMediaQuery({ query:'(max-width: 1224px)' })
constisPortrait = useMediaQuery({ query:'(orientation: portrait)' })
constisRetina = useMediaQuery({ query:'(min-resolution: 2dppx)' })
return (
<div>
<h1>Device Test!</h1>
{isDesktopOrLaptop&&<p>You are a desktop or laptop</p>}
{isBigScreen&&<p>You have a huge screen</p>}
{isTabletOrMobile&&<p>You are a tablet or mobile phone</p>}
<p>Your are in {isPortrait?'portrait':'landscape'} orientation</p>
{isRetina&&<p>You are retina</p>}
</div>
)
}
importMediaQueryfrom'react-responsive'
constExample = () => (
<div>
<h1>Device Test!</h1>
<MediaQueryminWidth={1224}>
<p>You are a desktop or laptop</p>
<MediaQueryminWidth={1824}>
<p>You also have a huge screen</p>
</MediaQuery>
</MediaQuery>
<MediaQueryminResolution="2dppx">
{/* You can also use a function (render prop) as a child */}
{(matches) =>
matches?<p>You are retina</p>:<p>You are not retina</p>
}
</MediaQuery>
</div>
)
To make things more idiomatic to react, you can use camel-cased shorthands to construct media queries.
For a list of all possible shorthands and value types see https://github.com/yocontra/react-responsive/blob/master/src/mediaQuery.ts#L9.
Any numbers given as shorthand will be expanded to px (1234 will become '1234px').
The CSS media queries in the example above could be constructed like this:
importReactfrom'react'
import { useMediaQuery } from'react-responsive'
constExample = () => {
constisDesktopOrLaptop = useMediaQuery({ minWidth:1224 })
constisBigScreen = useMediaQuery({ minWidth:1824 })
constisTabletOrMobile = useMediaQuery({ maxWidth:1224 })
constisPortrait = useMediaQuery({ orientation:'portrait' })
constisRetina = useMediaQuery({ minResolution:'2dppx' })
return<div>...</div>
}
device prop At times you may need to render components with different device settings than what gets automatically detected. This is especially useful in a Node environment where these settings can't be detected (SSR) or for testing.
orientation, scan, aspectRatio, deviceAspectRatio,
height, deviceHeight, width, deviceWidth, color, colorIndex, monochrome,
resolution and type
type can be one of: all, grid, aural, braille, handheld, print, projection,
screen, tty, tv or embossed
Note: The device property always applies, even when it can be detected (where window.matchMedia exists).
import { useMediaQuery } from'react-responsive'
constExample = () => {
constisDesktopOrLaptop = useMediaQuery(
{ minDeviceWidth:1224 },
{ deviceWidth:1600 } // `device` prop
)
return (
<div>
{isDesktopOrLaptop&& (
<p>
this will always get rendered even if device is shorter than 1224px,
that's because we overrode device settings with 'deviceWidth: 1600'.
</p>
)}
</div>
)
}
You can also pass device to every useMediaQuery hook in the components tree through a React Context.
This should ease up server-side-rendering and testing in a Node environment, e.g:
import { ContextasResponsiveContext } from'react-responsive'
import { renderToString } from'react-dom/server'
importAppfrom'./App'
...
// Context is just a regular React Context component, it accepts a `value` prop to be passed to consuming components
constmobileApp = renderToString(
<ResponsiveContext.Providervalue={{ width:500 }}>
<App/>
</ResponsiveContext.Provider>
)
...
If you use next.js, structure your import like this to disable server-side rendering for components that use this library:
importdynamicfrom'next/dynamic'
constMediaQuery = dynamic(() =>import('react-responsive'), {
ssr:false
})
import { ContextasResponsiveContext } from'react-responsive'
import { render } from'@testing-library/react'
importProductsListingfrom'./ProductsListing'
describe('ProductsListing', () => {
test('matches the snapshot', () => {
const { container: mobile } = render(
<ResponsiveContext.Providervalue={{ width:300 }}>
<ProductsListing/>
</ResponsiveContext.Provider>
)
expect(mobile).toMatchSnapshot()
const { container: desktop } = render(
<ResponsiveContext.Providervalue={{ width:1000 }}>
<ProductsListing/>
</ResponsiveContext.Provider>
)
expect(desktop).toMatchSnapshot()
})
})
Note that if anything has a device prop passed in it will take precedence over the one from context.
onChange You can use the onChange callback to specify a change handler that will be called when the media query's value changes.
importReactfrom'react'
import { useMediaQuery } from'react-responsive'
constExample = () => {
consthandleMediaQueryChange = (matches) => {
// matches will be true or false based on the value for the media query
}
constisDesktopOrLaptop = useMediaQuery(
{ minWidth:1224 },
undefined,
handleMediaQueryChange
)
return<div>...</div>
}
importReactfrom'react'
importMediaQueryfrom'react-responsive'
constExample = () => {
consthandleMediaQueryChange = (matches) => {
// matches will be true or false based on the value for the media query
}
return (
<MediaQueryminWidth={1224}onChange={handleMediaQueryChange}>
...
</MediaQuery>
)
}
That's it! Now you can create your application specific breakpoints and reuse them easily. Here is an example:
import { useMediaQuery } from'react-responsive'
constDesktop = ({ children }) => {
constisDesktop = useMediaQuery({ minWidth:992 })
returnisDesktop ? children : null
}
constTablet = ({ children }) => {
constisTablet = useMediaQuery({ minWidth:768, maxWidth:991 })
returnisTablet ? children : null
}
constMobile = ({ children }) => {
constisMobile = useMediaQuery({ maxWidth:767 })
returnisMobile ? children : null
}
constDefault = ({ children }) => {
constisNotMobile = useMediaQuery({ minWidth:768 })
returnisNotMobile ? children : null
}
constExample = () => (
<div>
<Desktop>Desktop or laptop</Desktop>
<Tablet>Tablet</Tablet>
<Mobile>Mobile</Mobile>
<Default>Not mobile (desktop or laptop or tablet)</Default>
</div>
)
exportdefaultExample
And if you want a combo (the DRY way):
import { useMediaQuery } from'react-responsive'
constuseDesktopMediaQuery = () =>
useMediaQuery({ query:'(min-width: 1280px)' })
constuseTabletAndBelowMediaQuery = () =>
useMediaQuery({ query:'(max-width: 1279px)' })
constDesktop = ({ children }) => {
constisDesktop = useDesktopMediaQuery()
returnisDesktop ? children : null
}
constTabletAndBelow = ({ children }) => {
constisTabletAndBelow = useTabletAndBelowMediaQuery()
returnisTabletAndBelow ? children : null
}
Pretty much everything. Check out these polyfills:
Generated using TypeDoc