react-responsive
Information
Package | react-responsive |
Description | Media queries in react for responsive design |
Browser Version | >= IE6* |
Demo |
The best supported, easiest to use react media query module.
Install
$ npm install react-responsive --save
Example Usage
With Hooks
This feature is available on the 8.0.0-beta branch, and will go stable very soon!
import React from 'react'
import { useMediaQuery } from 'react-responsive'
const Example = () => {
const isDesktopOrLaptop = useMediaQuery({
query: '(min-device-width: 1224px)'
})
const isBigScreen = useMediaQuery({ query: '(min-device-width: 1824px)' })
const isTabletOrMobile = useMediaQuery({ query: '(max-width: 1224px)' })
const isTabletOrMobileDevice = useMediaQuery({
query: '(max-device-width: 1224px)'
})
const isPortrait = useMediaQuery({ query: '(orientation: portrait)' })
const isRetina = useMediaQuery({ query: '(min-resolution: 2dppx)' })
return (
<div>
<h1>Device Test!</h1>
{isDesktopOrLaptop && <>
<p>You are a desktop or laptop</p>
{isBigScreen && <p>You also have a huge screen</p>}
{isTabletOrMobile && <p>You are sized like a tablet or mobile phone though</p>}
</>}
{isTabletOrMobileDevice && <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>
)
}
With Components
import MediaQuery from 'react-responsive'
const Example = () => (
<div>
<h1>Device Test!</h1>
<MediaQuery minDeviceWidth={1224} device={{ deviceWidth: 1600 }}>
<p>You are a desktop or laptop</p>
<MediaQuery minDeviceWidth={1824}>
<p>You also have a huge screen</p>
</MediaQuery>
</MediaQuery>
<MediaQuery minResolution='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>
)
API
Using Properties
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/contra/react-responsive/blob/master/src/mediaQuery.js#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:
import React from 'react'
import { useMediaQuery } from 'react-responsive'
const Example = () => {
const isDesktopOrLaptop = useMediaQuery({ minDeviceWidth: 1224 })
const isBigScreen = useMediaQuery({ minDeviceWidth: 1824 })
const isTabletOrMobile = useMediaQuery({ maxWidth: 1224 })
const isTabletOrMobileDevice = useMediaQuery({ maxDeviceWidth: 1224 })
const isPortrait = useMediaQuery({ orientation: 'portrait' })
const isRetina = useMediaQuery({ minResolution: '2dppx' })
return (
<div>
...
</div>
)
}
Forcing a device with the 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.
Possible Keys
orientation
, scan
, aspectRatio
, deviceAspectRatio
,
height
, deviceHeight
, width
, deviceWidth
, color
, colorIndex
, monochrome
,
resolution
and type
Possible Types
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'
const Example = () => {
const isDesktopOrLaptop = useMediaQuery(
{ minDeviceWidth: 1224 },
{ deviceWidth: 1600 }
)
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>
)
}
Supplying through Context
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:
Server-Side Rendering
import { Context as ResponsiveContext } from 'react-responsive'
import { renderToString } from 'react-dom/server'
import App from './App'
...
const mobileApp = renderToString(
<ResponsiveContext.Provider value={{ width: 500 }}>
<App />
</ResponsiveContext.Provider>
)
...
Testing
import { Context as ResponsiveContext } from 'react-responsive'
import { render } from '@testing-library/react'
import ProductsListing from './ProductsListing'
describe('ProductsListing', () => {
test('matches the snapshot', () => {
const { container: mobile } = render(
<ResponsiveContext.Provider value={{ width: 300 }}>
<ProductsListing />
</ResponsiveContext.Provider>
)
expect(mobile).toMatchSnapshot()
const { container: desktop } = render(
<ResponsiveContext.Provider value={{ 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.
Easy Mode
That's it! Now you can create your application specific breakpoints and reuse them easily. Here is an example:
import { useMediaQuery } from 'react-responsive'
const Desktop = ({ children }) => {
const isDesktop = useMediaQuery({ minWidth: 992 })
return isDesktop ? children : null
}
const Tablet = ({ children }) => {
const isTablet = useMediaQuery({ minWidth: 768, maxWidth: 991 })
return isTablet ? children : null
}
const Mobile = ({ children }) => {
const isMobile = useMediaQuery({ maxWidth: 767 })
return isMobile ? children : null
}
const Default = ({ children }) => {
const isNotMobile = useMediaQuery({ minWidth: 768 })
return isNotMobile ? children : null
}
const Example = () => (
<div>
<Desktop>Desktop or laptop</Desktop>
<Tablet>Tablet</Tablet>
<Mobile>Mobile</Mobile>
<Default>Not mobile (desktop or laptop or tablet)</Default>
</div>
)
export default Example
Browser Support
Out of the box
Chrome | 9 |
Firefox (Gecko) | 6 |
MS Edge | All |
Internet Explorer | 10 |
Opera | 12.1 |
Safari | 5.1 |
With Polyfills
Pretty much everything. Check out these polyfills: