How I learned to stop worrying and love inline CSS

If you learned web development more than a few years ago, before React came along essentially, then you probably learned (were told) that inlining CSS into your HTML is wrong

<div style="width: 100px; height: 100px; border: 1px solid black;">
bad
</div>

CSS has classes, allowing you to group together style rules and give them a name.

<style>
.box { width: 100px; height: 100px; border: 1px solid black; }</style>
<div class="box">
good
</div>

Why is this better?

  • You’ve made the styles reusable. You can use a box anywhere and then if you want to change how any box anywhere looks, you change that in one place. Yep, this is convenient.
  • You’ve given the style a meaningful name, it’s obvious when reading the markup that the div is a box. You can search for boxes in the markup very easily. Yeah, much better.
  • You’ve abstracted away the styles from the markup. This means your content and your styles are separate entities with no implicit dependency on one another, just a reference via the class attribute. You can even put your styles in an entirely different file. You can easily make the div not a box, but something else like a circle, by replacing this class, but it will still display the same content. OK, the result sounds like something I want but.. will that really work in practice?

Let’s dig in on that third point. We might want to change the way we present the same content. But what does content really mean here? Does it mean markup? I don’t think it really does, in a modern web app.

Why? Because we don’t just render things in boxes and circles — single styled div components — but in drawers and modals and floating buttons and other more complicated, multi-element components.

This means that the class often doesn’t work as a way to define a component, because changing component means more than changing the class of its container. It means completely changing the markup, and dropping the same content (i.e. the same copy, images, etc) as appropriate in this new structure.

Fortunately, most if not all web frameworks have a better abstraction for this: components that you can define the markup for and call whatever you like (probably something like Box or Circle) and then drop into markup via an HTML templating language where you pass the content as attributes to the component.

This is the right solution, the right abstraction. But for some reason, classes and external stylesheets hung around. Why? Because there was a rule that you weren’t supposed to mix styles and markup. The reason for the rule was that it made the old abstraction work. But that reason became mostly redundant with the new component abstraction, but the rule lived on anyway without being questioned much because that’s what rules tend to do.

Components give us the opportunity to actually inline or colocate styles with the component markup, while still taking care of the three points listed above. This is actually a great thing! When you need to change the style of a box, where do you go? To the Box file of course. And if your markup and styles are right there, either inlined into the markup or colocated with it, you change them and you are done. What’s more, you know for a fact that nothing references those styles and nothing else will therefore be affected. In the model of referenced classes in an external stylesheet, both these things are no longer true. You have to link to another file. You don’t know where else that box class is secretly referenced just as a quick hack. It’s messy and more work than necessary.

The class still has a winning feature, though, in not-so powerful templating languages. Because classes are referenced by strings, they are easy to dynamically create and choose between in a way that inline styles are not.

Perhaps that’s why it was the arrival of React where people did finally realise that the ‘no CSS in markup’ rule made little sense. JSX, React’s templating language, has the full power of JS. So building inline styles is trivial — elegant even — with simple JS objects such that it’s actually cleaner to do this than to use the string building tricks of old to reference classes.

Of course there’s a lot more to it than just this, but that’s outside the scope of this blog post, which has been drafted quickly and mainly just to discuss the main point about inline CSS making more sense in a component world. But just to quickly enumerate a couple of advantages class-based CSS still has over inline

  • Probably better compression by not repeating styles everywhere in server rendered markup (imagine you have 100 of the same element rendering the same inline styles 100 times vs in 1 class)
  • Better dev tool support, in general

Although there are more powerful abstractions (libraries) such as styled-components in React that actually use classes under the hood but give you inline-style syntax through other means. It’s the same concept though, the syntax is not important but the inline nature is — that is that the styles are embedded into the component itself and not external to it and referenced, making things much cleaner, clearer and more easily maintained.