Inline CSS Works Better in a Component World

If you learned web development more than a few years ago, then you probably learned (were told) that inlining CSS into your HTML like this is wrong:

// display 'some content' in a box <div style="width: 100px; height: 100px; border: 1px solid black;"> some content </div>

CSS has classes, allowing you to group together style rules and give them a name. You should use these:

// display 'some content' in a box <style> .box { width: 100px; height: 100px; border: 1px solid black; } </style> <div class="box">some content</div>

They both do the same thing, so why are classes 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.

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.

You abstract the styles away from the markup, meaning your content and the way it looks have no implicit dependencies on one another, only a reference via the class attribute. You can even put your styles in a different file. You can easily make the div a circle, instead of a box, by replacing this class, but it'll still display the same content.

These reasons all sound good, because they enable things we want. But will they really work in practice? I'd argue not really, in a modern web app.

To see why, let’s dig in on that third point in particular. We might want to change the way we present the same content, sure. But what does content actually mean here? Does it mean markup? I don’t think it really does.

Why? Because in modern web apps we don’t only render content in simple single-element containers like boxes and circles, but in drawers, modals, floating panels and other complex, multi-element components.

That means the class often doesn’t work as a way to define how a component looks, because changing that means more than changing the class of a single container. In practice it usually means completely changing the markup, and dropping the same content (the same copy, images, etc) as appropriate into this new structure.

All web frameworks have a good abstraction for this, of course: components. In a component, you can define the markup however you like and provide an interface where you pass the content as attributes, and then inject it as appropriate into the custom markup structure. You also call the component whatever you like - usually something like Drawer or Modal, and use that as a tag just like divs or spans.

In this way, you can just use components in a template the same way you can use single element divs or spans. Just type the component tags and plug in the content. This already obviates the need for classes as a way to specify how content should look.

In other words you go from this:

// some content in a square <div class='square'>some content here</div> // change to a circle <div class='circle'>some content here</div>

To this:

// some content in a drawer <Drawer>some content here</Drawer> // change to a Modal <Modal>some content here</Modal>

In modern web applications, it's pretty self evident that components are the right solution, the right abstraction. But even in a component world, CSS classes and external stylesheets hung around.

Why? Because in the old world, dominated by the old abstraction, there was a rule that you weren’t supposed to mix styles and markup. The reason for the rule was sound because as we've discussed, classes were components and the markup was content.

In a component world, though, that's no longer true, so the rule is redundant. 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 way a Modal looks, where do you go? To the Modal 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 elsewhere, so when you change a box you also change the thing that looks a bit like a box but slightly different, that you wanted to keep looking the same. It’s messy and more work than necessary.

The class still has one standout great feature, though. Because classes are referenced by simple string names, they are really easy to dynamically create, choose between and combine in a way that inline styles are not in a string-based HTML templating language. Creating actual CSS in such a templating language is messy and difficult.

That’s probably why it took the arrival of React for it to finally become more obvious that the 'no CSS in markup' rule makes little sense in a component world. The reason is that 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 string building 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 just aims 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 provided in libraries such as styled-components in React that actually use classes under the hood but give you inline-style syntax in your component code through other means. It’s the same concept though, the syntax is not important but the fundamentally 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.