UNPKG

8.74 kBMarkdownView Raw
1# react-responsive [![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url]
2
3## Information
4
5<table>
6<tr>
7<td>Package</td><td>react-responsive</td>
8</tr>
9<tr>
10<td>Description</td>
11<td>Media queries in react for responsive design</td>
12</tr>
13<tr>
14<td>Browser Version</td>
15<td>>= IE6*</td>
16</tr>
17</tr>
18<tr>
19<td colspan='2'><a href='http://contra.io/react-responsive/'>Demo</a></td>
20</tr>
21</table>
22
23The best supported, easiest to use react media query module.
24
25## Install
26
27```console
28$ npm install react-responsive --save
29```
30
31## Example Usage
32
33### With Hooks
34
35Hooks is a new feature available in 8.0.0!
36
37```jsx
38import React from 'react'
39import { useMediaQuery } from 'react-responsive'
40
41const Example = () => {
42 const isDesktopOrLaptop = useMediaQuery({
43 query: '(min-width: 1224px)'
44 })
45 const isBigScreen = useMediaQuery({ query: '(min-width: 1824px)' })
46 const isTabletOrMobile = useMediaQuery({ query: '(max-width: 1224px)' })
47 const isPortrait = useMediaQuery({ query: '(orientation: portrait)' })
48 const isRetina = useMediaQuery({ query: '(min-resolution: 2dppx)' })
49
50 return <div>
51 <h1>Device Test!</h1>
52 {isDesktopOrLaptop && <p>You are a desktop or laptop</p>}
53 {isBigScreen && <p>You have a huge screen</p>}
54 {isTabletOrMobile && <p>You are a tablet or mobile phone</p>}
55 <p>Your are in {isPortrait ? 'portrait' : 'landscape'} orientation</p>
56 {isRetina && <p>You are retina</p>}
57 </div>
58}
59```
60
61### With Components
62
63```jsx
64import MediaQuery from 'react-responsive'
65
66const Example = () => (
67 <div>
68 <h1>Device Test!</h1>
69 <MediaQuery minWidth={1224}>
70 <p>You are a desktop or laptop</p>
71 <MediaQuery minWidth={1824}>
72 <p>You also have a huge screen</p>
73 </MediaQuery>
74 </MediaQuery>
75 <MediaQuery minResolution="2dppx">
76 {/* You can also use a function (render prop) as a child */}
77 {(matches) =>
78 matches
79 ? <p>You are retina</p>
80 : <p>You are not retina</p>
81 }
82 </MediaQuery>
83 </div>
84)
85```
86
87## API
88
89### Using Properties
90
91To make things more idiomatic to react, you can use camel-cased shorthands to construct media queries.
92
93For a list of all possible shorthands and value types see https://github.com/contra/react-responsive/blob/master/src/mediaQuery.ts#L9.
94
95Any numbers given as shorthand will be expanded to px (`1234` will become `'1234px'`).
96
97The CSS media queries in the example above could be constructed like this:
98
99```jsx
100import React from 'react'
101import { useMediaQuery } from 'react-responsive'
102
103const Example = () => {
104 const isDesktopOrLaptop = useMediaQuery({ minWidth: 1224 })
105 const isBigScreen = useMediaQuery({ minWidth: 1824 })
106 const isTabletOrMobile = useMediaQuery({ maxWidth: 1224 })
107 const isPortrait = useMediaQuery({ orientation: 'portrait' })
108 const isRetina = useMediaQuery({ minResolution: '2dppx' })
109
110 return (
111 <div>
112 ...
113 </div>
114 )
115}
116```
117
118### Forcing a device with the `device` prop
119
120At 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.
121
122#### Possible Keys
123
124`orientation`, `scan`, `aspectRatio`, `deviceAspectRatio`,
125`height`, `deviceHeight`, `width`, `deviceWidth`, `color`, `colorIndex`, `monochrome`,
126`resolution` and `type`
127
128##### Possible Types
129
130`type` can be one of: `all`, `grid`, `aural`, `braille`, `handheld`, `print`, `projection`,
131`screen`, `tty`, `tv` or `embossed`
132
133Note: The `device` property always applies, even when it can be detected (where window.matchMedia exists).
134
135```jsx
136import { useMediaQuery } from 'react-responsive'
137
138const Example = () => {
139 const isDesktopOrLaptop = useMediaQuery(
140 { minDeviceWidth: 1224 },
141 { deviceWidth: 1600 } // `device` prop
142 )
143
144 return (
145 <div>
146 {isDesktopOrLaptop &&
147 <p>
148 this will always get rendered even if device is shorter than 1224px,
149 that's because we overrode device settings with 'deviceWidth: 1600'.
150 </p>
151 }
152 </div>
153 )
154}
155```
156
157#### Supplying through Context
158
159You can also pass `device` to every `useMediaQuery` hook in the components tree through a React [Context](https://reactjs.org/docs/context.html).
160This should ease up server-side-rendering and testing in a Node environment, e.g:
161
162##### Server-Side Rendering
163
164```jsx
165import { Context as ResponsiveContext } from 'react-responsive'
166import { renderToString } from 'react-dom/server'
167import App from './App'
168
169...
170 // Context is just a regular React Context component, it accepts a `value` prop to be passed to consuming components
171 const mobileApp = renderToString(
172 <ResponsiveContext.Provider value={{ width: 500 }}>
173 <App />
174 </ResponsiveContext.Provider>
175 )
176...
177```
178
179##### Testing
180
181```jsx
182import { Context as ResponsiveContext } from 'react-responsive'
183import { render } from '@testing-library/react'
184import ProductsListing from './ProductsListing'
185
186describe('ProductsListing', () => {
187 test('matches the snapshot', () => {
188 const { container: mobile } = render(
189 <ResponsiveContext.Provider value={{ width: 300 }}>
190 <ProductsListing />
191 </ResponsiveContext.Provider>
192 )
193 expect(mobile).toMatchSnapshot()
194
195 const { container: desktop } = render(
196 <ResponsiveContext.Provider value={{ width: 1000 }}>
197 <ProductsListing />
198 </ResponsiveContext.Provider>
199 )
200 expect(desktop).toMatchSnapshot()
201 })
202})
203```
204
205Note that if anything has a `device` prop passed in it will take precedence over the one from context.
206
207### `onChange`
208
209You can use the `onChange` callback to specify a change handler that will be called when the media query's value changes.
210
211```jsx
212import React from 'react'
213import { useMediaQuery } from 'react-responsive'
214
215const Example = () => {
216
217 const handleMediaQueryChange = (matches) => {
218 // matches will be true or false based on the value for the media query
219 }
220 const isDesktopOrLaptop = useMediaQuery(
221 { minWidth: 1224 }, undefined, handleMediaQueryChange
222 );
223
224 return (
225 <div>
226 ...
227 </div>
228 )
229}
230```
231
232```jsx
233import React from 'react'
234import MediaQuery from 'react-responsive'
235
236const Example = () => {
237
238 const handleMediaQueryChange = (matches) => {
239 // matches will be true or false based on the value for the media query
240 }
241
242 return (
243 <MediaQuery minWidth={1224} onChange={handleMediaQueryChange}>
244 ...
245 </MediaQuery>
246 )
247}
248```
249
250## Easy Mode
251
252That's it! Now you can create your application specific breakpoints and reuse them easily. Here is an example:
253
254```jsx
255import { useMediaQuery } from 'react-responsive'
256
257const Desktop = ({ children }) => {
258 const isDesktop = useMediaQuery({ minWidth: 992 })
259 return isDesktop ? children : null
260}
261const Tablet = ({ children }) => {
262 const isTablet = useMediaQuery({ minWidth: 768, maxWidth: 991 })
263 return isTablet ? children : null
264}
265const Mobile = ({ children }) => {
266 const isMobile = useMediaQuery({ maxWidth: 767 })
267 return isMobile ? children : null
268}
269const Default = ({ children }) => {
270 const isNotMobile = useMediaQuery({ minWidth: 768 })
271 return isNotMobile ? children : null
272}
273
274const Example = () => (
275 <div>
276 <Desktop>Desktop or laptop</Desktop>
277 <Tablet>Tablet</Tablet>
278 <Mobile>Mobile</Mobile>
279 <Default>Not mobile (desktop or laptop or tablet)</Default>
280 </div>
281)
282
283export default Example
284```
285
286And if you want a combo (the DRY way):
287
288```js
289import { useMediaQuery } from "react-responsive"
290
291const useDesktopMediaQuery = () =>
292 useMediaQuery({ query: "(min-width: 1280px)" })
293
294const useTabletAndBelowMediaQuery = () =>
295 useMediaQuery({ query: "(max-width: 1279px)" })
296
297const Desktop = ({ children }) => {
298 const isDesktop = useDesktopMediaQuery()
299
300 return isDesktop ? children : null
301}
302
303const TabletAndBelow = ({ children }) => {
304 const isTabletAndBelow = useTabletAndBelowMediaQuery()
305
306 return isTabletAndBelow ? children : null
307}
308```
309
310
311## Browser Support
312
313### Out of the box
314
315<table>
316<tr>
317<td>Chrome</td>
318<td>9</td>
319</tr>
320<tr>
321<td>Firefox (Gecko)</td>
322<td>6</td>
323</tr>
324<tr>
325<td>MS Edge</td>
326<td>All</td>
327</tr>
328<tr>
329<td>Internet Explorer</td>
330<td>10</td>
331</tr>
332<tr>
333<td>Opera</td>
334<td>12.1</td>
335</tr>
336<tr>
337<td>Safari</td>
338<td>5.1</td>
339</tr>
340</table>
341
342### With Polyfills
343
344Pretty much everything. Check out these polyfills:
345
346- [matchMedia.js by Paul Irish](https://github.com/paulirish/matchMedia.js/)
347- [media-match (faster, but larger and lacking some features)](https://github.com/weblinc/media-match)
348
349[downloads-image]: http://img.shields.io/npm/dm/react-responsive.svg
350[npm-url]: https://npmjs.org/package/react-responsive
351[npm-image]: http://img.shields.io/npm/v/react-responsive.svg