The Case for Re-Architecting Your CSS (with a CSS Preprocessor)

In the last few months I’ve become a pretty big fan of a particular CSS preprocessor called Stylus. Stylus is a node.js-powered preprocessor that I’ve used with some clients. Stylus has offered a huge boost in both my productivity and quality— and I’ve conjectured that it even gives me an edge performance. After seeing huge gains, I’ve wondered if existing websites can get a benefit from a CSS-to-Stylus conversion. Clients don’t ask for one, and it’s probably because no one has every done a CSS-rewrite and actually measured the gains. Well, guess what? I did a Stylus conversion on my blog, to find out if I could find any gains…

Oh yeah…I thought something looked different

I’ve had a growing list of things I wanted to change about the blog’s design. I’ve mostly been pleased with the design, but it could always be 10% better:

Global Changes:

  • Removed the border-bottom from my header
  • added an opening and closing <> to my navigation items
  • floated my “about me” navigation item to the right (to distinguish it from other nav elements)
  • added a background color to my articles
  • widened my side rail (conforms more closely to the divine proportion)
  • slimmed my main content(also conforming more closely to the divine proportion)
  • added a bottom border to headings in my side rail
  • Change the wording, color, and shape of my “widescreen toggle” in the upper right
  • Switched the navigation items to permanently fixed in phone breakpoints
  • Navigation items don’t have background color in phone breakpoint
  • Decided to go mobile-first instead of desktop-first with the CSS

Listing page changes:

  • just made the article look like a box, not some weird tagged card thing
  • removed fancy hover animations for seeing meta tags
  • the color , shape, and location of my read more button
  • article has a background color (used to only have background when you hovered)

Article page changes:

  • the article has a background color (used to only have background when you hovered)
  • Share tools at the bottom instead of off to the side
  • comments got an overhaul: no rounded-corner box shadowy stuff. simple dotted lines

In all,we have a list of 20ish changes to my UI that maybe amounted to 80 or 100 lines of CSS; relatively insignificant changes to the code base that I was working from.

The Goal

I had four basic goals in my project:

  • Improve page load time
  • Convert CSS to Stylus
  • Get the CSS ready for responsive, flex box, and standard layouts
  • Make the UI about 10% better

I also gave myself the same kinds of restraints a client might give me:

  • Don’t change the CMS itself
  • Don’t change the content
  • Remove what’s unused
  • Rewrite what is used

The Old Site

This is a WordPress blog and I was using the Toolbox theme. A while back I’d created my own child theme.  My theme used Toolbox CSS with heavy modifications. This included adding @import statements in the style.css to migrate in styles that existed on I was using a “Syndicated Design” methodology; I was using the @import rule to support a separation of brand and layout. I’d created my own sprites file and I’d brought in zocial.css to provide social media icons. I didn’t use my sprites anywhere and I didn’t use the social media icons, either. All of my social media stuff was in the “Follow Me” WordPress widget.

CSS Files on the Old Blog
CSS File Lines Kilobytes (kb)
style 1408 29
reset 51 936b
page-elements 552 13.6
fmt-sprites 20 469b
zocial 378 4
Total 2409 48.1

Network and Performance:

Old Blog Network and Performance
Stylesheet Requests 16/53 (total requests)
KB transferred 356/576
load time 10.88s

The extra stylesheets that aren’t accounted for in that first table were  added by WordPress plugins which I wasn’t using. WordPress is great as a general blogging platform, but it isn’t fantastic when your full-time job is making content management systems.

The Stylus Conversion

Stylus has a command line executable that converts an existing CSS file into a .styl file, but I didn’t use it.  I wanted to improve the divisions of brand, layout and components — and get some flexibility for turning out more responsive layouts. I avoided a simple command-line conversion because I wanted more discrete divisions of labor in my code. I do this with Tridion implementations, so it’s silly not to do this with a blog. Let me show you how I organized my files.

The Root Folder

The Root of my Stylus Project
The Root of my Stylus Project

In my root folder I created subfolders for  brand, layout, and components. In each of those I created an index.styl file which would do a Stylus import of all the files in that same folder. Back in my root CSS folder I added NIB, which is a CSS3 library for Stylus. Also in the root, I created a vars.styl file; this would contain any global variables that I might want to distribute across all my Stylus files. My vars file contains friendly names for colors, some functions, and font-conversion things.


