Susy - Compass Plugin

Susy is a semantic CSS grid system for designers.

Build beautiful grids of any type, width and breakdown, without touching your markup or changing the way you work. Built entirely native to [Compass](compass-style.org/), Susy is an expert at fluid grids in an elastic (or fluid, or fixed) shell that stay where you want without ever activating that bloody side-scroll bar. Susy sets your width on the outer element (‘container`), adds a `max-width` of `100%` and builds the rest of your grid in percentages. The philosophy and technique are based on [Natalie Downe](natbat.net/)’s “[CSS Systems](natbat.net/2008/Sep/28/css-systems/)” - which introduces difficult math in the service of beautiful structure. With the power of Compass/Sass, Susy will do that math and let you focus on your designs.

Using simple mixins, columns can be created, suffixed, prefixed, and nested - always in flexible percentages and without touching your markup.

Install

sudo gem install compass-susy-plugin

Create a Susy-based Compass Project

compass create <project name> -r susy -u susy

Then edit your ‘_base.scss`, `_defaults.scss`, `screen.scss` and `print.scss` files accordingly. A reset is added automatically, and includes support for HTML5 elements.

Philosophy and Goals

The method comes from [Natalie Downe](natbat.net/)‘s “[CSS Systems](natbat.net/2008/Sep/28/css-systems/)”, but I’ll cover it here.

It is important for accessibility and usability that we are:

  • Able to control our designs and line-lengths with some amount of precision.

  • Responsive to text sizing: In order for our site to be accessible we need to allow different font-sizes to be set by the client. In order to maintain design integrity of proportions and line-lengths, the grid needs to respond to those sizes.

  • Responsive to window sizing: In order to maintain usability across platforms/monitors, our grid needs to respond to the size of the viewport. This is mainly an issue as the viewport shrinks and we are given a side-scroll bar. No one likes that. On the large end our design integrity and line lengths are more important than taking up all the possible space.

In order to achieve both goals we need to combine the best of the elastic (em-based) and fluid (%-based) models. The solution is simple: First we build a fluid grid, then place it inside an elastic shell, and apply a maximum width to that shell so that it never exceeds the size of the viewport. It’s simple in theory, but daunting in practice, as you constantly have to adjust your math based on the context.

But Susy harnesses the power of Compass and Sass to do all the math for you.

Grid Basics

  • Set up your default grid values (total columns, column width, gutter width, side gutter width), your base font size, and important mixins in ‘_base.scss`.

    Example:
    
        $base-font-size: 16px;
        $base-line-height: 24px;
    
        $total-cols: 12; /* a 12-column grid */
        $col-width: 4em; /* each column is 4em (64px) wide */
        $gutter-width: 1em; /* 1em (16px) gutters between columns */
        $side-gutter-width: $gutter-width; /* 1em (16px) padding at the edges of the page as well */
    
  • Set defaults for all the important HTML tags in ‘_defaults.scss`. It’s better than using the browser defaults. And better than using ours.

  • Create your grid in ‘screen.scss`: apply the `@include susy` mixin at the top level and the `@include container` mixin to the element that contains the page grid. This will set up your font sizes, vertical rhythm, and grid container.

    Example:
    
        @include susy;
    
        #page {
          @include container; 
        }
    
    CSS Output:
    
        body {
          font-size: 100%;
          line-height: 1.5em;
        }
    
        html > body {
          font-size: 16px;
        }
    
        body {
          text-align: center;
        }
    
        #page {
          overflow: hidden;
          display: inline-block;
          text-align: left;
          margin-left: auto;
          margin-right: auto;
          width: 61em;
          max-width: 100%;
        }
        #page {
          display: block;
        }
    
  • Use the ‘@include columns` mixin to declare the width in columns of an element, or `@include full` for any element spanning the full width of its context.

    There is an important distinction between “root” and “nested” contexts in Susy. There is also a distinction between “grid elements” and “non-grid elements”. Grid elements are any elements that you assign a span to, either with the ‘columns` or `full` mixin. Non-Grid elements include everything else. Just as CSS absolute positioning happens in relation to the nearest positioned ancestor, Susy grid “context” depends on the nearest grid-element ancestor. Any element with the `container` as it’s nearest grid ancestor is considered to be in the “root” context. Any element within other grid elements (with a nearest grid ancestor other than the ‘container`) is considered to be in a “nested” context.

    This is important because side-gutters are handled at the root level, as margins on root grid elements. Margins that we don’t want at nested levels. It is also important because Susy grid elements are %-based, and so the context is important to Susy’s math. ‘Full` is simply a shortcut to replace `columns` when the span should be the full width.

    The `columns` mixin:
    
        @include columns($span [, $context]);
    
    The `full` mixin:
    
        @include full([$context]);
    

    Note: Context _must not_ be passed at the root level, and must be passed at nested levels.

  • Use ‘@include alpha` and `@include omega` to declare elements which include the first or last column within their parent element.

    Note: ‘@include alpha` is only needed in the root level, and does nothing in nested contexts. Neither is needed with an `@include full` element.

    The `alpha` and `omega` mixins:
    
        @include alpha;
        @include omega([$context]);
    
    Example Scss:
    
        #page {
          @include container;
          header {
            @include full;
            h1 {
              @include full(12);
            }
          }
          nav {
            @include columns(3);
            @include alpha;
          }
          #content {
            @include columns(9);
            @include omega;
            #main {
              @include columns(6,9);
            }
            aside {
              @include columns(3,9);
              @include omega(9);
            }
          }
        }
    

    Susy’s CSS output uses floats to arrange the columns, widths to set the spans, right-margins to set the getter, and both side margins to set the side-gutters on root ‘alpha` and `omega` elements.

  • Use ‘@include prefix` or `@include suffix` to pad (in columns) the width of an element using left and right padding, or `@include pad` to give both `@include prefix` and `@include suffix` at once.

    The `prefix`, `suffix` and `pad` mixins:
    
        @include prefix($prefix-span [, $context])
        @include prefix($suffix-span [, $context])
        @include pad($prefix-span, $suffix-span [, $context])
    
    Used with `full` these are subtractive, so the full width remains:
    
        header {
          @include full;
          @prefix(2);
        }
    
    Will result in a full-width element, with 2 columns of padding to the left.
    
    Used with `columns` these are addative, so the content width remains:
    
        aside {
          @include columns(3,9);
          @prefix(3,9)
        }
    
    Will result in a 6-column element, with 3 of those columns used as padding 
    on the left.
    

That’s it for the basics! Here’s a sample Susy grid layout:

@include susy;

#page {
  @include container; 
}

header {
  @include full;
  @include pad(1,1);

  h1 {
    @include full(10);
  } 
}

nav {
  @include columns(3);
  @include alpha;
}

#content {
  @include columns(9);
  @include omega;
  #main {
    @include columns(6,9);
  }
  aside {
    @include columns(3,9);
    @include omega(9);
  }
}

Tutorial

Being built…

Extra Utility Mixins

Extra utilities are included in Susy’s ‘utils.scss` file, with additional list options, experimental (CSS3/proprietary) CSS, and more.

  • ‘@include show-grid($src)` - Repeat the specified grid image on an element. Good for testing your baseline and grid.

  • ‘@include inline-block-list()` - Make list items inline-block when floating just won’t do the trick (if you need them centered or right).

  • ‘@include hide` - Hide content from visual browsers while keeping accessability intact.

  • ‘@include skip-link([$top, $right, $bottom, $left])` - Hide a link, and then show it again on focus. the TRBL settings allow you to place it absolutely on display. Default will be top left of the positioning context.

