The Emotion docs tell us how to make reusable media queries that works in the css prop. This allows us to make the following queries in a css prop:
<div
css={{
color: 'green',
[mq[0]]: {
color: 'gray'
},
[mq[1]]: {
color: 'hotpink'
}
}}
>
With mq[0]
and mq[1]
referring to the first two items in a breakpoints array. For example: const breakpoints = [576, 768, 992, 1200]
.
What's more, this article takes it one step further, by showing up how to get named reusable media queries by using a breakpoint object. It starts by making a similar function as per the emotion docs, but for objects:
const mq = n => {
const bpArray = Object.keys(bp).map(key => [key, bp[key]]);
const [result] = bpArray.reduce((acc, [name, size]) => {
if (n === name) return [...acc, `@media (min-width: ${size}px)`];
return acc;
}, []);
return result;
};
This then allows us to create a breakpoints object with named media queries:
// object
const breakpoints = {
sm: 500,
md: 768,
lg: 992,
xl: 1200
};
// query
${mq('sm')} {
color: gray;
}
So far, so good.
I would now like to do something similar in an emotion styled component. As such, I created an breakpoints object and the same function as mentioned in the above article.
I then tried to use the short hand media query in my emotion styled component -- like this:
import styled from '@emotion/styled'
const Container = styled.div`
${mq('sm')`max-width: 750px;`}
${mq('md')`max-width: 970px;`}
${mq('lg')`max-width: 1170px`}
`
But when I try this, it does not work. I get the following error message:
TypeError: Object(...) is not a function
Any idea why this is happening and what I can do to get it to work?
Thanks.
When writing media queries in styled-components I follow these three steps, and I can only recommend this approach. Define breakpoints based on application needs. Define devices using media query syntax. Apply the media query in the styled component.
The uses for Emotion are very different from those of styled-components. The main feature of this library is that the style composition is predictable for writing different CSS styles using JavaScript. This library supports both string and object styles.
Each media feature expression must be surrounded by parentheses. Logical operators can be used to compose a complex media query: not , and , and only . You can also combine multiple media queries into a single rule by separating them with commas.
A media query is a logical expression that is either true or false. A media query is true if the media type of the media query matches the media type of the device where the user agent is running (as defined in the "Applies to" line), and all expressions in the media query are true.
Using media queries in emotion works just like using media queries in regular css except you don’t have to specify a selector inside the block, you can put your css directly in the css block. Some text! Media queries can be useful to create responsive apps but repeating them is annoying and can lead to inconsistencies.
Media queries with styled components work the same as in CSS! If you want a more involved example with defining different device sizes, continue below. We'll start from a simple webpage that is not responsive and improve it wth media queries! Checkout the code on Code Sandbox. So how to make it responsive using styled components?
So how to make it responsive using styled components? Define the devices for each breakpoint using the usual media query syntax Let's create one breakpoint for each size used in the Chrome Dev Tools: Then, based on the size, let's create a media query for each device supported.
While defining media queries in constants is much easier than rewriting media queries each time, they’re still quite verbose since you usually want to change the same property at different breakpoints. facepaint makes this easier by allowing you to define what each css property should be at each media query as an array.
To clarify, there was mainly a minor syntax error in what the OP had posted (there should be no additional backticks in the interpolated string).
A full example of his code including type annotations would look like:
const breakpoints: { [index: string]: number } = {
sm: 500,
md: 768,
lg: 992,
xl: 1200,
};
const mq = Object.keys(breakpoints)
.map((key) => [key, breakpoints[key]] as [string, number])
.reduce((prev, [key, breakpoint]) => {
prev[key] = `@media (min-width: ${breakpoint}px)`;
return prev;
}, {} as { [index: string]: string });
const Container = styled.div`
${mq["sm"]} {
max-width: 750px;
}
${mq["md"]} {
max-width: 970px;
}
${mq["lg"]} {
max-width: 1170px;
}
`;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With