Is CSS in JS Okay?

Enhance!

So, my blog is pretty much my main regular touchpoint for the world of frontend development, outside of the odd bits of React/GraphQL I do at work. Every few months, I'll play around a bit to keep in touch with the world of frontend development, which allows me to maintain a fresh understanding of what's possible in terms of the frontend.

CSS in JS was a thing that for me needed more exploration. Obviously, you could always write inline styles in React components, but I figured the point of CSS in JS was to make this ergonomic - closer to writing normal CSS. I hoped there was also the oppurtunity to reduce some of my overhead when working with the frontend, and in an attempt to make my workflow slicker, I dove headfirst into it. What I found was enough to keep me using CSS in JS practices and technologies in my side project code, but I also came away with some questions about my pre-existing mental model when writing frontend code and also a question on where boundaries between separation of concerns lie in this context.

Workflow Considerations

I thought of my ideal workflow when I'm putting together a page for an application or website - I start by placing elements, then I style these elements in-line so I can iterate quickly, but visually also (usually this is done using devtools). Finally, once I'm in a good place, I crack these out into BEM namespaced styles and clean up/refactor bits. In the end, I usually have a SASS file and a mix of components. One problem I have with this workflow is that to understand how a component actually looks and what it can do I have to bounce between a few files even for my 'leaf' level components.

When you're looking at a component composed of multiple components, this kicks off a bunch of switching between files. Now, some of this is unavoidable to an extent, and I'm sure there are ways I can improve this workflow without using CSS in JS. In the spirit of trying new things, I wanted to see if CSS in JS could solve this problem for me.

Diving In

I picked as my CSS in JS library. Pretty dumb selection criteria - I fired up npm-trends and looked through the most popular libraries.

Not having much skin in this particular game, I took a look at styled-components and it looked okay. Remember, the aim was to just play with the paradigm, rather than pick the best thing.

CSS in JS broadly works via declaring components used in lieu of the standard elements JSX offers.

Here's an example:

const PostBody = styled.div`
  text-align: justify;
  font-family: ledger;
  color: #444444;
  letter-spacing: -0.5px;
`

One thing you can perhaps see immediately is that I'm able to alias the div, which I'm quite a big fan of. It reminded me of aliasing types, and I think when you look at the component itself, makes it that much more declarative. Not that this isn't possible outside of styled-components, but it felt very natural, intuitive and lightweight here. Here's an example:

<Post>
  <PostTitle title={title}>
  <PostBody>
    {paragraphs.map((p, idx) =>
    <PostParagraph key={idx}>
    {p}
    </PostParagraph>
    )}
  </PostBody>
</Post>

There's a lot to like about reasonably declarative code.

As I built up the number of components and pages, it was pretty easy to edit things holistically. Styles were just a Ctrl-P away to edit, and using styled-components I was able to write vanilla CSS.

Cause for Pause

It's not a world away from smooshing styles, markup and scripting all into one file, however. It's not even a different model of separation of concerns, it's a less granular one than the traditional model of styling.

When I use bog standard stylesheets with React, I have components which render fragments of a page, and I can compose these fragments to make up a page. Within each component, React/JS controls markup and scripting, and styling is controlled by SASS. The interface between my styles and markup become class names, and these are pretty strongly physically separated. With BEM though, the styling ends up pretty specific, honing in on a specific element in a component. At what point does the physical boundary just end up being indirection rather than a true separation of concerns? A component without styling has never been very useful to me, apart from project wide components that enforce some standards, but are otherwise overwriteable. You take CSS in JS on the other hand, and the physical boundary is gone - but I don't feel like, coming from BEM formatted selectors, much has changed. I'll need to think more about this one.

What is valuable about the traditional approach is the technology separation - CSS has been around for years and will be here long after React. SASS has been used to extend what CSS can do from a developer experience perspective, and can be used more or less anywhere, with any language with a bit of build script tinkering. With CSS in JS, the JS domain controls markup, scripting and styling directly, and there is no real separation of technologies anymore. The nonchalant decision to pick styled-components in the beginning becomes more of an investment in a real project, as I'm picking a framework that kind of needs to last.

Calling It

I'll keep on using styled-components in my blog. It works nicely, and I'm not too worried about some of the things I've outlined above. It definitely made my workflow slicker, and it felt pretty intuitive to me. At the same time, I'm left with questions about what purpose the separation of styling, markup and scripting actually serve in component architectures and a reminder of the gravity that decisions on frameworks carry in real projects.