Media query templates in styled components

Of late, the CSS in JS approach to organizing stylesheets in a project has become ever more popular in the JavaScript ecosystem. I think there are two main reasons for this:

That being said, most people seem to favor one of two approaches to implementing CSS in JS: styled-components, and emotion. Both are similar in many respects, but most of my experience has been with the larger of the two projects, styled components.

In this post, I’ll touch on what I think is one of the neatest parts of how styled components can be used: media templates! Here's what the styled components docs have to say about it:

Since media queries are long and are often repeated throughout an application, it can be useful to create a template for them. Due to the functional nature of JavaScript, you can easily define your own tagged template literal to wrap styles in media queries.

Let me show you how I’m using this approach in this site:

// media.js
import { css } from 'styled-components'

const sizes = {
	// Default styles written mobile-first assuming 320px width
	mbl: 375,
	tab: 700,
	desk: 990,
	deskL: 1200,
}

// Iterate through the sizes and create a media template
const media = Object.keys(sizes).reduce((acc, label) => {
	acc[label] = (...args) => css`
		@media (min-width: ${sizes[label] / 16}em) {
			${css(...args)};
		}
	`

	return acc
}, {})

export default media

I tuck the above code away in the utils directory, and then whenever I need to use a media query in any component throughout the project I can import and use it like so:

// textXL.js
import styled from 'styled-components'
import { dark } from '../utils/colors'
import media from '../utils/media'

const TextXL = styled.h1`
	font-family: Quincy, serif;
	font-weight: normal;
	font-size: 44px;
	color: ${dark};
	line-height: 52px;
	padding: ${props => (props.padding ? props.padding : `auto`)};
	margin: ${props => (props.margin ? props.margin : `auto`)};
	text-align: ${props => (props.center ? `center` : `left`)};
	${media.tab`
		font-size: 48px;
		line-height: 58px;
	`};
`

export default TextXL

And that’s it! There are many more exciting aspects of how to extend styled components, but of all of them, this solution to media queries is by far the most elegant and unique in my view. Hope you enjoy using this as much as I do, and happy querying!


Thanks for reading! Go home for more notes.