{"id":294015,"date":"2019-08-12T07:30:18","date_gmt":"2019-08-12T14:30:18","guid":{"rendered":"https:\/\/css-tricks.com\/?p=294015"},"modified":"2019-08-15T22:02:01","modified_gmt":"2019-08-16T05:02:01","slug":"in-search-of-a-stack-that-monitors-the-quality-and-complexity-of-css","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/in-search-of-a-stack-that-monitors-the-quality-and-complexity-of-css\/","title":{"rendered":"In Search of a Stack That Monitors the Quality and Complexity of CSS"},"content":{"rendered":"

Many developers write about how to maintain a CSS codebase, yet not a lot of them write about how they measure<\/em> the quality of that codebase. Sure, we have excellent linters like StyleLint<\/a> and CSSLint<\/a>, but they only help at preventing mistakes at a micro level. Using a wrong color notation, adding a vendor prefix when you\u2019re already using Autoprefixer, writing a selector in an inconsistent way… that kind of thing.<\/p>\n

We\u2019re constantly looking for ways to improve the way we write CSS: OOCSS<\/abbr>, BEM<\/abbr>, SMACSS<\/abbr>, ITCSS<\/abbr>, utility-first and more. But where other development communities seem to have progressed from just linters to tools like SonarQube<\/a> and PHP Mess Detector<\/a>, the CSS community still lacks tooling for deeper inspection than shallow lint rules. For that reason I have created Project Wallace<\/a>, a suite of tools for inspecting and enforcing CSS quality.<\/p>\n

<\/p>\n

What is Project Wallace?<\/h3>\n

At the core, Project Wallace is a group of tools that includes a command line interface, linter, analysis, and reporting<\/p>\n

Here\u2019s a quick rundown of those tools.<\/p>\n

Command Line Interface<\/h4>\n

This lets you run CSS analytics on the command line<\/a> and get statistics for any CSS that you feed it. <\/p>\n

\"\"
Example output for projectwallace.com<\/figcaption><\/figure>\n

Constyble Linter<\/h4>\n

This is a linter designed specifically for<\/a> CSS<\/a>. Based on the analytics that Wallace generates, you can set thresholds that should not be exceeded. For example, a single CSS rule should not contain more than 10 selectors, or the average selector complexity should not be higher than three.<\/p>\n

Analysis<\/h4>\n

Extract-CSS<\/a> does exactly what the name says: Extract all the CSS from a webpage, so we can send it over to projectwallace.com for analysis.<\/p>\n

Reporting<\/h4>\n

All analysis from Extract CSS is sent over to projectwallace.com<\/a> where a dashboard contains all of the reporting of that data. It\u2019s similar to CSS Stats<\/a>, but it tracks more metrics and stores the results over time and shows them in a dashboard. It also shows the differences between to points in time, and many, many more features.<\/p>\n

\"\"
A complexity analysis generated by projectwallace.com<\/figcaption><\/figure>\n

Analyzing CSS complexity<\/h3>\n

There aren\u2019t many articles about CSS complexity but the one that Harry Roberts (csswizardry) wrote<\/a> got stuck in my brain. The gist of it is that every CSS selector is basically a bunch of if-statements, which reminded me of taking computer science courses where I had to manually calculate cyclomatic complexity<\/a> for methods. Harry\u2019s article made perfect sense to me in the sense that we can write a module that calculates the complexity of a CSS selector<\/a> \u2014 not to be confused with specificity<\/a>, of course, because that\u2019s a whole different can of worms when it comes to complexity.<\/p>\n

Basically, complexity in CSS can appear in many forms, but here are the ones that I pay closest attention to when auditing a codebase:<\/p>\n

The cyclomatic complexity of CSS selectors<\/h4>\n

Every part of a selector means another if-statement for the browser. Longer selectors are more complex than shorter ones. They are harder to debug, slower to parse for the browser and harder to override.<\/p>\n

.my-selector {} \/* 1 identifier *\/\r\n.my #super [complex^=\"selector\"] > with ~ many :identifiers {} \/* 6 identifiers *\/<\/code><\/pre>\n

Declarations per ruleset (cohesion)<\/h4>\n

A ruleset with many declarations is more complex than a ruleset with a few declarations. The popularity of functional CSS frameworks like Tailwind<\/a> and Tachyons<\/a> is probably due to the relative “simplicity” of the CSS itself.<\/p>\n

\/* 1 rule, 1 declaration => cohesion = 1 *\/\r\n.text-center {\r\n  text-align: center;\r\n}\r\n\r\n\/* 1 rule, 8 declarations => cohesion = (1 \/ 8) = 0.125 *\/\r\n.button {\r\n  background-color: blue;\r\n  color: white;\r\n  padding: 1em;\r\n  border: 1px solid;\r\n  display: inline-block;\r\n  font-size: normal;\r\n  font-weight: bold;\r\n  text-decoration: none;\r\n}<\/code><\/pre>\n

The number of source code lines<\/h4>\n

More code means more complexity. Every line of code that is written needs to be maintained and, as such, is included in the reporting.<\/p>\n

Average selectors per rule<\/h4>\n

A rule usually contains 1 selector, but sometimes there are more. That makes it hard to delete certain parts of the CSS, making it more complex.<\/p>\n


\n

All of these metrics can be linted with Constyble<\/a>, the CSS complexity linter that Project Wallace uses in its stack. After you\u2019ve defined a baseline for your metrics, it\u2019s a matter of installing Constyble and setting up a config file. Here\u2019s an example of a config file that I\u2019ve pulled directly from the Constyble readme file:<\/p>\n

{\r\n  \/\/ Do not exceed 4095 selectors, otherwise IE9 will drop any subsequent rules\r\n  \"selectors.total\": 4095,\r\n  \/\/ We don't want ID selectors\r\n  \"selectors.id.total\": 0,\r\n  \/\/ If any other color than these appears, report an error!\r\n  \"values.colors.unique\": [\"#fff\", \"#000\"]\r\n}<\/code><\/pre>\n

The cool part is that Constyble runs on your final CSS, so it does its thing only after all of your preprocessed work from Sass, Less, PostCSS or whatever you use. That way, we can do smart checks for the total amount of selectors or average selector complexity \u2014 and just like any linter, you can make this part of a build step<\/a> where your build fails if there are any issues.<\/p>\n

Takeaways from using Project Wallace<\/h3>\n

After using Project Wallace for a while now, I\u2019ve found that it\u2019s great for tracking complexity. But while it is mainly designed to do that, it\u2019s also a great way to find subtle bugs in your CSS that linters may not find because of they\u2019re checking preprocessed code. Here\u2019s a couple of interesting things that I found:<\/p>\n