Daniel Erickson @techwraith

Your CSS needs a dependency graph

I think we can all admit it: our CSS is a mess. Everything is in one big file. We ship this massive file down to every page without caring that the page is only going to use a fifth of what's in it. We throw around classes like that annoying teenager at the movies throws popcorn.

I have good news, we've been doing it wrong, and there is a better way: CSS needs a dependency graph.

Once our css rules know the other rules that they depend on we get a bunch of wins:

Let's not reinvent the wheel

Great, now how are we going to add a dependency graph to our CSS? Easy. Node ships with the best dependency manager out there: npm and require(). We can use it for more than just JavaScript, the system works great for any kind of code. We can use it for our CSS.

First, we're going to need our CSS files to be able to find each other. That means building something like node's require function. Luckily, there's something built into CSS that's responsible for including more than one CSS file: @import. We can override it to allow us to use named modules (modules in your 'node_modules' directory) alongside relative paths. We can also add a style property to our package.json to indicate which stylesheet our module uses so that the new @import rule can find it. As an added bonus, if we publish this to npm other people can use it too!

Once we've got that in place, we just need to build a tool that can take an entry file as input and builds us an output file that doesn't repeat modules.

For example:

@import "module-a";
@import "module-b";

body {
  /* some styles for this build */
}
@import "module-c"

.module-a {
  /* some styles for module a */
}
@import "module-c"

.module-b {
  /* some styles for module b */
}
.module-c {
  /* some styles for module c */
}
.module-c {
  /* some styles for module c */
}
.module-a {
  /* some styles for module a */
}
.module-b {
  /* some styles for module b */
}
body {
  /* some styles for this build */
}

Sweet, people already thought of this:

When I thought this up, I did a quick npm search and found a module that seemed to do what I wanted. It's called npm-css and it's almost what I wanted. It's main problem was that it was too opinionated. I wanted a module that just gave us the @import and the file concatenating. npm-css did this, but it also prepended the module name as a class, which assumed too much about my markup.

After talking to the guys building Topcoat over at Adobe, and finding that they were excited about this idea too, Kristofer Joseph found a little tool called rework-npm. It was perfect. We use rework at Getable to add variables and other features to our CSS.

The talented people over at Adobe ended up combining it with a bunch of other rework modules to create Resin - a really cool CSS preprocessor with all of this stuff we've been talking about built right into it. Go check it out.

Atomify

At Getable we build a few different apps with a lot of shared components between them. We needed a way to easily transport those components (with their HTML, CSS, and JS) between apps. We built Atomify to solve that problem. It's basically Resin + Browserify + Handlbars templates. It allows us to build nice little components that can be shared across apps.

Atomify solves the dependency graph problem for your CSS, JS, and templates. In a future post, I'll show you how you can develop things quickly and, combined with Atomic Design, consistently with Atomify.

I hope you enjoy using it. As always, if you have any feedback, hit me up on Twitter or leave a Github Issue.