Last week I wrote a lengthy article over at Smashing Magazine covering different techniques to prepare websites and web apps for Retina devices. The feedback has been overwhelmingly good, but it also highlighted an apparent divide in the web design and development community over the why and the how of this transition.
Several commenters have argued that optimizing for Retina is unnecessary given the insignificant market share of HiDPI devices; that is simply beside the point. Those who are not convinced that offering a superior experience to a growing portion of their user base is worthwhile are clearly not the target audience.
The first section of the article attempts to clear out some of the confusion surrounding the difference between device, CSS, and bitmap pixels, while the second goes over the different approaches to serve high resolution images to Retina devices, namely:
HTML/CSS sizing: a straightforward solution that consists in using images with a bitmap resolution that is exactly double their CSS target size. Generally speaking, this approach is not bandwidth-friendly and should be avoided in most cases.
CSS/JS media querying: currently the most popular approach given its flexibility and bandwidth efficiency (serves only one asset per device). Its main shortcoming is the often tedious multiple-asset workflow (separate files for each media query).
SVG: the vector graphic format of the web. Ideal for icons, logos, and simple graphics. SVG works best with a PNG fallback for older browsers.
Icon fonts: consists in serving resolution-independent icons using @font-face with a custom web font. The lack of pixel-level control and editability are easily made up for with more flexibility and ease of use.
Following the suggestion of some readers, I put together a live examples page showcasing most of the techniques covered in the article. The page is comprised of two sets of examples, each yielding the same crisp results regardless of the screen density. Feel free to refer to it for a quick fix, and make sure to keep an eye on the repo for updates.
The primary goal of the article was to introduce plugin-free, client-side approaches to get started with resolution-agnostic web design. If you have been longing for a comprehensive list of JS libraries (both client and server side) for serving responsive images, look no further than this comparison chart put together by Boris Smus.
The newly introduced content blocks in Sass 3.2 make it extremely easy to use CSS querying without having to worry about the math or the verbose syntax. Enter the retina() mixin:
@mixin retina($ratio: 1.3) {
@media only screen and (-webkit-min-device-pixel-ratio: $ratio),
only screen and (min--moz-device-pixel-ratio: $ratio),
only screen and (-o-min-device-pixel-ratio: ($ratio*10)/10),
only screen and (min-resolution: #{round($ratio*96)}dpi),
only screen and (min-resolution: #{$ratio}dppx) {
@content;
}
}
The default ratio of 1.3 is meant to include Google Nexus 7 in the query, as Marc Edwards reports. I also intentionally left out the un-prefixed min-device-pixel-ratio since as it stands now, there seems to be little prospects of it being standardized. Meanwhile, the future-proof min-resolution seems to have a wider browser support and is more likely to replace Webkit’s device-pixel-ratio once the transition from inches (dpi) to pixels (ddpx) is complete.
Everyone would agree that none of the currently available solutions is striking a good balance between graphic crispness, ease of implementation, loading speed and cross-browser compatibility. And as many readers pointed out, it is going to take a while before we get anywhere close to that.
In the meantime, here some are immediately actionable items that would make this transition much less painful:
Replace your PNG icons with SVG when appropriate. Use PNG fallbacks if you care about the pre-IE9 crowd. You may use icon fonts as well if you can live with less pixel-level control.
Prepare @2x versions of prominent images in your website or app (splash screens, backgrounds, patterns, etc.) and use CSS or JS querying to swap them in on HiDPI devices. For inline images, your best bet for now is to use one of the available JS libraries.
Use CSS as much as possible for typography and UI elements. CSS3 is in the process of obsoleting Photoshop, and for a good reason.
While it may sound unreasonable—especially in a business context—to do all this “extra” work for every design project, you’d be surprised at how these practices make you much more efficient and improve your overall design workflow.
Sass 3.2 has finally come out last week as a stable release, bringing in a slew of new features to help you write cleaner and more maintainable stylesheets. Here are some modern web development techniques that leverage these features.
Mixins can now accept blocks of content using the new @content syntax. This opens the doors to DRY up your media queries and browser hacks. What used to be:
article {
width: 70%;
@media screen and (min-width: 54em) {
width: 100%;
}
}
aside {
width: 30%;
@media screen and (min-width: 54em) {
display: none;
}
}
…can now be written as:
@mixin desktop {
@media screen and (min-width: 54em) {
@content;
}
}
article {
width: 70%;
@include desktop {
width: 100%;
}
}
aside {
width: 30%;
@include desktop {
display: none;
}
}
The CSS output would remain unchanged:
article {
width: 70%;
}
@media screen and (min-width: 54em) {
article {
width: 100%;
}
}
aside {
width: 30%;
}
@media screen and (min-width: 54em) {
aside {
display: none;
}
}
With the help of a block mixin, changing the breakpoint for all the declarations is just one value away. Better yet, you can use variable breakpoints to generate content-specific media-queries:
@mixin desktop($breakpoint: 54em) {
@media screen and (min-width: $breakpoint) {
@content;
}
}
header {
height: 200px;
@include desktop(50em) {
height: 100px;
}
}
// CSS Output
header {
height: 200px;
}
@media screen and (min-width: 50em) {
header {
height: 100px;
}
}
Content blocks can also be used for legacy browser styles:
@mixin ie7 {
* + html & { // Using browser hacks
@content;
}
}
@mixin ie8 {
html.ie8 & { // Using Paul Irish's conditional comments
@content;
}
}
aside {
color: #000;
@include ie7 {
color: #555;
}
@include ie8 {
color: #444;
}
}
// CSS output
aside {
color: #000;
}
* + html aside {
color: #555;
}
html.ie8 aside {
color: #444;
}
Prior to Sass 3.2, styles meant to be extended were also compiled in the output, making extends less appealing in many situations. Enter placeholder selectors.
%banner {
background-color: #eee;
border: 1px solid #ddd;
font-family: 'Helvetica', sans-serif;
}
.yellow-banner {
@extend %banner;
background-color: yellow;
}
.red-banner {
@extend %banner;
background-color: red;
}
// CSS Output
.yellow-banner, .red-banner {
background-color: #eee;
border: 1px solid #ddd;
font-family: 'Helvetica', sans-serif;
}
.yellow-banner {
background-color: yellow;
}
.red-banner {
background-color: red;
}
Placeholder selectors do not appear in the compiled css and are simply ignored if they are not extended by any other selector.
Sass 3.2 makes interpolation even more useful by extending it to plain CSS directives such as @media and @keyframe. This means you can finally use variables in your keyframe definitions:
@mixin keyframes($animation-name) {
@-webkit-keyframes $animation-name {
@content;
}
@-moz-keyframes $animation-name {
@content;
}
@keyframes $animation-name {
@content;
}
}
@include keyframes(slide-down) {
0%, 100% { opacity: 1; }
10%, 90% { opacity: 0; }
}
// CSS Output
@-webkit-keyframes slide-down {
0%, 100% { opacity: 1; }
10%, 90% { opacity: 0; }
}
@-moz-keyframes slide-down {
0%, 100% { opacity: 1; }
10%, 90% { opacity: 0; }
}
@keyframes slide-down {
0%, 100% { opacity: 1; }
10%, 90% { opacity: 0; }
}
Some of these new features, namely content blocks, may produce more code at the end of the day. That said, it’s an easy trade-off considering how easy they make it to write more organized and maintainable code.

Ben Orenstein is joined this week by Phil LaPier, the creator of Bourbon and a designer at thoughtbot.
In episode #2 Ben and Phil discuss the design process, fundamentals of visual design, common design errors, and how to be a better designer (even if you’re a developer), and how to work with designers as a developer. They also answer some audience questions about design: How to handle feedback from clients, and HAML vs. HTML.
Call us toll-free at 1-877-9-ROBOTS x198 and leave a voicemail. That’s (877) 976-2687 x198, email your questions to info@thoughtbot.com or Tweet to us @thoughtbot.

Aside from applying that killer layout and visual design to your project, stylesheets need to be organized in a way that effectively communicates markup and style relationships and allows for quick and easy modification. A good measure of a well architected front-end is how easy it is for a new team member to jump into your project or for a new team to it take over. If your methods for organization and selector naming aren’t consistent and easily communicated to or understood by others, you’re probably creating a lot of code debt and certainly creating a higher than necessary barrier to entry for newcomers to the project.
Thanks to the partials feature in css preprocessors like Sass, less.js, and Stylus, we can organize our stylesheets better than ever before. We work with Sass because it comes built into rails and it’s awesome.
From the very start, all the apps we build come with a gem we built called Flutie. Flutie provides a stylesheet reset and most importantly, a method that adds a class name to the body element of every page. The body class name is made from the name of the controller and action responsible for generating that page. This allows us to target specific pages by using the unique body class and it also helps us semantically model our stylesheets directory after our views directory. So if we have a Clips controller with an Edit action and we have an associated view for that action called edit.html.erb in views/clips/ then the body element in that view would get a class of .clips clips-edit and in our stylesheets directory we should create a sass partial called _clips_edit.scss, if we are going to be applying styles to that view. Instead of namespacing the .scss files you could group your style sheets in folders (ex: clips/_edit.scss) the same way the rails views are organized. Organizing your styles in this way makes it much easier to find the styles you’re looking for when working between the browser’s inspector and your text editor.

So what about all the variables, mixins, extends, and other great stuff you can do with Sass and most other preprocessors, where do they go? We have found that organizing our variables, extends, mixins, animations and general base styles (default styles for things like typography, links, etc) in partials to be very useful. These partials are usually namespaced with _base or kept in a folder base/. So in a typical project I will have _base.scss, _base_variables.scss, _base_mixins.scss etc.
Often times we will build components of an application to be modular. So to keep the styles for these components modular as well, we create “shared” partials. If in your application you have a header component that maintains all or the majority of its styles across multiple views in your app, create a partial called _shared_header.scss or put _header.scss into a “shared” folder. If you have a view, clips_index.html.erb for example, in your app that is sharing the header with another view (clips_edit.html.erb lets say) but needs a slight tweak, target the header component in the _clips_index.scss stylesheet partial and make the clips_index.html.erb view specific tweaks there.
Now that we have our styles logically organized we create a file, often called application.scss or screen.scss, in which we import all of our partials with the @import directive (ex: @import “clips_edit.scss”;) to render the single stylesheet our app will use. The order in which you import these files is important as the import will render the contents of the imported files in the order they are imported and these are cascading styles sheets after all, so make sure you are importing your variables and base styles at the top.

As a consulting shop, one of our goals is to deliver clean code that our clients can continue to easily work with and grow after we are done working on the project. From the front-end perspective, an important piece of making that happen is keeping our markup and styles clearly organized by constantly using agreed upon methods. All code should look like it was written by one person, regardless of the actual number of contributors. Trying to work in a large application that has no clear reasoning for the structure of its front-end can feel like battling a kraken with a countless number of limbs. So even if you will be the only person ever working on a project, your future self will certainly appreciate the efforts you make now to keep your styles organized, modular and easily modified.

I’ll have to admit that, for years, I have resisted designing with flexible (fluid) layout mostly because I didn’t want to figure out all the math to make it work properly. My other problem was that, at certain sizes, the design just seemed to fall apart. For the longest time I was unconvinced that it was worth all of the effort that it would take to get the grid working correctly and looking good.
After reading Ethan Marcotte’s article and book on responsive design, I was convinced to try it again. I thought that I could amend the grid-width function already in Bourbon to my needs by giving the variables percentage value. I was wrong. It didn’t handle sub-containers because the ratio between columns and gutters changes.
I could still use Sass to do the math ( target ÷ container = percentage ). I gave the grid-width function a makeover to accommodate this and the result is flex-grid.
Start off by declaring a couple variables for the function. $fg-max-columns is the total number of columns in your grid. $fg-column and $fg-gutter define the relationship between column and gutter. I use pixels here because it is what I am most accustomed to.
// 960 12 column grid $fg-max-columns: 12; $fg-column: 60px; $fg-gutter: 20px;
The function takes two values: the number of columns that you want the element to span and its container column (which defaults to $fg-max-columns). This way the function allows you to nest containers without losing the relationship between column and gutter. For example:
body {
margin: 0 auto;
max-width: 1400px;
width: flex-grid(12);
section {
float: left;
width: flex-grid(8); // No second value needed since it's inside the main container
article {
float: left;
width: flex-grid(6, 8); // Since the article is inside the 8 column section
}
aside {
float: left;
width: flex-grid(2, 8);
}
}
}
You’ll notice the grid doesn’t have any gutters yet. They too can take two arguments, a container column count and gutter width. Container is set to your default max columns ($fg-max-columns) and gutter is set to $fg-gutter, which you’ll almost never need to change.
section {
float: left;
margin-right: flex-gutter();
width: flex-grid(8);
article {
float: left;
margin-right: flex-gutter();
width: flex-grid(6, 8);
}
aside {
float: left;
width: flex-grid(2, 8);
}
}
I add a max-width to my main container, mostly for me because I’m usually browsing at full screen on a 30” monitor. Since the grid is totally percentage based, I usually look to where the line-length becomes too long.
body {
margin: 0 auto;
width: flex-grid(12);
max-width: 1400px;
}