Here at Advomatic we've experimented with several approaches to responsive design over the past few years. I think the "mobile first" philosophy became popular right in the nick of time. There was a point when we'd detect if the user was on a mobile device and then deliver a separate mobile theme. This meant two instances of a site to develop for and maintain. I can't imagine doing that now, given the amount of device width/height possibilities and device-specific bugs that exist out there. So, now we work on layout with the goal of accommodating the content rather than the device. To accommodate a responsive and flexible layout, it's best to get your site on a grid. There are tons of options out there, but we've found one in particular helps you quickly get rolling and set up with a column layout that can adjust to whatever device you need your site to display on (and is fun to work with, too). Lately, it's been part of our holy trinity for responsive theming: Sass, Compass and Susy.
First things first: ditch pixels
One big first step to responsiveness in your site is to stop using pixel units for measurements. We use em units because they are proportional to any parent measurement, and therefore flexible and responsive. If we have a base font-size set on the body element of 16px, and our #footer is set to 1.6em, that #footer font-size will automatically scale up or down accordingly if the body's (or any parent element to #footer, for that matter) font-size changes. To manually figure out exactly what em value you should be using for an element, you can use a commonly used formula: target ÷ context = result… or you could do it the easy way with a Sass function:
// Create em() for setting font-sizes in pixels.
@function em($target, $context: $base-font-size) {
@if $target == 0 { @return 0 }
@return $target / $context + 0em;
}
// Example usage: font-size: em(21px);
// This will set the font-size to 21px in relation to the browser's base font size if it has not been established in any parent element, or in relation to $base-font-size which is a variable you can set in your Sass.
// Example usage 2: font-size: em(12px, 10px);
// This will set the font-size to 12px in relation to a parent element's font-size of 10px.
Get on the grid
If you're doing front end development these days, you're probably familiar with the concept of grid-based design and translating a comp into a fully fluid or adaptive layout via HTML/CSS. We frequently use Zen 5 as a base theme and have been big fans over the years because it comes loaded with many of the best tools for front end/theme development, while also pretty lean as far as bloat goes. While it's important to be able to build themes for browsers that can handle fancy bells and whistles, we also need to support older browsers that don't. Zen 5 already has Sass and Compass integrated. As far as a grid framework goes, we use Susy instead of Zen Grids… this has just come down to personal preference. Zen Grids is also a great system. Susy is a responsive grid framework/plugin for Compass, and it allows you to build on top of either a "magic", static or completely fluid grid.
- "Magic" grids are the default – they have an elastic container that responds to font sizes when set with em units, and is fluid on the inside. It's container size gets calculated according to the widths of your columns and gutters.
- Static grids are just that – all containers and column widths are not flexible and this is the traditional grid style. As such, it does not collapse when the viewport is smaller than the grid is wide. Even though you may specify pixel values for the column sizes, Susy converts to a percentage of the container size. The container size, like the magic grid, gets calculated according to the widths of your columns and gutters.
- Fluid grids are truly flexible layouts that respond to the width of the viewport. By default the container width is 100%. However, as with any grid type you choose, you can specify this with the $container-width variable (such as "$container-width: 70%").
Set it all up
To add Susy to your theme, there are a few things you'll need to do.
-
If you haven't already, install Sass and Compass.
sudo apt-get install rubygems
sudo gem update
sudo gem install sass
sudo gem install compass
-
Set up a Compass project in your theme directory.
This is already done for you with Zen 5. If you're not using Zen 5 or a contrib theme that has this done already (look for a config.rb file in the theme directory), then set up your Compass project by going to your theme directory in your favorite command line interface and run:
This will add a "config.rb" file to your theme, and is where the Compass project settings are located.
compass create nameofyourtheme
-
Then, install Susy.
sudo gem install susy
-
Require Susy in your Compass project.
Open up the config.rb file and add the following (wherever "requires" are located):
require "susy"
-
@include susy and add grid settings to your _base.scss (or equivalent "global" Sass file).
We usually stick any of our grid settings in the _base.scss file that comes with Zen so that the grid variables set there are available to any other Sass stylesheet in the theme (because Zen's base gets @imported in them all). You'll also want to place them in whatever Sass file you're using that gets imported into any file where you'll be doing responsive styling/layout. For example:
@import "susy";
$total-columns: 12; // a 12-column grid
$column-width: 4em; // each column is 4em wide
$gutter-width: 1em; // 1em gutters between columns
$grid-padding: $gutter-width; // grid-padding equal to gutters
After installing Susy, and getting your Compass project set up properly for the theme, you'll want to tweak those default grid settings that you just added (total columns, column width, grid padding, etc…) for the purpose of your own design. Using those settings, Susy will automatically figure out the math and put percentage widths on internal grid elements, as well as a max-width on the container (should you use a non-fluid grid). By default, all Susy grids are "magic." If you want to use one of the other types of grids, you would do that by setting the $container-style variable. For example, to build a 5 column-wide mobile first "magic" layout, we can do something like this:
$total-columns: 5;
$column-width: 3em;
$gutter-width: .75em;
$grid-padding: $gutter-width;
Making things happen at different viewport sizes
Another handy part of Susy is its at-breakpoint() mixin. This can be used in replacement of a long and drawn out media query that targets specific pixel-based min-width or max-width values of the viewport. Something we do frequently for adaptive/responsive layouts (where there are established, comp-determined breakpoints for mobile, tablet, desktop), is set variables for different numbers of grid columns.
So if you're building in a mobile first manner like this, and you want something to happen at a certain breakpoint in your Sass, you can use at-breakpoint() with your column count variables as an argument.
$mobile : 5;
$tablet : 11;
$desktop : 16;
In this situation, #content normally spans 5 columns wide, which is the default/mobile width of the grid in this example. When the viewport is at the desktop breakpoint (16 columns can fit in the viewport), the width of #content will change. span-columns(13, $desktop) means "make this 13 columns wide, out of 16 total columns". prefix(3, $desktop) means "add 3 columns of empty space beforehand." So #content becomes 16 columns wide in total, however only 13 columns of space are usable and contain content, since we added 3 columns of padding to the start. A different, non-layout related way of using at-breakpoint() is to maybe change some kind of style at a given breakpoint.
#content {
@include span-columns(5);
@include at-breakpoint($desktop) {
@include span-columns(13, $desktop);
@include prefix(3, $desktop);
}
}
Having at-breakpoint() at the ready is a great way of releasing yourself of the mindset and clutter of maintaining several pixel-based breakpoints in your site, and helps future-proof things since device sizes are fluctuating so wildly as time goes on. Since Sass supports code nesting, it has become standard operating procedure for us to use at-breakpoint() at the end of things in a selector's nested styles, so that they override any established defaults (which are usually the mobile version styles if we are building mobile-first).
padding-bottom: em(15px);
@include at-breakpoint($desktop) {
padding-bottom: em(85px);
background: url("bg-content.png") 162px 100% no-repeat;
}
Alternatively, Aurora
While we normally use Zen and add Susy in manually (replacing Zen Grids), some themes have Susy, Sass and Compass (and other front end goodies) baked in already. Aurora is also a Sass & Compass-powered minimalist theme with a focus on best practices for HTML5 and front end development within Drupal. It has a number of cool features like Google Chrome Frame and Typekit integration. Aurora encourages the use of Panels' HTML5 Sections layout instead of using the standard Drupal left/right sidebar block regions for sidebars. Aurora also suggests you use the Blockify module to turn all the little things on the page that normally get rendered in a page template variable into blocks that you can assign to regions via Drupal's block admin page. There are a number of features in Aurora which have been pulled out and put into a separate module, so that any theme can make use of them. That module is called Magic and some of it's best features are the ability to exclude certain CSS/JS from being included, exporting of theme settings, enhancement of CSS aggregation and adding a viewport width indicator – which is very helpful when developing a responsive site to check all your breakpoints and everything in between.
Conclusion
Susy provides a great way of quickly getting your site layout blocked out and can produce any kind of grid you need. What has your experience been like using Susy in Drupal?