What a CSS Code Review Might Look Like

Avatar of Geoff Graham
Geoff Graham on (Updated on )

Many programming languages go through a code review before deployment. Whether it’s a quick once-over, in-depth peer review, or complete unit testing, code reviews help us release code into the wild with confidence.

I started to imagine what a CSS code review might look like. CSS can be written in a number of ways, and the best way is often subjective to the project. I’m definitely not trying to get dogmatic with a post like this, but instead lay the foundation for what could be a starting point for getting the most out of CSS before it is released.

Why should CSS be reviewed at all?

It’s fair to wonder why we would want to review CSS in the first place. A review is yet another step that adds time and cost and effort and all that other stuff that seems to hold us up from shipping a product.

At the same time, a code review allows us to step back, take off our battle gear, and give our work an honest assessment—or hand it off to someone else for a fresh perspective. This is what separates us from the machines and, in the end, can save us the headache of having to deal with bug and performance fixes that could have been caught before they were shipped.

There’s much more benefit here than just preemptively squashing bugs. I find that splitting a review into specific areas focused on these benefits helps frame the conversation and prioritize those positive outcomes. The benefits for you may be different from what I’ll cover here, but these are ones I find myself coming back to time and again.

Area 0: It does the job

Let’s not dwell on this, but not forget it either. The first job of CSS is to style the page so it looks like it’s intended to. It matches the designers mockup or fits the style guide or whatever it’s supposed to do. And it can do so with variable content (titles and content of various lengths, images of various sizes, etc.) If it doesn’t, that needs to be fixed first.

If the design is responsive, make sure the design does what it’s supposed to do fluidly and at each breakpoint.

Area 1: Style and Consistency

The goal here is to ensure that CSS is well-written, organized, and documented. Those of us who have inherited projects from other developers know the benefits here. Code that uses a consistent naming convention and includes thorough documentation is easier to dive into and provides instruction for how to maintain and enhance the code in the future.

Questions to ask:

  • Is there a CSS style guide available for this project? If so, does the code follow it?
  • Is the code thoroughly documented? Are there confusing elements, properties, or hacks that would prevent another developer from knowing why something was written the way it was?
  • Are there any blatant inconsistencies in how elements are named or how their properties are organized?

Available resources:

  • CSS Lint: An excellent tool to find mistakes or inconsistencies. It’s even available as Grunt and Gulp tasks that can be configured to check against your own set of rules.
  • CSS Style Guides: A roundup of style guide examples that can be used as inspiration for creating your own.
  • What makes for good docs?: Dave DeSandro with the down low on how documentation is related to marketing.

Area 2: Browser Compatibility

Once CSS is organized and consistent, I tend to turn my attention to how it looks on different browsers and devices. Well-written code is one thing, but it isn’t worth much if it doesn’t work where and when it should.

Questions to ask:

  • Which browsers and devices does this project support? Do we have access to them for testing?
  • Are there analytics for this site? If so, do they give us insight into what browsers are more important to be testing for?
  • Are there any instances of “hacks” aimed at a specific browser or device? If so, is there another way around them? Are they well-documented?

Available resources:

  • Can I Use: A central repository for referencing which CSS properties are compatible with any browser and version.
  • Ghostlab: An app for synchronized browser testing across multiple devices.
  • OpenDeviceLab.com: An interactive map to locate nearby device labs for testing.
  • Establishing an Open Device Lab: Smashing Magazine does a deep dive on the the benefits of device labs and tips for how to set one up.
  • Support vs. Optimization: Brad Frost does a fine job of covering the difference between the two and how that can affect the way code is written.
  • Cross browser testing services: Cross Browser Testing or Browserstack.

Area 3: Specificity

Now is the time to gauge just how specific the elements in the code are and identify whether there are opportunities to refactor. This creates a responsible cascade of styles where elements are either as modular or as specific as we want them to be.

Questions to ask:

  • Are IDs used anywhere? If so, will a class name work instead? Does the style guide have anything to say about this?
  • Does !important make its way into the code? If so, why was it used and can the code be refactored to avoid using it?
  • Do we rely on prefixing and, if so, are prefixes organized in such a way that there are proper defaults in place for unsupported browsers?
  • How modular are the elements? Do they hold up in a “Kitchen Sink” test, where they are all used together in the same HTML document?

Available resources:

Area 4: Preprocessor Utilization

Ignore this if the project isn’t using a preprocessor. But if it is, there are certainly some extra things to think about.

Questions to ask:

  • Are existing variables being used where they should be? Have new variables been introduced? If so, do they make sense and are they documented?
  • Were other abstractions (e.g. extends, mixins, loops, maps, etc) used effectively and in adherence with how the rest of the code is doing things?
  • Is the new CSS placed into the correct partials? Were new partials used? Do they make sense architecturally?
  • Are they following any established preprocessor-specific style guides?

Available resources:

Area 5: Performance

I include performance toward the end of a review not to belittle it, but to make sure it is the cherry on top of our review sundae. Performant CSS is often about refinement and how it is packaged and served, so it seems appropriate for it to cap off the review process—even if performance is always in the back of our minds as we work.

Questions to ask:

  • How much does the final CSS file weigh? Are we planning to minify and gzip it (yes, please!) and what is the weight difference when we do?
  • How many different stylesheets are we loading (via or native @import)? Can we reduce that number? Can they be served conditionally? Async?
  • We’re caching CSS in production, right?

Available resources:

  • CSS Stats: Pop in the URL of a site and get a slew of stats returned, including a report of all the fonts and colors that were used.
  • CSS Dig: Very similar to CSS Stats, but packaged as a convenient Chrome browser extension.
  • unCSS: A task-runner that removes unused CSS by comparing it to the HTML and JavaScript markup. Available for Grunt, Gulp, and Broccoli.
  • Critical CSS: Another task-runner, but one that creates individual CSS files based on the HTML markup for a given page. This optimization is consistently recommended by Google PageSpeed Insights.
  • loadCSS: A function for loading CSS asynchronously

Wrapping up

I definitely wouldn’t say that every question and tool mentioned here is needed or even relevant for all projects. In fact, there are likely more questions and tools to consider. Are there questions you routinely ask before releasing CSS? For example, where would accessibility fit in for you? Please share!

Also, remember that the goal of auditing our code is not to make it perfect. We make compromises in CSS for many reasons (whether intentional or not) and, at the end of the day, just trying to do a good job is more than enough and this is part of that effort.