by

The Difference Between a Fix and a Solution in CSS

We all fix things, and we all solve things. But sometimes we don’t know whether we’re fixing a problem in CSS, or solving it. And I realize that even I’m guilty of not recognizing one over the other. This isn’t good. The inability to discern a “fix” from a “solution” has huge implications for the sustainability and scalability of a code base. And if we turn a code base into a collection of fixes, we kill page load, the user experience, and ultimately ourselves.

Pedantic Semantics

Fix

Fix is supposed to be a verb. But one of the beautiful things about English is that we can nounify verbs and verbify nouns. And “fix”, in its verb-ish form, can mean, “to repair; mend”1.

Fix is also synonymous with “correct” which means,

To set or make true, accurate, or right; remove the errors or faults from 2

The implication here is that a thing was broken, and that you have made it… unbroken.

In the world of front-end, this is adding position:relative to get something positioned, an extra class to a selector to raise specificity, or vendor-prefixing because Safari hates everyone. It could also mean adding !important because a property is getting overridden.

These are all fixes.

Solution

A solution is very different from a “fix”. It’s not about unborking a borked piece of code. A solution comes with thinking and intent. That’s why it’s defined as,

The act of solving a problem, question, etc 3

And what is solving? It’s the act of working out an answer. It comes from Latin’s solvere, which means to loosen or release4. When you solve a problem, you are releasing yourself from a stumbling block.

solving a problem requires us to find a root cause, while a fix does not.

Fixing and solving a layout problem

Fixing is all about correcting what’s wrong. You want to unbreak the brokenness. So let’s say we have an article with some padding:


<article class="article">
  <h1 class="article__title">hey there</h1>
</article>
.article {
  padding: .618em;
  border: 1px solid #333;
}

And it looks about like this:

An article, with an

Alas, our tester, tells us this is wrong! The title should be up higher, underneath the top border!

Let’s fix that:

.article__title {
  position:relative;
  top: -.618em;
}

See what I did there? I fixed it.

Fixing Stuff is Easy

A solution instead

Solving isn’t about repairing the problem and unborking the borkness. Solving is about releasing ourselves from a problem. It is an implementation that comes with investigation and comprehension.

Let’s try and understand why the title has been pushed down:

  1. Does this element have a ruleset in the CSS? No
  2. So this element must not be pushing itself down. Therefore another element is pushing it down.
  3. Does this element’s parent have a ruleset in the CSS? Yes
  4. Does this element’s parent ruleset have a property that affects spacing? Yes
  5. Can this property that affects spacing affect the position of my element? Yes

And so, the result of our problem solving is this:

.article {
  padding: 0 .618em .618em; /*don't need top padding, it was pushing down the title*/
  border: 1px solid #333;
}

Instead of adding four new lines of code, we edited one existing line.

This is not always the case when solving the layout problems; Sometimes code must be added. But in my experience, you’re way more likely to remove than add. This is because of the differences in how you’ve approached the problem. If the goal is to, “set it right” or “fix it”, we’re going to add whatever it takes to do that. But if we take the perspective of, “something has made this wrong”,we’re more likely to chisel away our code until the solution reveals itself.

Fixing Specificity vs. solving it

Another common thing that I see us do is “fixing” a specificity problem, instead of solving it.

Fixes with targeting

Suppose, again, we have an article and a title, and we are told that title needs to be a different color from typical <h1>.

<h1>Here's some article</h1>
<article class="article">
  <h1 class="article__title">hey there</h1>
</article>
h1 {
color: #333;
}
.article h1 {
color: #444;
}

This is fixing a specificity problem. It’s doing something with zero understanding of CSS or the cascade.

If we were to solve this instead, we would write

h1 {
color: #333;
}
.article__title {
color: #444;
}

Yes, this is a longer selector, but it’s a solution rather than a fix.

Why?

Because the problem wasn’t with an <h1>, but with an article title.

Fixes with specificity

Another kind of specificity fix, which I have been guilty of, is unnaturally raising the specificity. You start off with some HTML like this:

<section class="articleList">
<article class="article">
  <h1 class="tile">hey there</h1>
</article>
</section>

And then you style the title like so:

.articleList .title {
font-size: 1.5em;
}

And then you find out that the list of articles needs a title,too. so your .title won’t be in just an .article any more. So now you need to add a selector

<section class="articleList">
<h1 class="title">It's a list!</h1>
<article class="article">
  <h1 class="title">hey there</h1>
</article>
</section>
.articleList .title {
  font-size: 2em;
} 
.articleList .article .title {
  font-size: 1.5em;
}

Again, we fixed it. But we’re raising the specificity unnecessarily.

We can solve this problem by instead reducing specificity. After all, three classes to override two classes does the same thing as two classes to over ride one class, right?

.title {
  font-size: 2em;
} 
.article .title {
  font-size: 1.5em;
}

This seems scary, because we’re reducing code. But we’re not doing it blindly, we’re doing it with an understanding of the logic behind specificity:

