Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Intro to SASS: Building a flexible grid system

Steve Hickey
October 16, 2013

Intro to SASS: Building a flexible grid system

Steve Hickey

October 16, 2013
Tweet

More Decks by Steve Hickey

Other Decks in Design

Transcript

  1. What does SASS allow us to do? 1. Use variables

    in our CSS 2. Nest selectors for organization 3. Modularize with partials, mixins & functions 4. Extend/inherit style rules 5. Perform math on properties
  2. @import 'bourbon/bourbon'; @import 'reset'; @import 'variables'; @import 'mixins'; @import 'grid';

    @import 'type'; @import 'forms'; @import 'global'; @import 'helpers'; Any filename that starts with an _ is a partial, and SASS won’t output it. The one file without an _ is what SASS watches. It imports all the partials and outputs a single CSS file. You can output multiple files if you want to.
  3. user@machine:~ $ cd into/root-of-repo user@machine:~ $ sass --watch css/sass:css The

    terminal can compile SASS to CSS whenever a file is altered and saved. See sass-lang.com and RTFM for more options. Compile
  4. Variables $primary-color: #049cdb; // blue $heading-typeface: Arial, sans-serif; $modular-scale-base: 1

    // 16px $modular-scale-up1: 1.4375; // 22px /* ===================================== */ h2.article-title { color: $primary-color; font-family: $heading-typeface; line-height: $modular-scale-base; font-size: #{$modular-scale-up1}em; } /* ===================================== */ h2.article-title { color: #049cdb; font-family: Arials, sans-serif; line-height: 1; font-size: 1.4375em; } Store and reuse information in your stylesheets. Pro-tip: this feature alone makes SASS worth it.
  5. Nesting nav.global { width: 100%; a { background-color: #ddd; &:hover

    { background-color: #aaa; } } /* ===================================== */ nav.global { width: 100%; } nav.global a { background-color: #ddd; } nav.global a:hover { background-color: #aaa; } You can keep your code well organized while outputting proper selectors. Obey the Inception Rule. Try not to nest much deeper than 3 levels.
  6. Mixins @mixin border-radius($radius: 4px) { -webkit-border-radius: $radius; -moz-border-radius: $radius; border-radius:

    $radius; } /* ===================================== */ .container { @include border-radius(8px); } /* ===================================== */ .container { -webkit-border-radius: 8px; -moz-border-radius: 8px; border-radius: 8px; } Mixins create a group of styles that can accept arguments and be reused.
  7. Extend .message { border: 1px solid #ccc; padding: 10px; color:

    #333; } .success { @extend .message; border-color: green; } /* ===================================== */ .message, .success { border: 1px solid #ccc; padding: 10px; color: #333; } .success { border-color: green; } This allows you to share properties and avoid having to repeat yourself.
  8. Operators article { float: left; width: (600px / 960px) *

    100%; } aside { float: right; width: (300px / 960px) * 100%; } /* ===================================== */ article { float: left; width: 62.5%; } aside { float: right; width: 31.25%; } SASS allows simple math in your CSS, preserving your original units. This is not like calc() in CSS. You must use similar units.
  9. Functions @function flex-width($target, $context) { @return ($target / $context) *

    100%; } /* ===================================== */ article { float: left; width: flex-width(600px, 960px); } aside { float: right; width: flex-width(300px, 960px); } /* ===================================== */ article { float: left; width: 62.5%; } aside { float: right; width: 31.25%; } Determine your style rules programmatically and reuse the methods.
  10. Grids can be difficult to do well on the web.

    This is why we have so many frameworks, but they have issues. <div class="row"> <h2 class="span4">It slices!</h2> <h2 class="span4">It dices!</h2> <h2 class="span4">It juliennes!</h2> </div> /* ===================================== */ .row { margin-left: -20px; } .row:before, .row:after { display: table; line-height: 0; content: ""; } .row:after { clear: both; } .span4 { width: 300px; }
  11. Our markup will be clean and use (mostly) semantic class

    names. Functions can be used to calculate all of the properties we need. Mixins can be used to attach our styles to semantic class names. <div class="container"> <header role="banner">...</header> <div role="main"> <section class="hero">...</section> <section class="partner-quotes"> <h2>Quotes From Our Partners</h2> <div class="cosby">...</div> <div class="jobs">...</div> <div class="wilde">...</div> <div class="letterman">...</div> <div class="franklin">...</div> <div class="twain">...</div> </section> <section class="executive-team"> <h2>Our Executive Team</h2> <div class="ceo">...</div> <div class="other-executives"> <div class="cto">...</div> <div class="cmo">...</div> <div class="coo">...</div> <div class="cio">...</div> </div> </section> </div> <footer role="contentinfo">...</footer> </div>
  12. We’ll store the grid’s important details in some SASS variables.

    $max-width: 1000px; $column-width: 15%; $gutter: 2%; $max-columns: 6;
  13. Then we’ll create a set of helpful mixins. They have

    use beyond our grid system and should be defined globally. @mixin clearfix { zoom: 1; &:before, &:after { content: ""; display: table; } &:after { clear: both; } } @mixin border-box { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }
  14. @function columns($columns, $parent: $max-columns) { $width: $columns * $column-width +

    ($columns - 1) * $gutter; $parent-width: $parent * $column-width + ($parent - 1) * $gutter; @return percentage($width / $parent-width); } // Borrowed and modified from Bourbon.io Now, the fun stuff. This function uses our variables to figure out flexible column widths.
  15. And this function helps us get the correct width for

    gutters. @function gutter($parent: $max-columns) { $parent-width: $parent * $column-width + ($parent - 1) * $gutter; @return percentage($gutter / $parent-width); } // Borrowed and modified from Bourbon.io
  16. We’ll use these functions on elements like so: div.parent {

    width: columns(3); margin-right: gutter(); div.child { width: columns(1, 3); margin-right: gutter(3); } } /* ===================================== */ div.parent { width: 49%; margin-right: 2%; } div.parent div.child { width: 30.61224%; margin-right: 4.08163%; } And they’ll output this:
  17. A full grid system needs a few more behaviors. This

    mixin helps to control nesting elements. @mixin nesting($children: div) { padding: 0; & > #{$children} { float: left; margin-right: gutter; @include border-box; } }
  18. And this one tells elements to behave like rows. @mixin

    row { width: 100%; max-width: $max-width; margin: 0 auto; @include clearfix; @include nesting; }
  19. For more advanced layouts this function will calculate horizontal element

    offsets. @function offset-columns($columns) { $margin: $columns * $column-width + $columns * $gutter; @return $margin; }
  20. And we can apply it using our offset mixin. @mixin

    offset($from-direction: left, $columns) { @if $from-direction == left { float: left; margin-left: offset-columns($columns); } @if $from-direction == right { float: right; margin-right: offset-columns($columns); } }
  21. The last element in a row is an infuriating problem.

    The best solution is simple, but inelegant. @mixin last { margin-right: 0; float: right; }
  22. Note: I tried :last-child, :first-child and :nth-child(). They would be

    good solutions, but support is bad or intent is wrong.