And then the fun stuff in ‘_vertical_rhythm.scss`, originally written by Chris Eppstein and probably moving to the compass core before too long:

  • ‘@include adjust-font-size-to($to_size, [$lines, $from_size])` - adjust the font size and number of baseline (line) units to occupy.

  • ‘@include leader([$lines, $font_size, $property])` and `@include trailer([$lines, $font_size, $property])` - add leading or trailing whitespace to an element. These are added as top and bottom margins (by default) that keep your vertical rhythm intact. You can also send “padding” as the `$property` or use `@include padding-leader` and `@include padding-trailer`. Be aware that this may conflict with uses of rhythm-borders.

  • ‘@include leading-border([$width, $lines, $font_size, $style])` and `@include trailing-border([$width, $lines, $font_size, $style])` will combine border and padding to create borders that also keep the vertical rhythm going. The defaults are `1px, 1, $base_font_size, ’solid’‘. Also available: `@include horizontal-borders` (for both leading and trailing), and `@include rhythm-borders` for applying equal borders and padding to all sides of a box.

Advanced Options

Susy is built for flexibility, so that you always write the code you want to write. While everything should ‘just work’ out of the box, there are plenty of advanced options hidden inside. Here are a few:

  • ‘$hacks` is a boolean constant that you can set in your base.sass file to choose between using targeted hacks for IE (a variation of the star hack in most cases) in your screen.css, or using a conditional-comment targeted ie.css. All the needed mixins are available for either setting. `$hacks` is true by default so there is no extra work maintaining multiple files unless you want to.

    Example 1:
    
        $hacks: true;
    
        #nav {
          @include inline-block-list;          
        }
    
    Example 2:
    
        $hacks: false;
    
        // in screen.scss
        #nav {
          @include inline-block-list;
        }
    
        //in ie.scss
        #nav li {
         @include ie-inline-block; 
        }
    
    It requires more maintenance on your part, but the result is a hack-free
    output.
    
     The Susy mixins that use either hacks or targeted mixins are `@include
    omega` (`@include ie-omega([$right-floated: false])`), `@include
    inline-block` (`@include ie-inline-block`), and `@include
    inline-block-list` which sets `@include inline-block` on the list items.
    
     The ie-specific mixins only add the needed ie-specific adjustments, so
    they need to be used in addition to their counterparts, not on their own.
    
  • ‘gutter($context)` is a function that you can call at any time to return the size of a gutter in your given context as a percentage.

    Example:
    
        #nav {
          padding-right: gutter(5);
        }
    
  • ‘columns($number, $context)` returns the span of `$number` columns in `$context` as a percentage. This span includes any gutters between the columns spanned.

    Example:
    
        #nav {
          padding-left: columns(3,5);
        }
    
  • ‘side_gutter()` is also available and takes no arguments since it is always used at the top nesting level.

  • ‘$px2em` is a variable that represents the height of one pixel as a fraction of your base em-height. Multiply it with your target pixel value to represent that value in ems. Note that this is only accurate at your `$base_font_size`.

    Example:
    
        #nav {
          border-bottom: {
            style: solid;
            width: $px2em*2px;
          };
        }