Skip to content

Instantly share code, notes, and snippets.

@travellingprog
Last active February 23, 2016 03:06
Show Gist options
  • Save travellingprog/c9122c0db23980601a0f to your computer and use it in GitHub Desktop.
Save travellingprog/c9122c0db23980601a0f to your computer and use it in GitHub Desktop.
When Static Prototypes Go Wrong - some of the lessons learned

When Static Prototypes Go Wrong - Styling

For my part of the presentation, I will talk about some of the lessons learned around styling.

Short URL for this page: http://git.io/vgO0C

There's a ton of links embedded in this gist. I invited you to click through them to help you follow along.

Selecting A CSS Preprocessor

TL;DR At this time, I would recommend to choose Sass as your CSS preprocessor, because it comes packed with tons of functionality out-of-the-box, runs quickly (thanks to LibSass), has a large community behind it, and is well-documented. But keep an eye on PostCSS.

Sass vs Less

Less is a CSS preprocessor written in JavaScript, which makes it very easy to run within Node and in the browser. It helps you write your stylesheets in a modular and DRY manner by allowing you to define variables, import external stylesheets, create mixins with parameters, and nest CSS selectors, among other things.

Sass is another CSS preprocessor, that was first written in Ruby. It has all of the features I've listed above for Less, although usually with a different syntax. As a matter of fact, this preprocessor supports two different syntax styles, Sass and Scss.

Sass starts to shine above Less when you compare the more advanced features of these preprocessors. For example, functions in Less require defining a variable within your function, and remembering to use that same variable after your function call:

.average(@x, @y) {
  @average: ((@x + @y) / 2);
}

div {
  .average(16px, 50px); // "call" the mixin
  padding: @average;    // use its "return" value
}

On the other hand, functions in Sass work in a manner that's much more intuitive to developers:

@function average($x, $y) {
    @return ($x + $y) / 2
}

div {
  padding: average(16px, 50px);    // call the function directly where you need the value
}

Take loops as another example. Loops in Less are a rcomplicated affair; they're typically done with the use of two variables and a recursive mixin:

.generate-columns(@n, @i: 1) when (@i =< @n) {
  .column-@{i} {
    width: (@i * 100% / @n);
  }
  .generate-columns(@n, (@i + 1));  // recursive call
}

.generate-columns(4);

/*
output:
  .column-1 {
    width: 25%;
  }
  .column-2 {
    width: 50%;
  }
  .column-3 {
    width: 75%;
  }
  .column-4 {
    width: 100%;
  }
*/

Loops in Sass are much more straightforward, thanks to the built-in @for directive:

@for $i from 1 through 4 {
  .column-#{$i} {
    width: 25% * $i;
  }
}


/*
output:
  .column-1 {
    width: 25%;
  }
  .column-2 {
    width: 50%;
  }
  .column-3 {
    width: 75%;
  }
  .column-4 {
    width: 100%;
  }
*/

Sass comes with other useful directives as well, such as @while, @each and @if.

In the past, one of the common complaints among Sass users was speed. As your application grew, and the number of Sass files along with it, the preprocessing became quite slow. This spells trouble for developers, who want to see their latest changes on the page as soon as possible. The main culprit behind these performance woes was the Ruby engine, which is notorious for slow performance.

Thankfully, the Sass developer community decided to create Libsass, a C/C++ port which is a lot faster. Nonetheless, you should be aware that at the time of writing, it is missing some features of its Ruby counterpart. However, it should be fully compatible by version 3.4, which should arrive very soon.

So overall, by choosing Sass over Less, you're not missing out on any functionality. Quite the contrary, you're gaining some very practical and powerful features.

Sass vs PostCSS

PostCSS has a very unfortunate name in my opinion, because it is certainly used as a pre -processor by the majority of its users. At its core, PostCSS is simply a platform that allows you to write JS plugins that can process and output CSS stylesheets. Like other build tools in the Node universe (e.g. Gulp, Grunt), it doesn't achieve much on its own, and instead harnesses its power from an extensive list of plugins that you pick to install.

Take as an example the very popular plugin right Autoprefixer. This brilliant plugin takes your CSS, checks for missing vendor prefixes, and adds them for you:

/* input: */
:fullscreen a {
    display: flex
}

