Media queries in react for responsive design
npm install react-responsive| 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.
``console`
$ npm install react-responsive --save
Hooks is a new feature available in 8.0.0!
`jsx
import React from 'react'
import { useMediaQuery } from 'react-responsive'
const Example = () => {
const isDesktopOrLaptop = useMediaQuery({
query: '(min-width: 1224px)'
})
const isBigScreen = useMediaQuery({ query: '(min-width: 1824px)' })
const isTabletOrMobile = useMediaQuery({ query: '(max-width: 1224px)' })
const isPortrait = useMediaQuery({ query: '(orientation: portrait)' })
const isRetina = useMediaQuery({ query: '(min-resolution: 2dppx)' })
return (
You are a desktop or laptop
}You have a huge screen
}You are a tablet or mobile phone
}Your are in {isPortrait ? 'portrait' : 'landscape'} orientation
You are retina
}$3
`jsx
import MediaQuery from 'react-responsive'const Example = () => (
Device Test!
You are a desktop or laptop
You also have a huge screen
{/ You can also use a function (render prop) as a child /}
{(matches) =>
matches ? You are retina
: You are not retina
}
)
`API
$3
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:
`jsx
import React from 'react'
import { useMediaQuery } from 'react-responsive'const Example = () => {
const isDesktopOrLaptop = useMediaQuery({ minWidth: 1224 })
const isBigScreen = useMediaQuery({ minWidth: 1824 })
const isTabletOrMobile = useMediaQuery({ maxWidth: 1224 })
const isPortrait = useMediaQuery({ orientation: 'portrait' })
const isRetina = useMediaQuery({ minResolution: '2dppx' })
return
...
}
`$3
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 embossedNote: The
device property always applies, even when it can be detected (where window.matchMedia exists).`jsx
import { useMediaQuery } from 'react-responsive'const Example = () => {
const isDesktopOrLaptop = useMediaQuery(
{ minDeviceWidth: 1224 },
{ deviceWidth: 1600 } //
device prop
) return (
{isDesktopOrLaptop && (
this will always get rendered even if device is shorter than 1224px,
that's because we overrode device settings with 'deviceWidth: 1600'.
)}
)
}
`#### 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
`jsx
import { Context as ResponsiveContext } from 'react-responsive'
import { renderToString } from 'react-dom/server'
import App from './App'...
// Context is just a regular React Context component, it accepts a
value prop to be passed to consuming components
const mobileApp = renderToString(
)
...
`If you use next.js, structure your import like this to disable server-side rendering for components that use this library:
`js
import dynamic from 'next/dynamic'
const MediaQuery = dynamic(() => import('react-responsive'), {
ssr: false
})
`##### Testing
`jsx
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(
)
expect(mobile).toMatchSnapshot()
const { container: desktop } = render(
)
expect(desktop).toMatchSnapshot()
})
})
`Note that if anything has a
device prop passed in it will take precedence over the one from context.$3
You can use the
onChange callback to specify a change handler that will be called when the media query's value changes.`jsx
import React from 'react'
import { useMediaQuery } from 'react-responsive'const Example = () => {
const handleMediaQueryChange = (matches) => {
// matches will be true or false based on the value for the media query
}
const isDesktopOrLaptop = useMediaQuery(
{ minWidth: 1224 },
undefined,
handleMediaQueryChange
)
return
...
}
``jsx
import React from 'react'
import MediaQuery from 'react-responsive'const Example = () => {
const handleMediaQueryChange = (matches) => {
// matches will be true or false based on the value for the media query
}
return (
...
)
}
`Easy Mode
That's it! Now you can create your application specific breakpoints and reuse them easily. Here is an example:
`jsx
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 = () => (
Desktop or laptop
Tablet
Mobile
Not mobile (desktop or laptop or tablet)
)export default Example
`And if you want a combo (the DRY way):
`js
import { useMediaQuery } from 'react-responsive'const useDesktopMediaQuery = () =>
useMediaQuery({ query: '(min-width: 1280px)' })
const useTabletAndBelowMediaQuery = () =>
useMediaQuery({ query: '(max-width: 1279px)' })
const Desktop = ({ children }) => {
const isDesktop = useDesktopMediaQuery()
return isDesktop ? children : null
}
const TabletAndBelow = ({ children }) => {
const isTabletAndBelow = useTabletAndBelowMediaQuery()
return isTabletAndBelow ? children : null
}
``| Chrome | 9 |
| Firefox (Gecko) | 6 |
| MS Edge | All |
| Internet Explorer | 10 |
| Opera | 12.1 |
| Safari | 5.1 |
Pretty much everything. Check out these polyfills:
- matchMedia.js by Paul Irish
- media-match (faster, but larger and lacking some features)
[downloads-image]: http://img.shields.io/npm/dm/react-responsive.svg
[npm-url]: https://npmjs.org/package/react-responsive
[npm-image]: http://img.shields.io/npm/v/react-responsive.svg