Terrible Blog

Because Terrible Labs loves you.

Write Maintainable CSS

| Comments

Typical scenario #1: We’ve just spent several hours building an application feature. Now in the last part of the day we are tasked with styling the feature. We’re a little tired, it’s after lunch, and really nobody’s looking at the CSS anyway, so we can probably just do whatever is simplest to get the job done.

Typical scenario #2: We’ve just spent several hours modifying an application feature. Now in the last part of the day we are tasked with re-styling the feature. We’re a little tired, it’s after lunch, and we have little patience for mucking around in CSS. We open the stylesheets only to find that little attention was paid to the structure and organization of them. As a result we have to spend twice as long as we should combing through lines of CSS in order to figure out how our feature was styled in the first place. Our frustration with the current state of the CSS causes us to write even sloppier CSS to address today’s issue. We exacerbate the problem.

We write clean, maintainable application code. We do this because we know that the code will eventually need to change. Writing with change in mind informs our process. Yet with CSS we often let this discipline slip. We don’t spend the time to construct CSS the right way, choosing instead the path of least resistance. Perhaps because CSS is simpler than application code, we feel that it is below us and we can hustle through it without wasting too many brain cycles. Perhaps it’s just boring to write CSS and we want to get it out of the way. Whatever the excuse, it often leads to poorly-planned and un-maintainable styles. This leads to angst about writing CSS. Bad CSS taints our impression of all CSS. If we make a commitment to write more maintainable CSS, we will make our own lives significantly happier when we inevitably get back into those styles.

Here are some high-level concepts we should keep in mind to help write maintainable CSS. None of these are complicated, and may even seem common-sense. But are we always really following them? The broken window effect can quickly spiral out of control with CSS, so keeping the fundamentals in mind at all times will help keep us sharp.

How Global Is This Style?

This should be the first question we ask when styling any element. Instead of diving right into the CSS, we should take a few seconds to ask “does this element occur anywhere else?” 90% of the time the answer will be yes. At that point it’s up to us to determine if the style is better suited for a more global stylesheet, a mixin, or an extendable class. If it’s more efficient to create the style in one place first and only abstract it once it re-occurs, that’s fine. As long as we’ve made the decision to eventually globalize the style, we’re on the right path.

1
2
3
4
5
6
7
8
9
10
/* users.css_ */
#user-profile aside.menu {
  padding: 10px;
  border: 1px solid #ccc;
}

#user-profile aside.menu h4 {
  font-size: 12px;
  text-transform: uppercase;
}

This style looks fine initially. But before or after composing this CSS, we should take a quick look over the design to determine if any of these styles are more global. Let’s say we discover that there will be several side menus with the same border and padding styles. We can then make the aside style more global:

1
2
3
4
5
/* global.css */
aside.menu {
  padding: 10px;
  border: 1px solid #ccc;
}
1
2
3
4
5
/* users.css */
#user-profile aside.menu h4 {
  font-size: 12px;
  text-transform: uppercase;
}

DRY It Up

We don’t allow unnecessary duplicate methods to occur in our code; why then should we allow a set of CSS styles to occur more than once in our stylesheets? The most agonizing task when working in CSS is making adjustments to elements that are being styled from multiple places. Ideally we should only have to modify CSS in one place when making an update. Even if it feels like we’re writing a little more CSS initially in order to keep things dry, in most cases it’s way to go.

We don’t always know ahead of time where a duplication will occur; we may need to style a few elements and then factor out the common styles afterwards.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Before */
input[type=text] {
  width: 150px;
  height: 30px;
  border: 1px solid #000;
  color: #ccc;
  font-size: 12px;
}

textarea {
  width: 150px;
  height: 150px;
  border: 1px solid #222;
  color: #ccc;
  font-size: 11px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* After */
input[type=text], textarea {
  width: 150px;
  border: 1px solid;
  color: #ccc;
}

input[type=text] {
  height: 30px;
  border-color: #000;
  font-size: 12px;
}

textarea {
  height: 150px;
  border-color: #222;
  font-size: 11px;
}

The refactor creates more CSS than the original, but is is more manageable. If we need to change the width, border, or color of these form elements, we now only need to change them in one place.

Break Up Global Styles

global.css can become quite a large file if left unmanaged. Oftentimes there are groups of global styles which can be split off into separate files. Form styles are a good example. Typically the majority of form element styles will be consistent across our app, and they usually require a significant amount of CSS. Moving these form styles out of our global stylesheet and into a global feature stylesheet helps keep our styles organized and our files as small as possible.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* Keep in global.css */
h1 {
  font-size: 24px;
}

aside.menu {
  padding: 10px;
  border: 1px solid #ccc;
}

/* Move from global.css to forms.css */
form input[type=text] {
  width: 150px;
  height: 30px;
  line-height: 30px;
}

form textarea {
  width: 150px;
  height: 150px;
}

Don’t Start With the Home Page

This sounds a bit dramatic, and it may not be possible given project and client needs. But the point it demonstrates should not be overlooked. If establishing global styles early is a priority (as it should be), beginning our CSS work on the home page can present a challenge. If there is one page in our app that contains unique design characteristics or diverges from the global styles, it’s the home page. A lot of effort is dedicated to styling the home page. If we start there, when we move on to an inner page we will find ourselves saying “this style is like the home page style but it differs a little.” In fact the opposite is typically true: the home page often differs from the global styles, with some similarities. Using the home page for establishing canonical styles can therefore confuse the process.

Ideally we should start our CSS work on an internal page full of global style elements. Conveniently, our app’s core functionality is usually contained in these inner pages, and that core functionality is typically the starting point for the development process. Though it may feel awkward - for our client as much as ourselves - to initially avoid the homepage, it can make for a more streamlined process in the long run.

Write With Refactoring In Mind

The most elegant solution is not always immediately obvious. As long as we keep our eyes open for a better solution, we will continue to keep our CSS robust and flexible. We should approach our CSS with the intent of refactoring it as soon as it is appropriate. We constantly refactor our application code, yet too often we leave crummy, outdated CSS to rot. Taking the time to refactor CSS makes our lives exponentially better when we inevitable dip back into the styles.

Stay Disciplined

As a whole we are too lenient with CSS. As we all know, many hours can be sunk into a style update due to poorly-maintained CSS. Part of the difficulty in keeping CSS up to a high standard is the lack of outside attention paid to it. In the application world our code is under much more scrutiny than is our CSS. The discipline to keep the ship righted must then be self-imposed. It is in our (and our clients’) best interest to keep a sharp eye on our styles. We should hold our CSS to as high a standard as we hold our code.

Comments