Trivial Media Queries with Styled Components in React

circargs

CircArgs

Posted on December 6, 2020

Trivial Media Queries with Styled Components in React

The sometimes overlooked css tag in styled-components can give you a hand in writing media queries in your styles.

Suppose, for instance you have the following breakpoints (in px):

let theme = {
    breakpoints: {
        mobile: { value: 450 },
        tablet: { value: 700 },
        desktop: { value: 900 }
      }
}
Enter fullscreen mode Exit fullscreen mode

You may be setting up a reset for your app like so:

const GlobalStyle = createGlobalStyle`
*, *:before, *:after{
  padding: 0;
  margin: 0;
  box-sizing: inherit;
}

html{
  box-sizing: border-box;

  /* set default font size i.e. 1rem to 62.5% of 16px=10px */
  font-size: 62.5%; 
}
`
Enter fullscreen mode Exit fullscreen mode

But maybe you want that default font size to change by your breakpoints!

You could write ordinary media queries throughout your app, but that's a bit clunky eh?

@media only screen and (max-width: ${theme.breakpoints[bp].value / 16}em) {
      ${css(...args)}
    }
Enter fullscreen mode Exit fullscreen mode

That's where css can come in...

import { css } from "styled-components";

theme.media = {};
Object.keys(theme.breakpoints).map(bp => {
  theme.media[bp] = (...args) => css`
    @media only screen and (max-width: ${theme.breakpoints[bp].value / 16}em) {
      ${css(...args)}
    }
  `;
});

theme.media.min = {};
Object.keys(theme.breakpoints).map(bp => {
  theme.media.min[bp] = (...args) => css`
    @media only screen and (min-width: ${theme.breakpoints[bp].value / 16}em) {
      ${css(...args)}
    }
  `;
});

Enter fullscreen mode Exit fullscreen mode

What's going on here?

As the docs suggest, the css function isn't so dissimilar to styled-components' usual styled.tag_method in that it will interpolate for you (the usual ${props=>props.blah}). What we're doing here is creating our own tags (the theme.media.breakpoint_names + theme.media.min.breakpoint_names for max and min queries respectively) that we can use to generate css that will be interpolated in the usual styled.tag_method!

Now make the font size responsive:


const GlobalStyle = createGlobalStyle`
*, *:before, *:after{
  padding: 0;
  margin: 0;
  box-sizing: inherit;
}

html{
  box-sizing: border-box;

  font-size: 62.5%; 
  ${theme.media.tablet`
    font-size: 50%;`}
  ${theme.media.mobile`
      font-size: 40%;`}
}
`
Enter fullscreen mode Exit fullscreen mode

Easy 😎

Note: if theme is not in scope you'll need to use a callback e.g. props=>props.theme.media.tablet through which styled components will hydrate props with your theme given it through context


Thanks for reading. Think this is a useful pattern πŸ€“? Let me know! Think it's junk? Let me know what's better πŸ’‘ Questions? Just Ask ⬇️

You can see this post on my personal site as well.

πŸ’– πŸ’ͺ πŸ™… 🚩
circargs
CircArgs

Posted on December 6, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related