Skip to main content

Code Verbosity

TL;DR: If breaking a shorthand up makes the code more readable, that's a trade-off I'm willing to make… especially after seeing the alternatives.

Recently I was refactoring some CSS, and I found something like this code snippet:

body {
  font-family: sans-serif;
  font-size: 14px;
  line-height: 1.4;
}

h1 {
  font-family: serif;
  font-size: 36px;
  font-weight: bold;
}

Ugh, I thought, why so many lines? Let's use the shorthand syntax! So I refactored many instances of this code through our project and ended up with code like this:

body {
  font: 14px/1.4 sans-serif;
}

h1 {
  font: bold 36px serif;
}

But there's a problem! Turns out when you use the shorthand syntax, any values you don't pass in get reset to their initial values. That's fine for things like bold and italic, but in this case I was accidentally resetting my line-height to 1! Luckily, it was an easy fix using the inherit property.

body {
  font: 14px/1.4 sans-serif;
}

h1 {
  font: bold 36px/inherit serif;
}

Of course, we use Sass, so the code actually looked like this:

$size-body: 14px;
$font-body: sans-serif;
$size-header: 36px;
$font-header: serif;
$weight-header: bold;

body {
  font: #{$size-body}/1.4 $font-body;
}

h1 {
  font: $weight-header $size-header/inherit $font-header;
}

Now the shorthand syntax has two problems. Firstly, with all those variables the shorthand syntax is actually more difficult to read. Secondly, the shorthand line-height syntax looks like math. In order to keep Sass from trying to divide my font-size by my line-height, I have to wrap the variable in #{}, and even then it still looks like math to human developers.

So, as I see it, I have three options:

1. Use the Sass font shorthand

body {
  font: {
    family: $font-body;
    size: #{$size-body};
  }
  line-height: 1.4;
}

h1 {
  font: {
    family: $font-header;
    size: $size-header;
    weight: $weight-header;
  }
  line-height: inherit;
}

No one like this option. The Sass shorthand syntax means we're not writing recognizable CSS anymore, and it makes it more difficult to sort properties alphabetically. Moving on:

2. Use font shorthand, but set line-height separately.

body {
  font: #{$size-body} $font-body;
  line-height: 1.4;
}

h1 {
  font: $weight-header $size-header $font-header;
  line-height: inherit;
}

This isn't bad, but it feels inelegant, and those font shorthand rules are still really difficult to read with all the Sass variables.

3. Set each value separately.

body {
  font-family: $font-body;
  font-size: $size-body;
  line-height: 1.4;
}

h1 {
  font-family: $font-header;
  font-size: $size-header;
  font-weight: $weight-header;
}

Hey, this is great! Everything's nice and readable, and we can sort alphabetically again. Of course, you may have noticed the "problem" with this option:

It's the same code we started with.

Refactoring can be frustrating, because you can end up rejecting clever or space-saving solutions in favor of more readable or maintainable solutions. I was reminded of these quotes:

I’m always a fan of making your code more verbose (and as a result, increase filesize some) to ensure it’s easy to follow by others.

I have literally never regretted a choice to make some code more verbose. DRY, but verbose.

In the end, I'm not refactoring this code for my own immediate benefit. I'm refactoring while thinking of the poor slob who inherits this code months or years from now when I'm not around to explain it anymore. If breaking a shorthand up makes the code more readable, that's a trade-off I'm willing to make… especially after seeing the alternatives.