Functional CSS

I've been experimenting with Functional CSS since reading Adam Wathan's excellent article which I came across from the Smashing Magazine's blog. To me, the separation of HTML and CSS into content and style has always been a bit of an Emperor's new Clothes situation; you have to write your HTML this way or that way, adding all sorts of <div> structures etc. to get the layout you want, and the structure you use will be different whether your CSS uses floats; flexbox; grid or something else.

I work with Drupal a lot and so I'm used to dealing with default HTML templates with umpteen layers of <div> each with a half a dozen or so class names. This led me to trying to do everything in CSS - I had a class defined to identify pretty much anything in HTML, so now focus on styling those in CSS. I always resented having to edit an HTML template.

Then I started ditching the heavily-structured Drupal elements and classes and CSS, writing more and much simpler HTML templates containing only classes I'd need and this helped; my CSS got lighter and more easy to manage.

So functional css - the idea that once you've got a lot of very small CSS rules in place you can do all your designing in HTML - sounded appealing. Could it be true?

Specificity

I tried a couple of small projects with it but am now drawing further away from the pure-functional end of the spectrum. One of the beauties of functional CSS is that it is very low specificity; it saves you from runaway specificity where you find you need to override something that already has high specificity and the only way to do it is with more specificity. However I found that this was at the cost of one of the beauties of CSS - the C (cascading). If you want all your links in an element to be green, you don't need the user to input (or a programmatic HTML filter to apply) <a class="green"> every time; you can just create a rule for the parent. But then you can't use functional CSS classes within that element because they'll have lower specificity!

Interactive/responsive/context-aware styles

This was the other area that felt suffered in functional css. The Tachyons project brings in class suffixes like Bootstrap does, e.g. green-xs might apply green only to extra small devices.

I started defining classes without responsiveness, then as and when I needed them to be responsive, I added responsive versions. However I found that I was making more and more things responsive, multiplying the number of CSS rules. When you get to something like borders for a specific side and colour, you end up with

A border rules × B colours × C side options × D breakpoints.

...all of a sudden I had 450 rules, even though I'd only ever use a tiny subset of these.

Another example is hover states. You can add a green-hover class if you like, but what if you want it green when an ancestor element is hovered, e.g. for a cards design where the entire card is clickable?

SASS

I use the CSS preprocessor SASS and I found this was not an ideal tool for generating functional styles. In the end I was writing code like this:

// SASS/SCSS code:

// Project configuration:
$spacing-list: 0.5rem 1rem 2rem 4rem;

// Generate functional classes for margin top.
@for $i from 1 through length($spacing-list) {
  .mt-#{$i} { margin-top: nth($spacing-list, $i); }
}

// Provide a mixin for use elsewhere to help stick
// to the same configured functional styles
@mixin mt($i) {
  margin-top: nth($spacing-list, $i);
}
// e.g.
.mycomponent h2 {
  @include mt(1);
}

Stepping back from the edge

I'm now stepping back from the very functional (Tachyons) approach. Adam's article (do read it) offers some wisdom here, he says to start functional, but then to abstract patterns as they come up.

As usual with all these things (e.g. SMACSS, BEM) etc. they're all good ideas, children of good ideas and frustrations, but they all have their limitations. The challenge is how to take the useful bits and hopefully move closer to beautifully presented creative designs, with easy to maintain, efficient CSS and accessible HTML.

Add new comment