In Defense of CSS

Matt Clough
7 min readDec 12, 2016

--

Repos should be well-maintained. Syntax should be highlighted. Source code should be indented. Anything else is chaos. A programming language and uncompiled source code and syntax theme and repo should be praised if it’s good, and blamed if it’s bad, and anyone who praises the bad and speaks ill of the good — I think we can all agree — is just silly. Being a person of great rectitude, I am obligated to speak truth and refute ill speech where it is undue, and thus I am obligated to refute those who speak ill of CSS.

Before the adoption of CSS, the only way for a developer to style elements was by adding styles inline. That meant, for example, if borders needed to be changed from 2px to 4px, the style would need to be changed on every single bordered element on every single page of a site. Let’s say all buttons on a site should have a white background that changes to blue when the mouse hovers over the button. Before CSS that might look something like this—

<button style="background-color: 'white';" onmouseover="this.style.backgroundColor='blue';" onmouseout="this.style.backgroundColor='white';">Button</button>

That wasn’t a huge problem in the “web 1.0” era, but as sites grew larger and more complex, the amount of time it took to change styles across an entire site became impractical.

CSS brings the promise of “change it once, change it everywhere”. Rather than going through a site and changing the background color and hover states on every button, you can easily go to the stylesheet and change all buttons with as little as two lines.

button { background-color: 'white'; }
button:hover { background-color: 'blue'; }

This has the added benefit of making markup a little more legible. CSS also provides the indispensable ability to style elements for different browser widths, as well as pseudo-elements to style different parts of an element.

Why It Gets Gross

The ability to change one line of CSS and affect elements site-wide with no constraints is powerful. On top of that, CSS (cascading style sheet) is evaluated in a cascade, that is, from the top of the file to bottom; rules can always be easily overwritten. There’s also no real concept of scope. In programming, variables can have the same name with different values as long as they’re in different scopes — not so in CSS. If two selectors are identical, the last selector will have precedence.

Taking all this into account, it’s easy to see how a few people working on even a moderately sized site can easily step on each other’s styling toes. In order to avoid this there is a natural tendency to write more specific selectors. The thought is

“Well, h1 is already styled, but the h1 inside of this section needs to look slightly different. I’ll just give this an id and select section#special h1 so I don’t mess anything up.”

That selector is particularly gnarly for a few reasons, including its effect on browser performance[1], but adding specificity[2] by adding an id to the selector overrides the style of global h1s and isolates the style to that particular section. Sound confusing? It is! And when this kind of thing is perpetrated a number of times by a few people, it can happen over and over as a means of dealing with the confusion and dissolve any established system and either negate CSS’s usefulness, or completely turn it against itself.

So, CSS can be a little dangerous, but it’s only because it’s so powerful! The disastrous results of throwing water on a grease fire wouldn’t convince anyone that we should stop using fire. CSS, like fire, just needs to be handled carefully and deliberately.

Fortunately, people are starting to realize there are some ways to avoid starting a style grease fire, even in large-scale sites and apps.

Semantic Methodologies

A number of CSS methodologies have been developed whose primary purposes are to clarify markup, lower selector specificity, and encourage a systematic breakdown of UI components. The one we’ve used at Mobelux is known as BEM. The idea of BEM, which stands for block, element, modifier, is that UI components can be broken down into root classes — blocks — that contain elements, and can be modified. For example, consider a photo gallery. This is how it might be broken down in BEM.

<div class="gallery gallery--square">
<div class="gallery__slider">
<div class="gallery__item">
<img class="gallery__image" src="...">
</div>
<div class="gallery__item">
<img class="gallery__image" src="...">
</div>
<div class="gallery__item">
<img class="gallery__image" src="...">
</div>
</div>
<div class="gallery__controls">
<div class="gallery__previous">
<div class="gallery__next">
</div>
</div>

The component, or block, is given a class gallery. Elements of gallery are indicated using double underscores, and variations or modifications are indicated with double dashes, in this case gallery is being modified with gallery--square. Preprocessors that enable nesting are particularly helpful in writing BEM. This component, with nesting, would look something like this

.gallery {
&--square { ... }
&__slider { ... }
&__item { ... }
&__image { ... }
&__controls { ... }
&__previous { ... }
&__next { ... }
}

