How to Use Sass to Make Your Site More Maintainable Scott Vandehey - @spaceninja Front-End Engineer - Puppet Labs Devsigner 2014
A presentation at Devsigner 2014 in May 2014 in Portland, OR, USA by Scott Vandehey
How to Use Sass to Make Your Site More Maintainable Scott Vandehey - @spaceninja Front-End Engineer - Puppet Labs Devsigner 2014
DRY • Don’t Repeat Yourself • Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
“Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.” –Brad Bowman
Sass Color Manipulation $r: #f00; // red $b: #00f; // blue p { color: rgba($r, 0.5); // rgba(255,0,0,.5) color: mix($r, $b); // returns #7f007f color: lighten($r, 10%); // returns #ff3333 color: darken($r, 10%); // returns #cc0000 color: complement($r); // returns cyan color: desaturate($r, 10%); // returns #f20d0d }
Variables $brand_green: #76C642; $brand_font: “PT Sans”; $fontstack: #{$brand_font}, Arial, sans-serif; ! .btn { font-family: $fontstack; background: $brand_green; } ! Rendered Output .btn { font-family: “PT Sans”, Arial, sans-serif; background: #76C642; }
Nesting .btn { background: $brand_green; &.orange { background: $brand_orange; } } ! Rendered Output .btn { background: #76C642; } .btn.orange { background: #EFA92D; }
Includes // style.scss // This file combines all partials into one // style sheet that will be loaded on all pages. ! @import @import @import @import @import @import @import @import @import @import @import “vars”; “fonts”; “normalize”; “jquery-ui”; “drupal”; “layout”; “global”; “scoped”; “home”; “blog”; “print”; // // // // // // // // // // // Variables and mixins. Custom fonts. An alternative to CSS resets. jQuery UI overrides. Drupal-Specific Styles. Defines overall page layout. Styles used on every page. Styles scoped to individual pages. Styles scoped to the homepage. Styles scoped to the blog. Styles for printing.
Example Partial /** * global.scss - Global Styles * These styles control the broad strokes of the theme - header, footer, etc. * These styles should apply to every section of the site. / ! / Base Colors & Fonts —————————————————————————— */ body { background: #fff; color: $main_text_color; font:16px/1.5 $fontstack; } a { @include single-transition(color, .25s); text-decoration: none; color: $link_color; &:hover, &:focus, &:active { color: $active_link_color; text-decoration: underline; } }
Extends %shared_code { font: 30px “Comic Sans MS”; color: magenta; } p.ugly { @extend shared_code; color: green; } h1.ugly { @extend shared_code; font-size: 120px; } ! /* output on next slide */
Extends ! Rendered Output p.ugly, h1.ugly { font: 30px “Comic Sans MS”; color: magenta; } p.ugly { color: green; } h1.ugly { font-size: 120px; }
Mixins @mixin font-size($sizeValue, $baseline_px: 16){ font-size: ($sizeValue * 1) + px; font-size: ($sizeValue / $baseline_px) + rem; } ! h1 { @include font-size(36); } ! Rendered Output h1 { font-size: 36px; font-size: 2.25rem; }
Buttons Old .btn { background: $puppet_green; &:hover, &:focus { background: mix(white, $puppet_green, 10%); } &.orange { background: $puppet_orange; &:hover, &:focus { background: mix(white, $puppet_orange, 10%); } } &.purple { background: $puppet_purple; &:hover, &:focus { background: mix(white, $puppet_purple, 10%); } } }
Buttons New @mixin btn($color: $puppet_green) { background: $color; &:hover, &:focus { background: mix(white, $color, 10%); } } .btn { @include btn(); &.orange { @include btn($puppet_orange); } &.purple { @include btn($puppet_purple); } }
Modernizr Testing @mixin yep($feature) { // feature supported .#{$feature} & { @content; } } ! @mixin nope($feature) { // feature not supported .no-#{$feature} & { @content; } } ! /* usage on next slide */
Modernizr Testing #logo { @include yep(svg) { background: url(logo.svg): } @include nope(svg) { background: url(logo.png): } } ! Rendered Output .svg #logo { background: url(logo.svg): } .no-svg #logo { background: url(logo.png): }
Flexible Columns, Fixed Gutter @mixin span-columns($columns, $gutter: 20px) { $gutterWidth: (($columns - 1) * $gutter); $columnWidth: “(100% - #{$gutterWidth}) / #{$columns}”; width: calc($columnWidth); float: left; margin: 0 $gutter $gutter 0; @include nope(csscalc) { // fallback styles for browsers that don’t do calc() } } .three-columns .column { @include span-columns(3); } Rendered Output ! .three-columns .column { width: calc((100% - 40px) / 3); margin: 0 20px 20px 0; } .no-csscalc .three-columns .column { /* fallback styles / } ! / abbreviated for readability. full source: git.io/9vb-Fg */