This post is an opinion about CSS-IN-JS. There are many like it but this one is mine.
It started on my bus home.
How 'bout that CSS-in-JS? pic.twitter.com/mcR9scUhQq— Brad Frost (@brad_frost) May 8, 2018
I cannot help but be slightly triggered by the tweet. The code snippet demonstrates a fundamental misunderstanding of React and how to apply styles to React components. Anyone seasoned in front end cringes. But to package this up and say “How ’bout that CSS-IN-JS?” really misses the mark for me. This is not Brad’s code (he knows better): it’s a strawman. Perhaps a throwaway joke. But what it also does is dangerously conflate CSS-IN-JS with inline styles. To associate that code with CSS-IN-JS is disingenuous. Some readers of that tweet may misunderstand Brad’s intent and come to the conclusion that this code is representative “state-of-the-art” CSS-IN-JS. We aren’t constructively furthering the conversation this way. Most CSS-IN-JS solutions now output classes. Full stop.
We Drive into the Future Using Only Our Rearview Mirror
We all take for granted at this point how wrong the above code looks. We (I liberally assign myself in the following camp) come up in a world where CSS became more and more powerful and standardized. We can make CSS do some truly magical things. I revel in making CSS do amazing things just as much as the next developer. I’ve sweated the details within custom keyframe animations, crafted complex responsive layouts, built whole component libraries from scratch atop a BEM
block--element__modifier tower. It felt great.
Now, the product I work on at my job helps other teams write products quickly. It’s primarily a React application, so a modern front-end stack is expected. It can be complicated. We use a CSS-IN-JS technical solution as part of this product. JSS to be exact ,though the specifics do not matter to me for the purposes of this post.
I find it useful to look at a simple styled React component as a gentle introduction to a lot of concepts.
I have a co-worker that is not cut from the same cloth as I—he has little prior front-end experience. The muscle memory of dev tool inspection, source maps,
.scss @imports, and the like is not present in him. Hunting for a static class name in a file somewhere, or worse, a descendant selector feels daunting. Same-file collocation allows the styles that affect the component in question to be next to the markup and functionality. On purpose. Contained. As a single portable component.
Rather than forcing him to learn and follow a convention, the styling is right there for the reading alongside the component he implements.
Consume the Primitives
CSS-IN-JS (as the second step of React’s HTML-IN-JS approach) makes sense because it puts the most primitive functionality inside the most powerful, allowing for the powerful features to augment the primitive. This is what the smartphone did to clocks, contact lists, calendars, notepads, ad nauseum. Now my smartphone can schedule a meeting with someone halfway across the country at the right time for both of us—by helping me string together a bunch of separate concerns into a single flow.
Let’s look closely at the styles in the above snippet. Yes, it’s simple.
background. All properties we are familiar with. But look at the value for
Media queries work.
CSS fundamentals are required—but we have some powertools in our workshop now. Got lots of classes to manage? Look no further than classnames.
And yes, we still need progressive web applications. We still need
@supports feature detection, we still need to cut the mustard. We still need web design. CSS-IN-JS does not significantly erode or impede these necessities should someone need to build for them. I hope none of this persuades you otherwise!
Guess what? Your CSS badassery translates into a CSS-IN-JS solution. Teams still need an expert to own the craft of applying visual styles to markup. Doing so correctly and in a scalable manner is still key. All those years of accrued knowledge fighting browser quirks, consulting caniuse, learning CSS grid, clip-paths, gradients, etc, has only made me more powerful in a CSS-IN-JS world. It has translated just fine. I still need to know CSS in order to make something look the way I want to.
There is a time and place for every tool. CSS-IN-JS makes a lot of sense in a lot of situations that I have encountered in my real-life™ work helping teams. Sass continues to be my go-to everywhere else. Are you building a design system? You may need the portability of the primitive (Brad mentions this in the article below). I doubt I’ll ever advocate CSS-IN-JS to my personal clients—because I am interested in crafting right-sized solutions and most people I serve haven’t needed something so heavy. But for teams building large apps atop React it feels like a sane way forward.
I end with this.
There’s been some knee-jerk reactions from different communities (incl. React) to what Brad is posting as he’s exploring front-end libraries. Let’s remember we can disagree about a lot and still teach each other amazing things— Dan Abramov (@dan_abramov) May 9, 2018
I respect Dan’s perspective here. He’s very much on the cutting edge of modern front-end development and yet understands where we all came from and that together we need to go somewhere new.
P.S. I love Brad. I work with him, for goodness sake! While I was writing this post, Brad tweeted this and wrote this.
For what it's worth, I'm very aware I'm throwing some zingers around without really sinking my teeth into it. I'm very much open to learning more about it, but I do remain skeptical. Hopefully this post explains a bit of my apprehension a bit better: https://t.co/6vFKhT9Tbo— Brad Frost (@brad_frost) May 9, 2018
I'm very open to listening and learning more, and I'm excited to have started some great conversations with people who work with different approaches and swear by it.— Brad Frost (@brad_frost) May 9, 2018
I felt triggered today by Brad’s tweet, but also because there are folks where I work expending valuable energy, money, and creative exhaust building CSS only solutions, missing out on an opportunity to explore new territory. They see Brad’s of the world as standard bearers of the familiar, as I do. I think the problems Brad highlights are valid and warrant pause. Teams need to ultimately decide what is best for them over the lifespan of their product. I hope they try different approaches and construct an informed opinion.
And then, as my friend puts it, I hope they share what they know.