/* output: */
:-webkit-full-screen a {
    display: -webkit-box;
    display: -webkit-flex;
    display: flex
}
:-moz-full-screen a {
    display: flex
}
:-ms-fullscreen a {
    display: -ms-flexbox;
    display: flex
}
:fullscreen a {
    display: -webkit-box;
    display: -webkit-flex;
    display: -ms-flexbox;
    display: flex
}

However, in my opinion, the power of PostCSS is also its curse. The flipside of being given a library of plugins is that you now need to dedicate some of your time 1) researching, 2) setting up and 3) managing these new dependencies... and hope you didn't make any wrong choices along the way.

For example, say I want nested selectors. Well, guess I better grab PostCSS Nested. Oh, and I'd really like to make use mixins as well... Hmm, do I use PostCSS Mixins or PostCSS Sassy Mixins? Is one more powerful than the other? More popular? Which one is being updated more often? These are all valid questions to ask, but they're time-consuming to answer, and the answer to each one of them may change 3 months down the road.

The other possible pitfall is chaining your plugins in the wrong order, as explained here (scroll to "Plugin Execution Sequence"). This is likely going to be simple to resolve with your initial setup, but as your chain of plugins grows over time, I would expect this issue to become increasingly difficult to fix.

But the larger issue is dependency management. Are you on the latest version of that plugin? Is the newer version going to create issues with your other plugins? What about the plugin's dependencies, are they up to date? Can I count on this plugin being actively maintained? Oh, I just ran into a bug, can I fix it myself or is this thing build on spaghetti code?

Meanwhile, if you just used Sass instead, you would immediately have a ton of great features at your disposal, all bundled up nicely in one clean, well-documented package. With a big community behind it, too!

In my opinion, here's the most crucial question you want to ask yourself: is the enhanced flexibility of PostCSS over Sass worth the extra baggage of dependency management? At the moment, my answer to that is No.

On top of that, your choice of preprocessor has a business recruitment implication. The simple fact is, when it comes time to hire new developers, you're much more likely to find developers out there who are familiar with Sass rather than with your custom PostCSS pipeline.

That's not to say that I'm going to ignore PostCSS. For one thing, Sass and PostCSS are not mutually exclusive. Indeed, many people use Sass with Autoprefixer. And there's a few other major reasons to keep an eye on PostCSS:

  • The PreCSS plugin consolidates a bunch of other PostCSS plugins to provide you many of Sass' features, with a close-enough syntax.
  • The CSSNext plugin allows you to use some future CSS features that haven't yet been implemented in browsers.
  • Because they can easily navigate your stylesheet, PostCSS plugins can serve as CSS analysis tools (e.g. postcss-bem-linter).

I should also mention that PostCSS does have a lot of momentum behind it, and the front-end web development community has demonstrated time and time again that it will throw out yesterday's favorite tool to jump onto the latest trend. So understanding and having some experience with PostCSS might be required to keep up with the community.

Styling Guidelines and Documentation

TL;DR Your team should be equipped with a set of styling guidelines that dictate your preferences and best practices, to promote cohesiveness and avoid pitfalls. You should adopt a standard for documenting your styling directly within the stylesheet. It should also be possible to autogenerate a styleguide. I recommmend documenting with KSS.

Guidelines

Regardless of which CSS preprocessor tool you decide to use, the powerful features it provides will definitely have some gotchas and best practices. For example, with SASS, when should I extend another class and when should I extend a selector placeholder? How many levels of nesting should I be doing? There's also a bunch of questions that don't have any definitive answer but instead come down to personal preference: What should I name this variable? How should I split my stylesheets? Where shoud I define this mixin?

This is where a thorough set of guidelines comes in handy. Still, having your team put together this set of guidelines from scratch would be a very time-consuming, difficult task (developers tend to be a strongly-opinionated bunch). Thankfully, a quick internet search will show you that other people have already spent a huge amount of time pondering these questions, and have been kind enough to publish their conclusions online. Lucky you! Just make use of one of these sets of guidelines, or at least take it as a starting point for your own set of guidelines.

If you're using SASS, then you should definitely take a look at Sass Guidelines. This is a detailed set of opinions on how you should put together your Sass code; it covers all the questions I mentioned above, and many more. At the very least take a look at the summary. On top of that, the source code of its webpage is available on GitHub, so you're welcome to contribute to it or make your own fork of it.

