Introduction to CSS Explorer

I’ve been curious about the state of our CSS code and its changes over the time. So I’ve written recently a program called specificity. What does it do? It answers the following questions:

  1. What is a total number of selectors in your CSS codebase? How has it been changing over the time?
  2. What is a maximum/average/median selector‘s specificity of your CSS codebase? How has it been changing over the time?
  3. How does the distribution of selector‘s specificity of your CSS codebase look like? How has it been changing over the time?
  4. How many selectors in your CSS codebase contain at least one rule with the !important directive? How has it been changing over the time?

Wait, why is it so important? It’s not, until you have a codebase of dozens of thousands lines of code that is hard to maintain and you used to do a lot of experiments. And of course, if it’s not even important, it’s quite interesting at least.

CSS specificity chart

So, node-specificity provides two commands. One is for parsing your CSS files and creating profiles. Second is for reading or “exploring” these profiles. Let’s look at an example. I have a few versions of CSS of the website you’re reading right now. As I’m writing this post the website is using v8.css.

Alright, let’s create profiles for these files:

$ node-specificity parse v1.css --label=v1 --output=v1.json
...
$ node-specificity parse v8.css --label=v8 --output=v8.json

We’ve created a profile for each CSS file since we want to observe changings over the time. If you use more than one CSS file on your website, you have to create a profile for all of them, for instance:

$ node-specificity parse main.css print.css --label=2014-12-23 --output=20141223.json

Label acts as a profile’s name in reports. Once we have profiles created, we are able to run a report. Let’s start a ‘server’ report:

$ node-specificity explore v*.json --report=server
Server is running on http://localhost:4000/
Press Ctrl + C to stop it.

Open a browser and go to “http://localhost:4000/”. Now you’re supposed to be seeing the page with different controls and a weird graph. It‘s the specificity distribution chart (see in the picture above). For each specificity (tuple) it shows the total number of selectors of this specificity in the specific profile.

Other graphs are: number of selectors in your CSS files and total number of selectors in profiles, how many of them contain rules with the !important directive, average and median values of selector’s specificity for CSS files and profiles.

Number of selectors chart

You are able to explore all these graphs for a specific profile. To do this, you have to select the particular profile’s label in the dropdown list. For instance, it’s the specificity distribution bar chart for ‘v8.json’ profile in the picture below.

CSS specificity chart

So, server report is quite a powerful tool. Bear in mind, images above are for the profiles of one humble CSS file. If you have a few files for profile, it gets better.

There is also inspect report (it’s used as the default one). If you run node-specificity explore v8.json, it will print out the list of all selectors in the given profile, the summary on specificity numbers and the specificity distribution chart, which is very similar to the one you can see above.

Screenshot of the ‘inspect’ report

Reports can accept additional command line options. There are few of them. In the example above, --no-inspect-selectors option has been used. It disables printing out the list of all selectors.

That’s it. Happy exploring!

What’s worth watching

Open all modified files in editor

Often I finish working day without committing changes to the repository. Thus, next morning I need to open all the files I was working yesterday. And I found an efficient way to do this.

$ vim -p $(git diff --name-only HEAD | sed "s,$(git rev-parse --show-prefix),," | tr "\n" " ")

It opens Vim and loads all modified files in tabs. You could add this command as an alias to your .bashrc, but adding this to .gitconfig seems like a better option. This is what you need to add to your ~/.gitconfig.

[alias]
open = "!vim -c \"cd $GIT_PREFIX\" -p $(git diff --name-only HEAD | tr '\\n' ' ')"

To run this command you need to type git open in the terminal. Since all commands prefixed with an exclamation point are executed from the top-level directory of a repository, we need to change working directory in Vim to the current one. And of course you can replace Vim by your favorite editor or event by $EDITOR.

Besides, If you use sort of file watchers to perform certain operations when files change, then you would find the following command quite helpful. It changes modification time of all modified files at once.

[alias]
touch = "!touch -c $(git diff --name-only HEAD | tr '\\n' ' ')"

You can find more handy aliases in .dotfiles of mine.

What’s worth watching

  • Bred Victor (MIT) on “Media for Thinking the Unthinkable”: incredible ideas that will probably change the way we present and understand things.
  • Douglas Crockford on “The Better Parts”: you aren’t supposed to use every feature of the language to write error-free programs. Douglas is sharing his favorite parts of JavaScript and coming ES6 standard.
  • Facebook’s way to Flux and React in “Rethinking Web App Development at Facebook”.
  • John-David Dalton (Lo-Dash) on “Unorthodox Performance”: interesting techniques to improve JavaScript performance.
  • Patrick Hamann (The Guardian) on “CSS and the Critical Path”: dealing with performance bottlenecks in the browser from network to painting.

What’s worth watching

Archive