Let’s Look Back

tagged under , , ,
reading time ~21 mins

One of the most important aspects to any codebase, besides the obvious fact that it should work, is that it should work well. What I mean by that is—it should be built upon an intelligent methodology and architecture that allows for maintenance and stronger comprehension. Fortunately, I was very conscious of this when I initially embarked on building my website and was extremely militant about how I organised my code. Thorough use of comments and sectioned components helped me to keep my code clean and maintainable. This is a practice I will undoubtedly carry forward to every project I work on—not just in an HTML and CSS sense, but in terms of project management, documentation, etc.

In Comes Sass

Well, not quite. I haven’t found a need myself for the full library of options available in Sass, a CSS extension language, but I have adopted a few of the tools that comprise SCSS. These tools include the ability nest selectors, assign variables, and create mixins to be used and extended elsewhere in the CSS. These utilities are extremely useful in writing CSS and in reading and understanding it. Because with SCSS we can nest selectors, children selectors sit inside their parents, and a clearer relationship is drawn between the two. Furthermore, due to the way that we indent CSS, child selectors will be indented to (roughly) match the DOM structure.

I don’t want to do anything, anymore!

Ever since I was fortunate enough to attend State of the Browser in 2013 and saw talks from Paul Kinlan and Jake Archibald, I’ve grown to care a great deal more about automation and performance. In the past months I’ve strived to maintain a streamlined site that not only has pristine, carefully-crafted code, but also responds quickly and loads in under one second, a personal goal of mine. Because I put such rigid limitations on the code and it being lightning-fast, I wanted to make sure that every line of code served a purpose—trim the fat.

One fantastic utility that helps immensely in trimming the fat, I learned about at State of the Browser: Can I Use, a repository of compatibility tables for support of web technologies such as HTML5 and CSS3. The kicker is that the tables are updated based on global browser usage statistics, so the tables are always up-to-date on what is supported, what isn’t, what requires a vendor prefix, etc. for all major browsers. The tables are invaluable for quickly checking what options I have for support when developing a new piece of code, but it’s all a bit tedious if I want my code and vendor prefixes to be up-to-date all the time.


Say an old version of Chrome becomes stale and the global usage of that version dips below an arbitrary percentage (which I do not support) such that I no longer need a webkit prefix for a property anymore; I would need to physically check the support tables, manually find out that the prefix fell out, and then crawl and update my entire codebase to remove the unnecessary code. That isn’t good enough if I want smooth sailing.

Fortunately there’s a great tool that plugs into Can I Use’s API: Autoprefixer. In short, it “[parses] CSS and add[s] vendor prefixes to rules by Can I Use”. That gets rid of the headache of updating vendor prefixes to match my arbitrary set of browser support rules, and I don’t even have to write them in my CSS anymore. Very convenient… but not the perfect solution; I still have to manually run this command whenever I want to compile.


Because I also decided to make the switch to SCSS, I was wasting a lot of time in the command line, running the command to compile my SCSS every time I made a change. Then I was minifying it because that’s what I serve to users (using this). To be fair, I actually used a bash alias to run a chain of commands, but I wanted true automation!

It’s only a small amount of time spent each time I wanted to compile my SCSS, but as anyone who writes CSS knows, an awful lot of time is spent tweaking a value, refreshing the browser, tweaking a value, refreshing the browser, and so on. The time spent compiling the SCSS myself added up to one big frustration.

All the while, I desperately wanted to take the responsibility and menial tasks off of my hands: crushing images, compressing CSS, combing my CSS, and compiling my SCSS for the most part.

There must be a better way!

Good news everyone!
There is!

And it comes in the form of gulp. gulp is a streaming build system built on node.js that automates complex tasks for you—the answer to all my prayers! I initially chose an alternative called Grunt which does almost exactly the same thing, but I prefer the workflow used in gulp, which is why I ultimately chose it. I recommend checking it out if you haven’t; you can get started right here!

Let’s see what gulp does for me

How does gulp work?

Here’s a sample gulpfile.js that shows the workflow at play. It should give you a fairly good idea of what’s going on.

What gulp does is runs a series of commands and even listens for and responds to changes. In the example above, from the gulp GitHub repository, gulp is being used to compile multiple coffeescript files, minify them, and concatenate them into a single file as well as compress images. The watch task is being used to listen for changes to particular files and run tasks subsequently. My particular gulpfile.js is used to compile my SCSS, run Autoprefixer, minify the CSS, and refresh my browser. This becomes incredibly useful for front-end developers who are used to a tweak a value, compile, refresh browser workflow when watch is paired with LiveReload to automatically refresh the browser—the workflow then becomes, essentially, tweak a value… tweak a value… tweak a value as saving the file after each tweak would trigger gulp watch to compile, minify, and refesh for you!

Good old brass tacks

Here’s an example of what the CSS for my logo looked like prior to these changes:

