Never write media queries hard-coded in styled components; always create variables for them.
Let me explain why…
CSS clamp
and calc
functions help a lot in making sites responsive without media queries. However, there are still cases when we need media queries. For example, adjusting the layout for different screen sizes, showing or hiding elements at a particular size, or adapting typography for various devices.
In previous issues of our styled components article series, we have talked about how to structure styled components in a React app, the ways to write reusable styles, and in the last article, we learned how to write reusable Flex components for faster development.
We have covered many things. Today, we are going to see how to write media queries in styled components for a production application.
Let's learn it step by step.
Let's start with an example. Imagine we have three cards displayed in a row, but we want them to stack in a column layout if the screen size is 600px
or less.
Here's how you could write the media query without optimizing it so we can see the difference.
const BlogCardsContainer = styled.div`display: flex;justify-content: space-between;@media (max-width: 600px) {flex-direction: column;}`
This approach works well; however, there are several problems with hard-coding media queries:
- We have to remember all the breakpoints.
- If you need to make changes to the UI, such as applying smaller screen changes
(600px)
to tablet screens(768px)
, you would have to manually locate and update every instance of the media query in the code. - The third problem is that it's not user-friendly; every time we have to repeat
@media (max-width:600px)
.
To address these problems, a better approach is to create a separate file called breakpoints.ts
(assuming you are using TypeScript with styled components) in the styles folder for media queries. In this file, you can define all the breakpoints as an object.
interface Size {xs: stringsm: stringmd: stringlg: stringxl: stringxxl: string}const size: Size = {xs: '400px', // for small screen mobilesm: '600px', // for mobile screenmd: '900px', // for tabletslg: '1280px', // for laptopsxl: '1440px', // for desktop / monitorsxxl: '1920px', // for big screens}export const device = {xs: `(max-width: ${size.xs})`,sm: `(max-width: ${size.sm})`,md: `(max-width: ${size.md})`,lg: `(max-width: ${size.lg})`,xl: `(max-width: ${size.xl})`,xxl: `(max-width: ${size.xxl})`,}
With this setup, you can now write media queries in a more optimized way:
const BlogCardsContainer = styled.div`display: flex;justify-content: space-between;@media ${device.sm} {flex-direction: column;}`
By using the device
object and accessing the appropriate property (sm
in this case), we have solved the three problems mentioned earlier. It's much easier to remember and update breakpoints since they are defined in a central file, and the code becomes more readable and user-friendly.
Isn't it awesome?
Now the question is, can we further improve it?
Yes we can, the repetition of @media
by optimizing it using the css
function from styled-components
. Here's an example of how you can achieve this:
But it personal preference, if you like this approach you can implement it.
import { css } from 'styled-components'const device = {xs: '400px',sm: '600px',md: '900px',lg: '1280px',xl: '1440px',xxl: '1920px',}const media = {xs: (...args) => css`@media (max-width: ${device.xs}) {${css(...args)};}`,sm: (...args) => css`@media (max-width: ${device.sm}) {${css(...args)};}`,md: (...args) => css`@media (max-width: ${device.md}) {${css(...args)};}`,lg: (...args) => css`@media (max-width: ${device.lg}) {${css(...args)};}`,xl: (...args) => css`@media (max-width: ${device.xl}) {${css(...args)};}`,xxl: (...args) => css`@media (max-width: ${device.xxl}) {${css(...args)};}`,}
Now you can use the media
object to write media queries more concisely:
const BlogCardsContainer = styled.div`display: flex;justify-content: space-between;${media.sm`flex-direction: column;`}`
The same pattern can also be used with SCSS by making syntax modifications.
I hope you learned something useful in this article.
If you want to learn
If you want me to write an article on how I make font-size, margins and paddings responsive using CSS clamp and calc functions without writing media queries, let me know via email at [email protected], LinkedIn, or Twitter.