Yes, typically nesting in CSS, as we’ve already discussed, is bad juju, but when this is compiled, the resulting CSS looks like this

.gallery { ... }
.gallery--square { ... }
.gallery__slider { ... }
.gallery__item { ... }
.gallery__image { ... }
.gallery__controls { ... }
.gallery__previous { ... }
.gallery__next { ... }

The idea with BEM is to achieve flatness of specificity by giving everything a unique class that explains what the class does. This way, anyone should theoretically be able to jump in and confidently change things with a clear understanding of what’s going on. In my experience, done right, and with practice, BEM is really great way to not only keep CSS specificity low and avoid grease fires, but to build strong UI breakdown skills.

Functional CSS

There is an approach to CSS that aims to limit the amount of CSS written overall known as f(CSS) or functional CSS[3]. I’ve mentioned that CSS is powerful stuff, and functional CSS takes this power to its logical conclusion. Functional CSS is a bunch of minuscule classes that do one thing and only one thing. They are meant to be combined on an element to compose the element’s style. The classes never change, and the result of applying the classes is always the same. Want to give an element 100% width, a blue background, white text, and a box shadow?

<div class="w-100 bg-blue white shadow"></div>

Coming from writing styles inline, to then writing CSS with the precision of a child with finger paints, to finally getting it together and writing some decently organized and semantic CSS, functional CSS is puzzling and a little hard to accept at first. In fact, functional CSS kind of creeped its way in to our practice at Mobelux. At first it was just —

“Instead of giving all these buttons color modifiers, let’s just have a class called .bg-blue. So many other things on this site also have a blue background.”

Font colors followed shortly after, then paddings, and margins, and widths. It’s hard to look at it though without thinking, “How is this not inline styling?” That’s a valid question. It does appear to be very much like inline styling. However, it has the powerful backing of CSS with media queries, pseudo-classes, etc. Say, for example, an element should be 100% width at mobile viewport size, and 50% at a medium size, and 25% at a large size. Functional CSS could make that happen like this

<div class="w-100 w-50-m w-25-l"></div>

In this example, width classes are namespaced with a leading w-, followed by the percent width, followed by the viewport size (mobile doesn’t get one because you’re styling mobile first, right?)

Something else you might be asking yourself is —

“So what happens when I want to update a component’s style across the whole site? Won’t I have to update it a thousand times?”

Also a valid question, because if you’re just writing plain old HTML, that’s true. If you’re using a templating engine however, you’re massively in luck, because you can wrap all your components up into a partial or a much better option — a React component.

There are a few great functional CSS libraries out there already. I’ve been taking a hard look at Tachyons.

CSS Modules

The web is becoming more and more modular every day. CSS Modules are a fascinating answer to our componentized, Reactified future. The idea is fairly simple, but it relies on some other software to make the magic happen. Let’s say you have a component in React that needs some styling

import React from 'react';

const Component = () => (
<div>
<div></div>
</div>
);

It’s pretty boring at the moment, so you write a stylesheet for it.

/* component.css */
.component {
background-color: black;
color: white;
}

.child {
width: 50%
}

With CSS Modules, you can combine the two by simply importing the stylesheet into the component’s javascript.

import React from 'react';
import styles from './component.css';

const Component = () => (
<div className={styles.component}>
<div className={styles.child}></div>
</div>
);

When the styles are imported, the classnames are automatically given a unique hash to guarantee that they are scoped locally and will never override each other. It doesn’t matter if you’ve got another stylesheet for another component that also has a .child class, they won’t bother each other at all. CSS Modules also have the ability to compose or inherit from one another, a.k.a. @extend for all you SASS people (it’s okay if you weren’t aware of it, you probably shouldn’t be using it with SASS anyway).

Wrapping It Up

Yes, CSS has its problems. But, I ask, what in the world wide web doesn’t? Maybe it was too much too soon, or maybe the rest of the web just outpaced CSS in growth. It is getting better though, and even the best solutions to CSS’s biggest problems only serve to highlight the fact that CSS doesn’t really suck, we’re just still figuring out the best way to use it.

Now, please direct all your angry thoughts to me on Twitter @cluffpost ✌️

--

--