use-breakpoint
use-breakpoint copied to clipboard
React `useBreakpoint` hook to have different values for a variable based on a breakpoints.
Intro
React useBreakpoint
hook to have different values for a variable
based on a breakpoints.
Demo
https://wintercounter.github.io/use-breakpoint
Install
npm i @w11r/use-breakpoint
Setup
Add provider
Add BreakpointProvider
in your React tree.
import { BreakpointProvider } from '@w11r/use-breakpoint'
...
<BreakpointProvider>
...
</BreakpointProvider>
...
Default breakpoints
The following default breakpoints are being used, including several shorthands.
const breakpoints = {
micro: [0, 375],
mi: [0, 375],
mobile: [376, 639],
m: [376, 639],
tablet: [640, 1023],
t: [640, 1023],
small: [1024, 1439],
s: [1024, 1439],
medium: [1440, 1919],
med: [1440, 1919],
large: [1920, 10000],
l: [1920, 10000],
// Multi range
device: [0, 1023],
d: [0, 1023],
smallDevice: [0, 639],
sd: [0, 639]
}
Override default settings
import { setup, breakpoints } from '@w11r/use-breakpoint'
setup({
breakpoints: {
// Extend default values
...breakpoints,
alienDevice: [342, 43534] // from, to
}
})
Usage
With passing values
useBreakpoint(defaultValue, breakpointValues)
// breakpointValues: array of breakpoint based values
[
['mobile', 300],
['tablet', 400]
]
// In case you have a single breakpoint value, `['mobile', 300]` is enough instead of `[['mobile', 300]]`
Without passing values
In case you don't specify any value to the hook, it'll return a generated object including boolean values for each breakpoint keys that's being defined in options.
It'll return the following object with the basic setup.
{
isLandscape: false,
isPortrait: true,
isHDPI: false,
isMicro: false,
isMobile: true,
isTablet: false,
isSmall: false,
isMedium: false,
isLarge: false,
'is-Micro': false,
'is|Micro': false,
'isMicro+': true,
'is-Micro+': true,
'is|Micro+': true,
'isMicro-': false,
'is-Micro-': false,
'is|Micro-': false,
'is-Mobile': true,
'is|Mobile': true,
'isMobile+': true,
'is-Mobile+': true,
'is|Mobile+': true,
'isMobile-': true,
'is-Mobile-': true,
'is|Mobile-': true,
'is-Tablet': false,
'is|Tablet': false,
'isTablet+': false,
'is-Tablet+': false,
'is|Tablet+': false,
'isTablet-': true,
'is-Tablet-': true,
'is|Tablet-': true,
'is-Small': false,
'is|Small': false,
'isSmall+': false,
'is-Small+': false,
'is|Small+': false,
'isSmall-': true,
'is-Small-': true,
'is|Small-': true,
'is-Medium': false,
'is|Medium': false,
'isMedium+': false,
'is-Medium+': false,
'is|Medium+': false,
'isMedium-': true,
'is-Medium-': true,
'is|Medium-': true,
'is-Large': false,
'is|Large': false,
'isLarge+': false,
'is-Large+': false,
'is|Large+': false,
'isLarge-': true,
'is-Large-': true,
'is|Large-': true
}
Usage
const { isMobile } = useBreakpoint()
// The above is basically a replacement for
const isMobile = useBreakpoint(false, ['mobile', true])
You can also access the values with suffix and prefix, but you need to rename the variables because it contains invalid character:
const { 'isMobile+': isMobile } = useBreakpoint()
Component example
import useBreakpoint from '@w11r/use-breakpoint'
const MyCmp = () => {
const columns = useBreakpoint([1,2], ['mobile', [2,1]])
return <Grid cols={columns} />
}
// Or using inline
const MyCmp = () => {
return <Grid cols={useBreakpoint([1,2], ['mobile', [2,1]])} />
}
Rules-of-Hooks are still true in this case as well. Make sure your component will ALWAYS run it without any condition!
Modifiers
All breakpoint names coming with modifiers included.
Orientation prefix
- `` (none): all
-
-
: Landscape -
|
: Portrait
Range suffix
You can also control your value to behave as and up
and and down
.
- `` (none): all
-
+
:and up
-
-
:and down
Examples
-
['|mobile', 300]
: on mobile, on portrait -
['|mobile+', 300]
: on mobile and up, on portrait -
['mobile+', 300]
: on mobile and up, both portrait and landscape -
['mobile', 300]
: on mobile, both portrait and landscape -
['tablet-', 300]
: on tablet and below, both portrait and landscape -
['mobile-', 300]
: on mobile and down, both portrait and landscape
Generate Media Query strings using the same logic
It is useful when you just need simple CSS. For example with styled-components
:
import styled from 'styled-components'
import { mediaQuery } from '@w11r/use-breakpoint'
const mediaQueryString = mediaQuery(
['mobile-', `width: 100%;`]
)
const Box = styled.div`
${mediaQuery(
['mobile-', `width: 100%;`]
)}
`
// You can still use multiple queries at once just like with the hook:
mediaQuery([['mobile-', `width: 100%`], ['medium+', `width: 50%`]])
This utility comes with additional support for shorthands
which is configurable through options
.
setup({
shorthands: {
foo: '@media (wow: bar) and (hmm: khm)'
}
})
mediaQuery(['foo', value])
Additionally, it supports dark
and light
mode prefixes:
-
(
: Light mode -
)
: Dark mode
mediaQuery([')mobile', 'content'])
// @media screen and (min-width: 376px) and (max-width: 639px) and (prefers-color-scheme: dark) { content }
mediaQuery([')', 'content'])
// @media screen and (prefers-color-scheme: dark) { content }
FAQ
Is there any best practice suggestion?
Yes! Use as fewer hooks as possible. It's always faster to have a single
isMobile
variable and have simple conditions based on it. It's even better
if you can solve your size related cases using pure CSS Media Queries.
Why not using an Object
? Why the Array
structure?
Object's cannot guarantee the order of the defined keys. It is crucial
to check for values in the correct order because useBreakpoint
uses
eager evaluation and mediaQuery
must maintain the defined order of
the generated Media Queries.
Which rule is being prioritized?
The hook uses eager evaluation, so the first truthy breakpoint value gets returned.