If on the other hand you're looking for guidelines that are shorter and give you more flexibility, then take a look at CSS Trick's Sass Style Guide. You'll also want to look at their more general list of CSS style guides.

Even if you're not using Sass, the two guidelines mentioned above are worth reading through, as many of the opinions they state can easily be applied with other CSS preprocessors.

Documentation

As you application grows, your stylesheets will grow in complexity along with it. You'll create more and more mixins, functions and variables. And you'll create some CSS classes that other developers should use in certains scenarios (e.g. "if any form field is invalid, then apply this .invalid class I just created to to the parent <form>"). Over time, it becomes difficult to keep track of all this functionality. Every so often, you'll want a reminder on what X variable is for, or when Y mixin should be applied.

This is why you should be documenting your stylesheets. From the outset, you should set clear expectations to document anything in your stylesheet that will be used by other stylesheets. You should also set a standard for how that documentation should be written. For maximum clarity, you should write your documentation directly within your stylesheets, and use a tool that can extract all that documentation and output it in a central styleguide.

A great tool for this is KSS (Knyle Style Sheets). The documentation for the KSS is a very quick read, although for some reason it fails to mention the very useful Markup: tag that generates live examples within your central styleguide. Although the original KSS parser was written in Ruby, a Node module port has also been created, which means you should be able to find a plugin for your Node build tool as well (e.g. gulp-kss). Another great feature of the Node port is that it includes a live demo, so you can see how comments in a stylesheet become a web page in the styleguide.

On the other hand, you might have a preference for Docco-style documentation, which shows you your documentation side-by-side with your source code (Underscore provides a good example of this documentation style). In that case, I would point you towards CoreMedia StyleDocco. Just keep in mind that Docco doesn't provide you with any recommended comment format; you'll likely want to set an agreed-upon format to make your styleguide cohesive.

Implementing A Responsive Design

TL;DR Even if you have designers supplying you with the wireframes for mobile/tablet/desktop, you still need to implement that responsive page in a correct manner. Developers should take a quick refresher course on the latest best practices around writing CSS for responsive designs. Your breakpoints should be mobile-first, content-based and defined in ems.

Take A Refresher Course

The world of web development moves quickly, so it's good idea to check what the latest best practices are before you begin your project. Even if you've recently build a fully responsive page, you're more than likely to learn something new and useful. At this time, Google offers a great walkthrough of responsive design and also a free course on Udacity for those who want to take the time to dive deeper. Another great resource is Treehouse's 2014 guide.

Choose A Responsive Layout Type

The latest understanding of responsive design is that all layouts tend to fit under 5 categories:

  1. Mostly Fluid
  2. Column Drop
  3. Layout Shifter
  4. Tiny Tweaks
  5. Off Canvas

You should consider each of these options and understand that some layouts are more difficult to maintain than others. For example, a Layout Shifter approach can be quite difficult to put together, and likely harder to modify afterwards. Ultimately, choose the approach that aligns best with the needs of your web application.

Setting Breakpoints

To begin with, your CSS should be mobile-first: your default styling should reflect your minimum width design, and media queries should be used to apply transformations for bigger screen sizes.

Second of all, the breakpoints values you choose should be dictated by the needs of your content, rather than by the width of a target device. The reasoning here is straightforward: if you only target certain devices, you'll usually end up with weird transition states as you go from one device width to another. An unfortunately, the user might end up seeing that weird state on his preferred devce. Moreover, this approach makes your design more future-proof, as web-viewing devices evolve over time.

Combining the above two recommendations in practice is quite simple. First, you start by setting up your design in its minimum screen width. Then, you stretch the screen width until your content begins to "look broken". That's where you set your breakpoint. Google's responsive walkthrough (mentioned above) provides a great example.

If you want to read more on this approach, I recommend two articles:

Finally, you should define your breakpoints in ems rather than in pixels. In particular, this helps you deal with the accessibility requirement of "zooming text only", because your layout will respond accordingly.

If You Must Hack

In a perfect world, you would never have to write CSS that targets a particular device. But as you likely know, the world of web development is pretty ugly. If you must do a device-specific CSS tweak, I invite you to look at the excellent list of device-targetting media queries put together by CSS Tricks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment