Media Query Breakpoints with Styled Components
In every responsive web project, you need media queries to adapt to different screen sizes. Styled components are a popular way to write CSS styles in React applications. This article proposes a way to write media queries with the styled components library Emotion.
CSS Pixels
In order to understand the values of the CSS breakpoints used, it is important to understand CSS pixels. CSS pixels are different from actual screen resolutions for most devices. For example, the Samsung Galaxy S8 mobile phone has a display with physical resolutions of 1440x2960. In CSS, the browser will respond with a resolution of 360x740. These are the device independent pixels. A related metric is PPI, which are the pixels per inch on physical space. Smartphones have a small space, but often a high resolution. So their PPI is quite high compared to normal desktop screens.
The website MyDevice has a very good comparison between physical pixels and CSS pixels.
Breakpoints
So when using CSS queries, it is necessary to align the breakpoints with the CSS pixels.
This is one snippet I found in a Gatsby starter project (Novela) that I find useful:
mediaQueries.ts
import { css } from '@emotion/core'
const breakpoints = [
['phone_small', 320],
['phone', 376],
['phablet', 540],
['tablet', 735],
['desktop', 1070],
['desktop_medium', 1280],
['desktop_large', 1440],
]
const toEm = (size: number) => size / 16 + 'em'
const mediaQueries = breakpoints.reduce(
(acc, [label, size], i) => ({
...acc,
// max-width media query e.g. mediaqueries.desktop
[label]: (...args) => css`
@media (max-width: ${toEm(size)}) {
${css(...args)};
}
`,
// min-width media query e.g. mediaqueries.desktop_up
// This is the breakpoint prior's size +1
[`${label}_up`]: (...args) => css`
@media (min-width: ${toEm(breakpoints[i - 1][1] + 1)}) {
${css(...args)};
}
`,
}),
{}
)
export default mediaQueries
The breakpoints array defines the different breakpoints in CSS pixels and their associated devices.
Styled Components with Media Queries
Styled components are React components that have a style associated with them. Emotion packages styled components in the package emotion/styled. It is based on the template literal string syntax of JavaScript. So you can embed media queries in your styled components like so:
import styled from '@emotion/styled'
import mediaQueries from './mediaQueries'
const Button = styled.button`
${mediaQueries.phablet`
color: black;
`}
color: turquoise;
`
So this results in a button that has a media query of max-width of the phablet CSS pixels (540 pixels).
The reverse would look like this:
import styled from '@emotion/styled'
import mediaQueries from './mediaQueries'
const Button = styled.button`
${mediaQueries.phablet_up`
color: black;
`}
color: turquoise;
`
This result in a media query that has a min-width of the phone CSS plus one, so everything above a phone resolution is black.
This saves you the hassle of writing all the media queries manually and having to set the breakpoints manually.
Conclusion
Media queries breakpoints need not be managed manually, but rather a simple library function can be used instead.
References
-
Emotion: https://emotion.sh
-
MyDevice: https://www.mydevice.io/
-
Gatsby Starter Novela: https://novela.narative.co
Published
15 May 2020