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

Keeping your Sass squeaky clean - SassConf 2014

Adam Onishi
October 02, 2014

Keeping your Sass squeaky clean - SassConf 2014

In this talk, I will take a look at all the features Sass and Compass put at your disposal, showing you how they can be used in real-world situations with a case study from the new Persil.co.uk website. From making complex responsive front end builds more manageable, working with custom IE style sheets, all the way through to improving the consistency amongst a team of developers. All of this formed part of the work that went into the new Persil website. In the last few years we’ve become quite accustomed to increasing our productivity with preprocessors like Sass or LESS. But how many of us take it much further than using a few variables, nesting our selectors, and using partials. Sass brings much more functionality to the table, including loops, conditionals, functions, and mixins. Now bring Compass into the mix and you have an even more powerful combination with added functions and built-in mixins. I'll show you how you can start cleaning up your own Sass with these advanced techniques that we've been using in the Persil project.

Adam Onishi

October 02, 2014
Tweet

More Decks by Adam Onishi

Other Decks in Technology

Transcript

  1. @onishiweb – Drew McLellan @drewm “Sass is like an F1

    car. It’s powerful and fast, but you need a lot of skill not to die in a fiery ball.” Squeaky
  2. @onishiweb – Stu Robson @sturobson “Helps you care about your

    work. Makes you aware of what you're doing. Gives understanding as to what you're doing. Helps others comprehend what you've done.” http://bit.ly/stus-codelicious Sassy
  3. @onishiweb themes/ |- core/ |- brazil/ |- chile/ |- china/

    |- indonesia/ |- portugal/ |- uk/ Architecture
  4. @onishiweb scss/ |- core/ |- brazil/ |- chile/ |- china/

    |- indonesia/ |- portugal/ |- uk/ Architecture
  5. @onishiweb # Require any additional compass plugins here. ! #

    Set this to the root of your project when deployed: http_path = "/" css_dir = "public/wp-content/themes" sass_dir = "app/scss" javascripts_dir = "app/js" ! fonts_dir = "public/wp-content/assets/fonts" fonts_path = "public/wp-content/assets/fonts" ! http_fonts_path = "/wp-content/assets/fonts" http_fonts_dir = "../../assets/fonts" ! images_dir = "public/wp-content/assets/images" ! http_generated_images_path = "/wp-content/assets/images" http_images_path = "../../assets/images" Hello! Architecture
  6. @onishiweb # Set this to the root of your project

    when # deployed: http_path = "/" css_dir = "public/wp-content/themes" sass_dir = "app/scss" Hello! Architecture
  7. @onishiweb scss/ |- uk/ | |- style.scss | |- ie.scss

    |- indonesia/ | |- style.scss | |- ie.scss Architecture
  8. @onishiweb themes/ |- uk/ | |- style.css | |- ie.css

    |- indonesia/ | |- style.css | |- ie.css Architecture
  9. @onishiweb core/ |- templates/ | |- offers-and-promotions.php | |- parallax.php

    |- partials/ | |- navigation.php | |- content-cross-link.php |- 404.php |- front-page.php |- page-contact-us.php Architecture
  10. @onishiweb core/ |- partials/ | |- pages/ | | |-

    _404.scss | | |- _front-page.scss | | |- _contact-us.scss | | |- _offers-and-promotions.scss | |- components/ | | |- _navigation.scss | | |- _cross-link.scss Architecture
  11. @onishiweb .grid--half { @extend %grid__item; ! @extend %small--one-half; } !

    .grid--whole-whole-half { @extend %grid__item; ! @extend %small--one-whole; @extend %large--one-half; } Architecture
  12. @onishiweb .grid--whole-half-third { @extend %grid__item; ! @extend %small--one-whole; @extend %medium--one-half;

    @extend %large--one-third; ! @include breakpoint(large) { &:nth-of-type(3n + 1) { clear:left; } } } Architecture
  13. @onishiweb $breakpoints: ( 'small' 25em, 'medium' 35em, 'large' 62.5em );

    Helpers/mixins https://github.com/csswizardry/csswizardry-grids
  14. @onishiweb $fix-mqs:false !default; ! @mixin respond-min($width) { // If we're

    outputting for a fixed media query set... @if $fix-mqs { // ...and if we should apply these rules... @if $fix-mqs >= $width { // ...output the content the user gave us. @content; } } @else { // Otherwise, output it using a regular media query @media screen and (min-width: $width) { @content; } } } Helpers/mixins http://jakearchibald.github.io/sass-ie/
  15. @onishiweb @mixin breakpoint($point) { // Get the width of the

    query based on the passed $point variable $width: get-list-value($breakpoints, $point); ! @if $fix-mqs { @if $fix-mqs >= $width { @content; } } @else { @media screen and (min-width: $width) { @content; } } } Helpers/mixins https://github.com/bpscott/breakup
  16. @onishiweb .a-selector { … ! @include breakpoint(large) { … }

    @include tweakpoint(40em) { … } @include max-breakpoint(small) { … } } Helpers/mixins
  17. @onishiweb @mixin old-ie { // Only use this content if

    we're dealing with old IE @if $old-ie { @content; } } ! // Example .outer-container { width:100%; margin:0; ! @include old-ie { width:1000px; } } Helpers/mixins http://jakearchibald.github.io/sass-ie/
  18. @onishiweb // ie.scss ! // Set up defaults and max

    size of page, then // import core ! $old-ie:true; $fix-mqs:63em; // 1000px @import 'core'; Helpers/mixins
  19. @onishiweb // Rems with pixel fallback for any property @mixin

    rem($property, $px-values, $baseline-px: $base-font-size) { // Convert the baseline into rems $baseline-rem: $baseline-px / 1rem; ! // Create an empty list that we can dump values into $rem-values: (); @each $value in $px-values { // If the value is zero, return 0 $rem-values: append($rem-values, if($value == 0, $value, $value / $baseline-rem)); } ! // Output the property's px and rem values #{$property}: $px-values; #{$property}: $rem-values; } Helpers/mixins https://github.com/BPScott/bpscott.github.io/blob/develop/source/stylesheets/vendor/_rem.scss
  20. @onishiweb @mixin font-size($size) { @include rem('font-size', $size + px); }

    ! // Example usage .selector { @include font-size(20); } Helpers/mixins
  21. @onishiweb %clearfix { zoom:1; &:before, &:after { content: '\0020'; display:

    block; height: 0; overflow: hidden; } &:after { clear: both; } } Helpers/mixins
  22. @onishiweb /* Hide the text of an element - for

    use with buttons with background images etc */ %hide-text { display:block; text-indent:100%; white-space:nowrap; overflow:hidden; } ! /* Hide from both screenreaders and browsers: h5bp.com/u */ %hidden { display:none !important; visibility:hidden; } Helpers/mixins
  23. @onishiweb .button-square, %button-square { display:inline-block; margin:0 0 $baseline; padding:5px 7px;

    color:#fff; @include rem('font-size', 14px); line-height:1; font-weight:normal; text-transform:uppercase; background-color:$clr-brand; } Helpers/mixins http://csswizardry.com/2014/01/extending-silent-classes-in-sass/
  24. @onishiweb wp-content/ |- assets/ | |- fonts/ | |- images/

    | | |- uk/ | | |- brazil/ | | |- portugal/ Compass
  25. @onishiweb wp-content/ |- assets/ | |- fonts/ | |- images/

    | | |- common/ | | |- page-headers/ | | |- lightbox/ Compass
  26. @onishiweb # Require any additional compass plugins here. ! #

    Set this to the root of your project when deployed: http_path = "/" css_dir = "public/wp-content/themes" sass_dir = "app/scss" javascripts_dir = "app/js" ! fonts_dir = "public/wp-content/assets/fonts" fonts_path = "public/wp-content/assets/fonts" ! http_fonts_path = "/wp-content/assets/fonts" http_fonts_dir = "../../assets/fonts" ! images_dir = "public/wp-content/assets/images" ! http_generated_images_path = "/wp-content/assets/images" http_images_path = "../../assets/images" Hello! Compass
  27. @onishiweb # General images directory images_dir = "public/wp-content/assets/images" ! #

    Image paths full and relative paths http_generated_images_path = "/wp-content/assets/images" http_images_path = "/wp-content/assets/images" Hello! Compass
  28. @onishiweb image-url(‘common/site-bg.jpg') // Outputs: // url(/wp-content/assets/images/common/site-bg.jpg) ! // Image dimensions

    image-width('smartgold/play.png'); image-height(‘smartgold/play.png'); Hello! Compass
  29. @onishiweb @mixin bg-image($img, $img-2x:false) { width:image-width($img); height:image-height($img); background:image-url($img) no-repeat 0

    0; ! @if $img-2x { @include hidpi-query() { width:image-width($img-2x)/2; height:image-height($img-2x)/2; background:image-url($img-2x) no-repeat 0 0; background-size:(image-width($img-2x)/2) (image- height($img-2x)/2); } } } Hello! Compass
  30. @onishiweb .site-icons-sprite, .site-icons-delete, .site-icons-edit, .site-icons-new, .site-icons-save { background: url('/images/site-icons- s34fe0604ab.png')

    no-repeat; } ! .site-icons-delete { background-position: 0 0; } .site-icons-edit { background-position: 0 -32px; } .site-icons-new { background-position: 0 -64px; } .site-icons-save { background-position: 0 -96px; } Hello! Compass
  31. @onishiweb @import "site-icons/*.png"; ! .actions { .new { @include site-icons-sprite(new);

    } .edit { @include site-icons-sprite(edit); } .save { @include site-icons-sprite(save); } .delete { @include site-icons-sprite(delete); } } Hello! Compass
  32. @onishiweb adjust-lightness($color, $amount); ! adjust-saturation($color, $amount); ! scale-lightness($color, $amount); !

    scale-saturation($color, $amount); ! shade($color, $percentage); ! tint($color, $percentage); Hello! Compass
  33. @onishiweb $clr-brand-hover:shade( $clr-brand, 10% ); ! $clr-kids-activities-hover:shade( $clr-kids-activities, 10% );

    ! $clr-sustainability-hover:shade( $clr-sustainability, 10% ); ! $clr-parenting-hover:shade( $clr-parenting, 10% ); ! $clr-mmr-hover:shade( $clr-mmr, 10% ); Hello! Compass
  34. @onishiweb @include border-radius($radius 0 0 $radius); ! @include box-shadow(0 0

    4px rgba(#000, 0.2)); ! @include transform( scale(1.1) ); ! @include transition(color 0.2s ease); ! @include transition(background-color 0.2s ease); Hello! Compass
  35. @onishiweb // & runs the command in the background //

    in terminal. Freeing up your command line ! > compass watch & > grunt watch & Hello! Compass
  36. @onishiweb – Rick Waldron (idiomatic.js) “Every line of code should

    appear to be written by a single person, no matter the number of contributors.” Team
  37. @onishiweb – Mark Otto @mdo (codeguide.co) “Enforce these, or your

    own, agreed upon guidelines at all times. Small or large, call out what's incorrect.” Team
  38. @onishiweb Rule 1: Obey the rules ! Where possible all

    of these rules should be followed to the letter. But, all rules are open to discussion and review. Obviously there are also times where a rule must be broken, but you should be able to explain why it was necessary and what benefit it gave you. Team
  39. @onishiweb Rule 4: It's all about the bike code. !

    None of these rules are personal, there is no agenda in the rules; it's all about the code. The rules are here to help us write good code and work together as a team. It's about learning as well, front end development is continually evolving with new techniques and new tools becoming available all the time, the rules will keep evolving with these best practices and be updated over time. Team
  40. @onishiweb Rule 12: The correct number of JavaScript libraries to

    know is n+1 ! Most front end developers are familiar with JavaScript and jQuery, but there are now more frameworks than you can shake a stick at! Whether it's Angular, Meteor, Backbone, Ember, Coffeescript, or Node.js there's always something new to learn. Team
  41. @onishiweb Rule 2: Lead by example ! You should make

    yourself familiar with the rules inside and out and ensure your code always follows the rules. Code reviews will be employed and pull requests will be declined if you're found to be breaking the rules. Team
  42. @onishiweb Rule 3: Guide the uninitiated ! You should help

    others follow the rules. Code reviews and pair programming are encouraged. Do your best to make yourself available for code reviews when possible, or make sure if you're a reviewer on a pull request you review the code thoroughly. If code is breaking the rules, comment and state the rule number the coder should check their code against. Team
  43. @onishiweb @mixin breakpoint($point) { // Get the width of the

    query based on the passed $point variable $width: get-list-value($breakpoints, $point); ! @if $fix-mqs { @if $fix-mqs >= $width { @content; } } @else { @media screen and (min-width: $width) { @content; } } } Future
  44. @onishiweb @mixin breakpoint($point) { // Get the width of the

    query based on the passed $point variable $width: map-get($breakpoints, $point); ! @if $fix-mqs { @if $fix-mqs >= $width { @content; } } @else { @media screen and (min-width: $width) { @content; } } } Future
  45. @onishiweb $archive-themes: ( 'default': ( 'color': $clr-brand, 'hover': $clr-brand-hover, 'header':

    'page-headers/bg-header.jpg' ), 'activity': ( 'color': $clr-kids-activities, 'hover': $clr-kids-activities-hover, 'header': 'page-headers/bg-header-pink.jpg' ), 'parenting': ( 'color': $clr-parenting, 'hover': $clr-parenting-hover, 'header': 'page-headers/bg-header-orange.jpg' ), ); Future
  46. @onishiweb @each $theme, $settings in $archive-themes { ! $color:map-get($settings, 'color');

    $hover:map-get($settings, 'hover'); $header:map-get($settings, 'header'); ! $class:'.archive'; ! @if( $theme != 'default') { $class: '.archive.#{$theme}'; } ! #{$class} { […] } } Future
  47. @onishiweb scsslint: { core: ['app/scss/core/**/*.scss'], options: { bundleExec: true, config:

    '.scss-lint.yml', reporterOutput: 'scss-lint-report.xml', colorizeOutput: true, maxBuffer: NaN }, }, Future
  48. @onishiweb core/ |- partials/ | |- pages/ | |- components/

    | |- themes/ | |- shame/ | | |- _kids-activities.scss | | |- _products.scss | | |- _solve-your-stain.scss Future