Organization of Brand
Organization of Brand

In my 001-brand folder, I created a Stylus file for each part of my brand experience. I ended up with a total of nine different files ranging from a reset to  tables. I made sure that these files contained only colors, font information, borders, CSS3 effects, and a small amount of padding.


Layout was a bit more of a challenge because I want to offer two layouts: Flex Box and Standard. Within my layout folder, I’d created a subfolder for each. Within each subfolder, I broke my layout into four parts: page, header, footer, widgets. Anything relating to floats, heights, widths and margins goes in here. These are relatively small files because they’re only addressing shape and placement of things on the page. This enabled me to make very small and simple responsive files.

I don’t have an index in the root of my layout folder; I have two entirely different layouts so the index is on a per-layout basis. As I create responsive designs, I could either create 003 and 004 folders for tablet and phone, or I could create responsive setups inside of my standard and flex folders. I haven’t decided which way to approach responsiveness, but I have the flexibility for either.

Page Layout
Page Layout


“Component” is a Tridion term. It’s a single, discrete piece of manageable and syndicatable content. I didn’t adhere to the strict definition here, so Tridion geeks should know that I said “components” while thinking “component templates”.

Component Organization
Component Organization

It was hard to write my components in a way that made them not have brand and not have layout. I decided to focus these individual files on margins, paddings, and specific font-sizes and other rules that couldn’t possible be shared in anyway.

Using grunt

I probably spent more time working on things for my CSS than actually writing it. Along with getting my organization in place, I didn’t want to spend a ton of time building and rebuilding my files —especially when I want flex and non-flex CSS. That’s where Grunt.js comes in. Grunt is a node.js-based task runner. I installed two Grunt plugins: Stylus and Watch.  With Watch, Grunt would monitor my filesystem and look for any changes to my styl files. If something changes, Grunt runs my Stylus tasks. I had a Stylus task called standard, and another called flex. They would import my vars.styl file and the nib library, and then add a banner to the top of that CSS file (which was the WordPress comment block for identifying the theme).  Whenever I was ready to start coding, I’d just run grunt from my terminal in my root folder.

A happy side-effect of using grunt is that I gain another level of abstraction. I can import and concatenate files with Grunt, too. Right now Grunt builds two CSS files that both contain brand, layout, and components. If I want, I can have Grunt build me a CSS file for brand and components with separate CSS files for both standard and flex. Grunt keeps me from being locked in to just one way to build my CSS.

Probably the nicest side-effect of using that when Stylus builds to my CSS, it does a small amount of minification, too. Stylus will clump similar rules to the same line, remove whitespace, and remove indenting. It’s like a prettified version of minification (if that’s even a thing).

The Performance Gains

CSS Files

CSS Files on New blog
CSS File Lines Kilobytes (kb)
style 262 8.2

I know what you’re thinking: “That’s not a fair comparison because Stylus does some minification!” It’s not a thorough minification, though. It’s just eliminating white space and putting stuff on the same line.

Even if you prettify my standard.main.css, you’ll see that it only expands to around 750 lines. If Stylus didn’t minify, we’d be talking a 69% drop in lines of code. Factor in that minification and you have a 91% drop in lines of code — but lines of code is better for browser parsing, not page weight. I’m now loading 8.2kb worth of CSS, instead of the 48kb we had before.

Let me reiterate, you are browsing the same website, with the same look and feel, the same layout, and only minor improvements to the UI, but with almost 70% less CSS.

Network and Performance

New Blog Network and Performance
Stylesheet Requests 10/51
KB transferred 343/676
load time 9.78s

The real kicker here, and the thing worth taking note, is that load time in a cheap Samsung Chromebook dropped from 10.88s to 9.78s. That’s a 1.1 second drop! I tested in Chrome for a Mac and also observed a 1 second drop in page load.

How Much is 1 Second Worth?

I took a website and did nothing but change the CSS. I consolidated CSS files into a single one. I then created a new architecture for my CSS. After that, I went line-by-line, and rewrote that stylesheet in Stylus, rather than vanilla CSS.

The total amount of work adds up to about 60 hours of development time. Most of it was spent spinning up Grunt and getting the framework in place. The gain, though,  is over a second on page performance— and a CSS setup that will be flexible for years to come.

So, is it worth it for a client to ask for a CSS do-over? Ask your users what one second is worth to them.