3 classes > 2 classes :: 2 classes > 1 class

The problem with !important

There’s another, more common way that we “fix” specificity, rather than solve it. This is with the use of !important.
Let’s suppose that our article title should have a larger font-size on tablets and desktops than phones. We add the media query declaration, and we discover that the font-size works, but the color does not:

.article .article__title {
 color: #454545;
}

@media screen and (min-width: 500px) {
  .article__title {
    color: #565656;
    font-size: 3em;
  }
}

So, we can fix this with an !important declaration:

.article .article__title {
  color: #454545;
}

@media screen and (min-width: 500px) {
  .article__title {
    color: #565656 !important;
    font-size: 3em;
  }
}

This, however, is merely a fix. The problem still remains. And that problem is that we failed to understand specificity. In order for a declaration inside of a media query to override the declaration outside of a media query, both rulesets must have the same specificity. So a solution to the problem is to change the selector that we’ve used in.

So if we decide that the selectors should match, how do we decide which one should be matched? Let’s, again, avoid rushing to “fix”, and think through our options:

If we set the media query to the original, it’ll look like this

.article .article__title {
  color: #454545;
}

@media screen and (min-width: 500px) {
  .article .article__title {
    color: #565656;
    font-size: 3em;
  }
}

We have added code. We have indeed solved a problem, but is this the best solution possible?

Sometimes There’s More than one Selector Solution

What if we opt for removing code, rather than adding it? Setting the original selector to be the same as the media query does this:

.article__title {
  color: #454545;
}

@media screen and (min-width: 500px) {
  .article__title {
    color: #565656;
    font-size: 3em;
  }
}

This again reminds of of a simple logic rule of specificity:
2 classes : 2 classes :: 1 class : 1 class

By choosing to avoid a fix with !important, we have encountered not one solution, but two. So which one is the best solution? Hmmm…

Is the best solution always the one that removes code?

That depends; what do we know about .article__title?

  • Are we solving a problem for titles specifically within articles?
  • Or are we solving a problem for all article titles?

When we have multiple solutions for a specificity problem, we want to choose the selector that best-reflects our intent. If there’s more than one way to write a selector, choose the option with the best selector intent 5.

But don’t fret; two solutions to a problem are infinitely better than one fix.

A Reminder about !important

Remember that !important, when used as a fix, is a bad idea. It wasn’t meant to solve specificity problems, and it goes against industry best practices. If you want a list of ways to fix specificity problems without using !important, there’s a blog post for that, too.

But, don’t assume that every use of !important is a fix. Granted, the odds are in your favor that it is a fix… but !important, can actually prevent future problems when used proactively, especially for helper classes or accessibility purposes6.

The Big Idea

Yes, fixes and solutions are different. But they do have one thing in common:

They both work.

And this is a problem: Not all working code is equal.

If you’re coding to fix a problem, the problem is still there. Over time, those fixes will weigh down your stylesheet, slowing down load time, and ultimately, they’re still there. Waiting for someone to chisel away that good code, so that it can strike again.

If you can see the difference between a CSS fix, and a CSS solution, your codebase will thank you for it. Solution-driven development means code is leaner, more scalable, and easier to maintain.

If you’re forced to fix something, fix it. But leave a comment in the code that reminds you that it’s just a fix, still in need of a solution.

Be a problem-solver in the end.

Sources and Whatnots

1 Dictionary: fix

2 Dictionary: correct

3 Dictionary: solution

4 Dictionary: solve

5 Thank you Harry Roberts for the term “selector intent

6 !important isn’t all doom and gloom

4 Comments


  1. //

    Great read. Extremely thorough, very timely as well. I have to deal with this every day, and it can be more than just challenging… I make my decision based on allocated time, so we have lots of “fixes” around here and it’s only a matter of time before everything becomes completely unmanageable :\


    1. //

      There is a strategy for that!

      Harry Roberts introduced the strategy of “shame.css”. When you’re under pressure and you simply don’t have time to “solve” the problem, you can add your “fix” to a file called shame.css.

      The concept is that, when we do these fixes, we often forget about them. If we instead put them in a shame.css file, we have a collection of all the fixes in one place, and we can actually work through fixing them.

      Checkit: http://csswizardry.com/2013/04/shame-css/


      1. //

        Yes, I’ve seen ‘shame’ but these are generally pretty specific to CMS problems, non-semantic markup, HTML tables, and things like…

        “less than ideal CSS in order to meet deadlines, to get something working, or to fix pressing—or even live—bugs”

        …and so this dog has been chasing his tail lately :)


  2. //

    So, what you’re saying is that I’ve been solving things all along. I can’t stand not knowing why something went wrong and how to fix it. I can’t stand giant blocks of code that should be short. And while I do like spaghetti, I only like the kind that I can eat. It may take a bit longer for me to write code, but when it’s done-ish*, you won’t find a single fix.

    *Because code that was written a long time ago (in internet time, so that could even be as short as a whole week) might need to be updated, which clearly means that it’s never truly done.

Comments are closed.