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 }
}
}
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%;
}
`
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)}
}
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)}
}
`;
});
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_name
s + theme.media.min.breakpoint_name
s 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%;`}
}
`
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)
Very clever. Thanks for the writeup!
its unclear in which files you write all this code and how is it available everywhere automatically