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

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 :-)