Responsive Styled Components in 3 Minutes (and 18 lines of code)

Matt Granmoe
Aug 30, 2017 · 4 min read
(I may need to level up my GIF skillz)

Motivation

Some weeks ago, while working on some quick SPA prototyping, I found myself wanting, nay yearning for, a declarative and elegant responsive design library in React. I also discovered that I could no longer brook the oppression of being forced to clutter my components with class names, themselves powerless without separately defined rulesets, and at the mercy of a chaotic and unforgiving global namespace. I was offended by this needless bifurcating and convoluting of code undertaken solely to attach styles to markup. I decided on that day, drawing inspiration from such spiritual luminaries as mxstbr and tkh77, to transcend this primitive and torturous blood-rite. And so I npm installed styled-components. “Just styled-components,” you say? Yes. “Don’t we need bootstrap? Or some other library?” No and no. I built what I needed for my purposes using only styled-components and about 30 lines of code. Let’s relive my journey together. ***sitcom flashback music***

API

The first step (as often seems to be the case) is to ask, “what would the ideal API for this look like?” My initial instinct is this:

This is OK, but it doesn’t seem like the simplest possible API for the use case. Since the breakpoints are not likely to change at runtime, and we don’t want to be manually passing those props all the time, the usage could be more along the lines of this:

This looks much more readable and descriptive. Now, it would be great to make this flexible enough to have components that conditionally show within any arbitrary widths: small only, extra large only, medium and greater, large and lower, etc. What would that look like? Maybe something like this:

So that’s the end result we’d like. What would the simplest API to create those components look like? How about:

Sure, it’s equivalent to the more direct,

but the point is that we can create styled components programmatically, which opens the door to many possibilities. For example, what if we wanted to generalize this functionality to allow passing in any arbitrary set of style rules, not just display: none;? Well, then I guess we would need a function that takes in breakpoints and style rules and returns a styled component. To take a contrived example, if I wanted to have a responsive fonts styled component, I might wish to create the component like this:

(Sidenote: not sure why js fiddle formatting freaked out on me here. Sorry about that.) Lastly, I’d also like to be able to pass in an optional tag name — I had been assuming we’d just use a div up until now. Passing a tag name would just be another param:

Implementation

Now that we’ve designed an API, let’s implement it. I’ll start with our most important function, makeResponsiveComponent. This will take in the params and return a styled component, so it should look something like this:

OK, so we need to implement buildStyles and build a string from an array. Time to bust out the old Swiss Army knife, reduce:

Sweet. Now, can we reuse this general logic to implement our sugared-up hideAt function? Easily:

As you can see, I’m just converting the arguments passed to hideAt to the format that makeResponsiveComponent expects, so that I can call that function and return the result.

This is all well and good, but I have one more tiny wish for the API. I’d like the consumer to be able to use hideAt as a component. I’ll call it <Breakpoint>:

That should do it! Here’s the full code:

Demo

Now go play with this code in codesandbox :-)

Thanks

Thanks for reading! And thanks to the developers of styled-components for making an amazing library!

Important Note

So this was a fun exploration. A learning experience regarding the styled-components API and how it can be easily abstracted to provide a more custom API for specific use cases. However, in my particular contrived example, I think it’s probably more direct and simple to just stick to the normal styled-components API. E.g. just do export const Small = styled.div... with all the media queries and rules laid out explicitly. Perhaps I’ll write another post that demonstrates this and call it “Responsive Styled Components in 1 Minute” :-)

Update (1/5/2018)

I just learned of the facepaint library for emotion, written by the emotion team, which is quite similar to what I created in this post, plus a few more bells and whistles. I’ll take this as validation that my approach here is not as superfluous as I might have thought :-)

💅 styled-components

Visual primitives for the component age.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store