react-responsive-functions
v1.2.1
Published
Functions for easily creating UI elements with responsive sizes in React
Downloads
42
Maintainers
Readme
React Responsive Functions
This collection of functions will help enable to you to translate designs into responsive react applications with ease.
Setup
To get started, simply run
npm install react-responsive-functions
or
yarn add react-responsive-functions
in your react project to install.
Then, you can add the ResponsiveProvider component to give your component access to the responsive functions.
The Responsive Provider
Responsive functions must be used within the ResponsiveProvider component, which gives access to the screen width. The ResponsiveProvider can be added to the root component, or another location that surrounds all the components that use a responsive function.
It is also here that you the define the breakpoints you are using for your project. The following example shows a configuration with two breakpoints, one for mobile and one for desktop.
import { ResponsiveProvider } from 'react-responsive'
export default function ExampleWrapper() {
return <ResponsiveProvider sizes={{mobile: 960, desktop: 1920}}>
// Your code goes here
</ResponsiveProvider>
}
You can define any number of breakpoints, with any names you want. When you invoke responsive later, you'll use the same shape of object to define the desired size of the element at each breakpoint. In this example, there are four different breakpoints:
import { ResponsiveProvider } from 'react-responsive'
<ResponsiveProvider sizes={{sm: 768, md: 960, lg: 1200, xl: 1920}}>
// Your code goes here
</ResponsiveProvider>
The largest breakpoint size also represents the maximum screen width; that is, after the width exceeds that size, elements using Responsive will no longer chage in size.
Using React Responsive Functions
The res() function takes in an object that shows the size of the element at each breakpoint, and returns a value based on the current browser width. Here's an example with just two breakpoints:
import React from 'react'
import { res } from 'react-responsive'
export default function Example() {
const h1Style = `font-size: ${res({mobile: 20, desktop: 60})}px;`
return <h1 style={h1Style}>Header Text</h1>
}
Responsive and Emotion
Responsive pairs well with @emotion/css, which allows styles to be defined programmatically with ease. Here's the previous example rewritten using an emotion class:
import React from 'react'
import { res } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const header = css`
font-size: ${res({mobile: 20, desktop: 60})}px;
`
return <h1 className={header}>Header Text</h1>
}
The px() function
The px function is a simple shortcut fuction, which automacally appends px to the end of the calculated px value. So the previous example could be re-written as such:
import React from 'react'
import { px } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const header = css`
font-size: ${px({mobile: 20, desktop: 60})};
`
return <h1 className={header}>Header Text</h1>
}
We recommend using the px() function as opposed to res() in general, though there may still be cases when you need res(), like if you need to perform operations on the returned value.
The rem() function and accessibility
You may have noticed that the previous examples all use px values for the header style, which will not respond to changes in the default browser font size. For better accessibility, the rem() function converts the px value calculated into rem units. Lets update our example to use rem units instead of px units:
import React from 'react'
import { rem } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const header = css`
font-size: ${rem({mobile: 20, desktop: 60})};
`
return <h1 className={header}>Header Text</h1>
}
You'll notice that the ONLY change was which function was was used. The conversion from px values is handled entirely in the function, so just make sure you use responsiveText() instead of responsive() whenever you want rem units. The rem() function assumes a default browser font size of 16px.
The single value shortcut
If every breakpoint uses the same value, but you still want it to scale with the other responsive values, you can supply a single value instead of an object to use that value for every breakpoint:
import React from 'react'
import { rem } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const header = css`
font-size: ${rem(20)};
`
return <h1 className={header}>Header Text</h1>
}
Conditionals
For more complex reponsive designs, you might to test what breakpoint you are at to determine which elements should be displayed. To help with this, Responsive includes three functions to test the current breakpoint.
The inBreakpoint() function
The inBreakpoint() function takes in the name of a particular breakpoint and returns true if the current width is less than or equal that breakpoint, but larger than the next smallest breakpoint (or 0 for the smallest). Let's see this in practice:
import React from 'react'
import { rem, inBreakpoint } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const header = css`
font-size: ${rem({mobile: 20, desktop: 60})};
color: ${inBreakpoint('mobile') ? blue : red};
`
return <h1 className={header}>Header Text</h1>
}
In the above code snippet, we would expect the header to appear blue on mobile screens and red on desktop screens. For apps with more than two breakpoints, you may need to test for multiple breakpoints at once.
The inBreakpoints() function
For testing multiple breakpoints at once, you can use the inBreakpoints function. This function accepts a list of breakpoints, and will return true if the current window width is within any of the listed breakpoints. Here's the previous example rewritten with four distinct breakpoints instead of two.
import React from 'react'
import { rem, inBreakpoints } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const header = css`
font-size: ${rem({xs: 20, sm: 25, md: 20, lg: 25, xl: 30})};
color: ${inBreakpoints(['xs', 'sm']) ? blue : red};
`
return <h1 className={header}>Header Text</h1>
}
The above code works the same as the previous example, but will test if the current breakpoint is any of the listed breakpoints. If you are testing the same breakpoints, you might break this out into a helper funtcion:
import React from 'react'
import { rem, inBreakpoints } from 'react-responsive'
import { css } from '@emotion/css'
function isMobile() {
return inBreakpoints(['xs', 'sm'])
}
function Example() {
const header = css`
font-size: ${rem({xs: 20, sm: 25, md: 20, lg: 25, xl: 30})};
color: ${isMobile() ? blue : red};
`
return <h1 className={header}>Header Text</h1>
}
The isMax() function
The inBreakpoint() and inBreakpoints() function only test if the current width is lower than the given breakpoints. If you need to check if the width is at or above the maximum width, you can invoke the isMax() function:
import React from 'react'
import { rem, isMax } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const header = css`
font-size: ${rem({xs: 20, sm: 25, md: 20, lg: 25, xl: 30})};
color: ${isMax() ? red : blue};
`
return <h1 className={header}>Header Text</h1>
}
In this example, when the screen size reaches its maximum (as defined by the xl breakpoint in this case), the header color will change to red.
The smooth option
The smooth option allows you configure how you want the responsive values to be interpreted. If smooth is set to true, which is the default, the values will scale preciscely with the width of the screen. This means any responsive elements on screen will scale relative to the screen width. When set to false, responsive values will only update when the breakpoint changes. To set smooth to false, simply include it as a prop in the ResponsiveProvider:
<ResponsiveProvider sizes={{mobile: 960, desktop: 1920}} smooth={false}>
// Your code goes here
</ResponsiveProvider>
The oneOf() function
Even when you have a application utilizing the smooth values, you may have some values that you wish to change based on the the current breakpoint without the values being altered by the screen width. For thhose cases, you can call oneOf(). Unlike the the res() function, the oneOf function can take in any data type, not just numbers, for each breakpoint, since it doesn't need to perform a calculation.
import React from 'react'
import { oneOf } from 'react-responsive'
import { css } from '@emotion/css'
function Example() {
const text = `Current breakpoint size: ${
oneOf({mobile: 960, desktop: 1920})
} pixels!`
return <h1>{text}</h1>
}
Accessing the window dimensions
While the above functions will handle most of your needs, sometimes you may just need to directly find out what the current window dimensions are. Responsive makes this available to you through the useWindowDimensions() hook. The hook returns an object containing teh current width and height of the window.
import React from 'react'
import { useWindowDimensions } from 'react-responsive'
export default function Example() {
const { width, height } = useWindowDimensions()
return <p>Width: {width}, Height: {height}</p>
}
Mocking responsive for testing
In jest, responsive can be mocked using the jest.mock function, as shown below. Remember to not import react-responsive-functions into your test file when you mock in this way.
jest.mock('react-responsive-functions', () => ({
res: jest.fn().mockReturnValue(2),
px: jest.fn().mockReturnValue('2px'),
rem: jest.fn().mockReturnValue('2rem'),
oneOf: jest.fn().mockReturnValue(4),
inBreakpoint: jest.fn().mockReturnValue(true),
inBreakpoints: jest.fn().mockReturnValue(true),
isMax: jest.fn().mockReturnValue(false),
useWindowDimensions: jest.fn().mockReturnValue({width: 900, height: 600})
}))
If you need to cater you return values for mocks for different test, you can additonally import the functions like so:
import {
res,
px,
// etc...
} from 'react-responsive-functions'
Then inside your test:
res.mockReturnValue(20)
Note that this is in addition to including those functions in the jest.mock() call as shown above.