Stephen Lindberg

Product Designer @ Iterable

29 February 2020

Managing Specificity with CSS Variables

Here’s a quick idea for keeping rule specificity low when writing CSS. Let’s say we have a table:

<table>
  <tr>
    <td> Datum </td>
  </tr>
  <tr>
    <td> Datum </td>
  </tr>
  <tr class="highlight">
    <td> Datum </td>
  </tr>
</table>

The third row has the class highlight, which gives a unique background color to each td element in the row with a rule like this:

.highlight td {
  background-color: yellow;
}

Now, what happens if we give every odd row a slightly different background color?

tr:nth-child(odd) td {
  background-color: var(--gray-300);
}

Uh oh, this rule has a specificity higher than the highlight rule, so our row won’t get highlighted correctly.

Now, we could artificially increase the specificity of our highlight rule in order to make it supersede the odd-row rule, but that feels kind-of dirty. What if we could control the specificity of the odd-row rule? We can do just that with CSS variables, check it out:

tr td {
  --row-bg: transparent;
  background-color: var(--row-bg);
}

tr:nth-child(odd) td {
  --row-bg: var(--gray-300);
}

.highlight td {
  background-color: yellow;
}

Since the rule for odd rows is applied with the selector tr td, it’s specificity is lower than .highlight td, which will now give us our nice, yellow row.

Enjoy!