Thomas Derflinger BlogFR

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. Smart phones 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 16 May 2020

Thomas Derflinger

Thomas Derflinger

I am an independent entrepreneur and software developer.

Web is a topic I really enjoy. Let's get in touch!