Let’s face it, that’s a monumental amount of code to read, let alone scroll through. Although I spent a monumental amount of time organising it well and ensuring it was super-maintainable, there are a lot of repetitions and property values that could be assigned to variables and used elsewhere in the CSS. The advantage of this becomes obvious when you find yourself having to remember bespoke colour values, but we also have a lot of repetitions due to the requirement of vendor prefixes. Although we will need the vendor prefixes again when we deliver CSS to the user on the front-end, because we’re compiling our CSS beforehand, we can get rid of them in our uncompiled stylesheet.


Firstly, let’s remove the vendor prefixes to take advantage of Autoprefixer and Can I Use.

Already looking much better! You’ll notice I was even able to exclude the entire repeated -webkit-keyframes declarations as Autoprefixer will include these for me when gulp runs.


Next, let’s turn this CSS into SCSS.

Just look at it... Beautiful.
Success.

You’ll notice a few major changes

  • the hover, focus, and active states are nested, using an & prefix
  • the after pseudo class is nested, using an & prefix
  • the span child of .logo is nested directly inside .logo
  • the media query is nested inside the .logo declaration as @include breakpoint()
.logo {
    ...
    &:hover,
    &:focus,
    &:active {
        text-decoration: none;
    }
    &:active {
        @include translate3d("0, .039em, 0");
    }
    &:after {
        ...
    }
    /**
     * Only animate when the user hovers the logo.
     */
    &:hover:after,
    &:focus:after,
    &:active:after {
        @include animation-play-state("running");
    }
    @include breakpoint("tablet") {
        height: 1.74em;
        display: inline-block;
        float: none;
        line-height: 1.74em;
    }
    span {
        white-space: nowrap;
    }
}
  • some declaration values are defined as variables, denoted by a preceding $
  • these variables are defined in the variables section of the SCSS
$text-color: #4f4f4f;
$heading-font-stack: "league-gothic", sans-serif;
  • liberal use of @includes
  • these reference @mixins that are defined in the variables section of the SCSS
@mixin breakpoint($width) {
    @if $width == "tablet" {
        @media (max-width: 768px) { @content ; }
    }
    @else if $width == "mobile" {
        @media (max-width: 500px) { @content ; }
    }
}
@mixin transition($transition: "all .15s ease-in-out") {
    transition: #{$transition};
}
@mixin translate3d($values: "0, 0, 0") {
    transform: translate3d(#{$values});
}
@mixin animation($animation: "fade .3s ease-out") {
    animation: #{$animation};
}
@mixin animation-play-state($value: "paused") {
    animation-play-state: #{$value};
}

The CSS here a lot more concise now, and the advantages are tremendous as you get over the learning curve, however short it may be for you. If you extrapolate this methodology of components you can imagine how it simplifies development across a codebase and between contributing developers. Because we’ve defined variables and mixins, it’s now a lot easier to change code across the entire site’s codebase at once, for example: breakpoints, colours, transition timings, typefaces, to name a few.


Another thing, which I won’t bother to illustrate here, is the splitting of files. Similar to how I talked about building a componential CSS architecture, Sass allows you to concatenate multiple SCSS files into one file in the output .css file. I’ve done exactly that with my SCSS files—split them into partials: \_articles.scss, \_asides.scss, \_buttons.scss, etc.—and this helps to create a bird’s-eye-view or holisitic view of the separation of components.

It’s also extremely useful if you build a core set of styles and then extend those styles for bespoke designs in separate files; in this way, you only need to include the core styles on each page, instead of having to pull in all the bespoke CSS and using only a small part of it.

  1. Sass Guide
  2. Sass Guide - Variables
  3. Sass Guide - Nesting
  4. Sass Guide - Partials
  5. Sass Guide - Import
  6. Sass Guide - Mixins
  7. My Sass files
  8. My gulpfile configuration

And if you want to start using gulp, here’s a fantastic guide, Getting started with gulp, by Mark Goodyear.

Wrapping it up

I cannot stress how awesome Sass and SCSS are and how they can drastically speed up your workflow. If you’ve never written Sass or SCSS before, try it with variables first. When you’re building a big stylesheet, or group of stylesheets, it can be a pain to have to remember HEX colour values or font stacks. The advantage of Sass is that it allows you to set these values to variables and use them througout the rest of your CSS; furthermore, if you need to manipulate these colours (lighten, darken, opacity, etc.), Sass has the ability to do this for you, leaving you to only remember the variable names.

The power of Autoprefixer speaks for itself, really.

And with gulp watching, the transition from the SCSS above to the minified CSS happens almost instantly and the browser refreshes almost as soon as you hit Save.

So that’s what’s up

To sum up, the site looks pretty much the same, but the codebase behind it is different. I can’t recommend getting into SCSS and gulp enough. They changed my workflow for the better and I save a lot of time as a result of it. I feel wrong for saying it, being so loyal to vanilla CSS for so long, but writing SCSS feels more natural, and coupled with gulp makes for a seamless and more focussed coding workflow.

You can see the raw, uncompiled SCSS files on GitHub here, and the README file of the repository here.

As always, please let me know if you have any comments, suggestions, or bug-fixes in the comments below or create an Issue on Github!

Latest Articles

All Articles