Functional CSS with Special Characters

Preamble

Working with Tachyons has completely changed how I think
about CSS. I highly recommend trying it out. Everything below is heavily
influenced by Tachyons.

Crazy Example

I’m working with a Handlebars template that builds blog posts using a markdown function. In this example <p> tags are styled by default with:

p {
margin: 1em 0 1.25em;
}

Handlebars template:

<div>
{{{markdownify article.body}}}
</div>

Output from markdown:

<div>
<p>Hello, World!</p>
<p>Hello, Earth!</p>
</div>

The margin-top from the first <p> tag will push the article body down by 1em. However, the UI designer wants the first paragraph of all articles to have no margin-top.

In the past, my first thought would be to follow BEM and create an .article class with an .article__body “element” that controls margins of child <p> tags. This does work, but, I want to address something that I don’t think we put enough time into. My first thought was to write more CSS. And not just more CSS, but CSS that is highly specific to a certain UI component.

What if the UI designer wants any other piece of the UI to have no margin-top? Do I accumulate more and more classes like .article? And what about the .article__body class tells me as a developer that the first <p> tag has no margin-top? What if it’s not a <p> tag that should have no margin?

The solution is to create a generic functional class that conveys exactly what it will do:

/* _margins.css */
.mt0\:first-child :first-child {
margin-top: 0;
}
<!-- index.html -->
<div class=”mt0:first-child”>
<! — no more margins :) →
<p>Hello, World!</p>
<p>Hello, Earth!</p>
</div>

This looks kind of crazy at first, but once you understand the naming conventions behind this bit of CSS you will intuitively understand what it does.

BEM

Some of the problems with BEM and similar methodologies of writing CSS are:

  1. At a glance, you have absolutely no idea what any specific class does. What does .article__body do to itself or it’s children?
  2. BEM, SMACSS, OOCSS, etc., promote writing more CSS instead of writing generic reusable CSS.
  3. Soon enough, you will have a million nondescript and highly specific classes that all do similar things and aren’t composable or reusable.

These CSS methodologies promise to reduce CSS specificity, and they certainly achieve that. But they do so by tightly coupling CSS to specific pieces of UI. Look at how Bootstrap works for an example of this. Better yet, try to remove a border from a .btn without creating a new class.

Functional CSS

Here’s some food for thought: did you know that CSS has 3 values for float? They are: left, right, and none. How many occurrences of float exist in your CSS? You can find out by copy and pasting the below in your terminal:

$ grep -o ‘float’ -r ./path/to/css/dir | wc -l

I ran this on a legacy project’s SCSS directory and found over 40 unique occurrences of classes with floats. 40. Let’s reduce that number to 3.

.fl {
float: left;
}
.fr {
float: right;
}
.fn {
float: none;
}

Now we can float any element we want without writing or transpiling any CSS at all! Just by adding .fl or .fr to an element. By using this simple naming convention we can convey huge meaning with our styles.

Naming Functional CSS Classes

  1. Start with a base class name.
    We shorten the property display to d.
  2. Determine modifiers.
    What values do we want to represent with this class? In my codebase I want none, block, and inline-block.
  3. Put it all together:
/*
Base:
d = display
Modifiers
b = block
ib = inline-block
n = none
*/
.dn {
display: none;
}
.dib {
display: inline-block;
}
.db {
display: block;
}

We now have a set of classes that are easy to remember and fit in with the rest of our classes.

Representing Media Queries

We live in a mobile-first world, our apps and websites must be responsive. How have we handled this? Most examples I’ve seen use suffixes or prefixes that are associated with a name of a breakpoint. If you’re familiar with Bootstrap, Foundation, or any grid system for that matter, you’ve probably done something like this:

<! — hard to scan and decipher →
<div class=”col col-6 col-md-4 col-xl-3">
<div class=”article”>
<h1>such responsive</h1>
</div>
</div>

Or maybe you’re used to using SCSS and dumping breakpoints into the actual classes themselves. Which has the added drawback of coupling layout with a presentational class.

/* couples presentation with layout ;_; */
.article {
@include media-breakpoint-down(xl) {
@include col(3)
}
@include media-breakpoint-down(md) {
@include col(4)
}
@include col(6)
}

The SCSS way is even worse because it leads to writing more styles. How do you use this .article and make it full width? By writing a modifier class
.article — full-width that overrides the media queries. Yuck.

My argument is to use @ as an intuitive symbol for understanding responsive breakpoints in your markup. For example:

/*
Base:
d = display
Modifiers
b = block
ib = inline-block
n = none
Media Query Extensions
@md = medium
@lg = large
*/
@media screen and (min-width: 30em) and (max-width: 60em) {
.dn\@md {
display: none;
}
/* etc. */
}
@media screen and (min-width: 60em) {
.dn\@lg {
display: none;
}
/* etc. */
}

I came across this concept from this article on BEMIT by Harry
of CSS Wizardy. I think Harry can put it more eloquently than I ever could:

The @ is a human readable and logical way of denoting conditional states. It allows developers to learn about any potential permutations or appearances that the piece of UI in question might have, just at a glance.

I have completely embraced this idea and it has made scanning and understanding CSS in markup a breeze for me. I’ve extended this concept by using : to signify :hover states and other pseudo-selectors. For example:

.bg-red-400 {
background-color: red;
}
/* I’m aware of how weird this looks */
.bg-red-500\:hover:hover {
background-color: darken(red, 20%);
}
<p class=”bg-red-400 bg-red-500:hover”>
Hipster ipsum obscure reference
</p>

Benefits of Switching to Fun(ctional) CSS

Functional CSS actually solves specificity. OPINION WARNING: It is the way CSS is meant to be written. Composable, reusable, small, and easy to understand. You will stop writing mountains of CSS and begin to think of CSS as pure functions.

Faults and How to Address Them

What if we want a collection of small classes that define a component that is
heavily reused? Do we really want to see something like below everywhere?

<button class=”dib bn bg-primary-400 bg-primary-600:hover”>
Confirm
</button>

We would have to find every occurrence of this button and modify them one by one(or with unix tools if you’re hip to that). If you’re using a templating
language like Handlebars I would suggest creating a styles or components partial that contains this string. That way you have this little collection of classes contained in a file. It’s sort of like faking CSS.

{{! — ./partials/components/button/primary.hbs — }}
dib bn bg-primary-400 bg-primary-600:hover

{{!-- ./layouts/some-template.hbs --}}
<button class=”{{> components-button-primary }}”>Confirm</button>

Doing this you can easily add additional classes:

{{! — full width primary button — }}
<button class=”{{> components-button-primary }} w100">
Confirm
</button>

TL;DR: Experiment and Have Fun!

Be creative and have fun! We are all in this together trying to figure out this
whole Internet app/website development thing. Lots of stuff has changed in the last few years and our industry is awesome and constantly evolving. So be bold and experiment and share what works for you.

Functional CSS is awesome, I’ve really enjoyed it and I know many developers that have as well. Give Tachyons a try and see how it can completely transform your workflow.