DEV Community

CircArgs
CircArgs

Posted on

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.

Top comments (2)

Collapse
 
engelmav profile image
Vincent Engelmann

Very clever. Thanks for the writeup!

Collapse
 
yaireo profile image
Yair Even Or

its unclear in which files you write all this code and how is it available everywhere automatically