Slide 1

Slide 1 text

@onishiweb Keeping Your Sass Squeaky Clean Adam Onishi SassConf 2014 - New York

Slide 2

Slide 2 text

@onishiweb Good morning!

Slide 3

Slide 3 text

@onishiweb Hello https://www.flickr.com/photos/simon__syon/8187169079/

Slide 4

Slide 4 text

@onishiweb Hello

Slide 5

Slide 5 text

@onishiweb Squeaky clean Sass?

Slide 6

Slide 6 text

@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

Slide 7

Slide 7 text

@onishiweb maintainable? Understandable? Extendable? Squeaky

Slide 8

Slide 8 text

@onishiweb The Project

Slide 9

Slide 9 text

@onishiweb Project

Slide 10

Slide 10 text

@onishiweb Team

Slide 11

Slide 11 text

@onishiweb • External design company • team of developers • 35 markets worldwide • … Project

Slide 12

Slide 12 text

@onishiweb Warning! Contains WordPress

Slide 13

Slide 13 text

@onishiweb • Multisite • Parent & Child themes • Single codebase Project

Slide 14

Slide 14 text

@onishiweb Sass & Compass Project

Slide 15

Slide 15 text

@onishiweb Getting Sassy

Slide 16

Slide 16 text

@onishiweb • Architecture • Sass helpers/mixins • Compass • Working with a Team Sassy

Slide 17

Slide 17 text

@onishiweb #codelicious @sturobson Sassy http://sass.rocks/news

Slide 18

Slide 18 text

@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

Slide 19

Slide 19 text

@onishiweb Architecture

Slide 20

Slide 20 text

@onishiweb File Organisation Architecture

Slide 21

Slide 21 text

@onishiweb themes/ |- core/ |- brazil/ |- chile/ |- china/ |- indonesia/ |- portugal/ |- uk/ Architecture

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

@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

Slide 24

Slide 24 text

@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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

@onishiweb Components Architecture

Slide 28

Slide 28 text

@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

Slide 29

Slide 29 text

@onishiweb core/ |- partials/ | |- pages/ | | |- _404.scss | | |- _front-page.scss | | |- _contact-us.scss | | |- _offers-and-promotions.scss | |- components/ | | |- _navigation.scss | | |- _cross-link.scss Architecture

Slide 30

Slide 30 text

@onishiweb Tightly coupling templates & Sass Architecture

Slide 31

Slide 31 text

@onishiweb Variables Architecture

Slide 32

Slide 32 text

@onishiweb $font-body $font-headers ! $clr-brand $clr-kids-activities $clr-parenting ! $img-dash-brand $img-dash-kids-activities Architecture

Slide 33

Slide 33 text

@onishiweb $clr-brand:#4BCEFA !default; $clr-kids-activities:#F96EC4 !default; $clr-parenting:#FFB400 !default; $clr-sustainability:#8DD400 !default; $clr-mmr:#009edc !default; Architecture

Slide 34

Slide 34 text

@onishiweb Architecture

Slide 35

Slide 35 text

@onishiweb Architecture

Slide 36

Slide 36 text

@onishiweb Layout & Grid Architecture

Slide 37

Slide 37 text

@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

Slide 38

Slide 38 text

@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

Slide 39

Slide 39 text

@onishiweb Sass Helpers/Mixins

Slide 40

Slide 40 text

@onishiweb Media Queries Helpers/mixins

Slide 41

Slide 41 text

@onishiweb $breakpoints: ( 'small' 25em, 'medium' 35em, 'large' 62.5em ); Helpers/mixins https://github.com/csswizardry/csswizardry-grids

Slide 42

Slide 42 text

@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/

Slide 43

Slide 43 text

@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

Slide 44

Slide 44 text

@onishiweb .site-nav-bar { width:100%; height:50px; ! @include breakpoint(large) { width:300px; height:100%; } } Helpers/mixins

Slide 45

Slide 45 text

@onishiweb .a-selector { … ! @include breakpoint(large) { … } @include tweakpoint(40em) { … } @include max-breakpoint(small) { … } } Helpers/mixins

Slide 46

Slide 46 text

@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/

Slide 47

Slide 47 text

@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

Slide 48

Slide 48 text

@onishiweb REMs Helpers/mixins

Slide 49

Slide 49 text

@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

Slide 50

Slide 50 text

@onishiweb @mixin font-size($size) { @include rem('font-size', $size + px); } ! // Example usage .selector { @include font-size(20); } Helpers/mixins

Slide 51

Slide 51 text

@onishiweb Extending carefully Helpers/mixins

Slide 52

Slide 52 text

@onishiweb %clearfix { zoom:1; &:before, &:after { content: '\0020'; display: block; height: 0; overflow: hidden; } &:after { clear: both; } } Helpers/mixins

Slide 53

Slide 53 text

@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

Slide 54

Slide 54 text

@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/

Slide 55

Slide 55 text

@onishiweb Compass

Slide 56

Slide 56 text

@onishiweb Images Compass

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

@onishiweb wp-content/ |- assets/ | |- fonts/ | |- images/ | | |- common/ | | |- page-headers/ | | |- lightbox/ Compass

Slide 59

Slide 59 text

@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

Slide 60

Slide 60 text

@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

Slide 61

Slide 61 text

@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

Slide 62

Slide 62 text

@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

Slide 63

Slide 63 text

@onishiweb Inline Images Compass

Slide 64

Slide 64 text

@onishiweb .logo { background-image:inline-image('12devslogo.png'); } Hello! Compass

Slide 65

Slide 65 text

@onishiweb Compass

Slide 66

Slide 66 text

@onishiweb Compass

Slide 67

Slide 67 text

@onishiweb Sprites Compass

Slide 68

Slide 68 text

@onishiweb images/site-icons/new.png images/site-icons/edit.png images/site-icons/save.png images/site-icons/delete.png Hello! Compass

Slide 69

Slide 69 text

@onishiweb @import "compass/utilities/sprites"; @import "site-icons/*.png"; @include all-site-icons-sprites; Hello! Compass

Slide 70

Slide 70 text

@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

Slide 71

Slide 71 text

@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

Slide 72

Slide 72 text

@onishiweb Sprites Compass

Slide 73

Slide 73 text

@onishiweb Colours Compass

Slide 74

Slide 74 text

@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

Slide 75

Slide 75 text

@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

Slide 76

Slide 76 text

@onishiweb css3 Mixins Compass

Slide 77

Slide 77 text

@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

Slide 78

Slide 78 text

@onishiweb Build tools Compass

Slide 79

Slide 79 text

@onishiweb // & runs the command in the background // in terminal. Freeing up your command line ! > compass watch & > grunt watch & Hello! Compass

Slide 80

Slide 80 text

@onishiweb Working with a team

Slide 81

Slide 81 text

The Architect dev team, my team! Or funny gif! Justice League? @onishiweb Team

Slide 82

Slide 82 text

@onishiweb Common starting point Team

Slide 83

Slide 83 text

@onishiweb Boilerplates Team

Slide 84

Slide 84 text

@onishiweb Team

Slide 85

Slide 85 text

@onishiweb Front-end Boilerplate Team https://github.com/wearearchitect/Frontend-Boilerplate

Slide 86

Slide 86 text

@onishiweb Team

Slide 87

Slide 87 text

@onishiweb Share Team

Slide 88

Slide 88 text

@onishiweb Developer Déjeuner Team

Slide 89

Slide 89 text

The Architect dev team, my team! Or funny gif! Justice League? @onishiweb Team

Slide 90

Slide 90 text

@onishiweb Tools specialist Team

Slide 91

Slide 91 text

@onishiweb Lightning fast coder Team

Slide 92

Slide 92 text

@onishiweb … Team

Slide 93

Slide 93 text

@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

Slide 94

Slide 94 text

@onishiweb Team

Slide 95

Slide 95 text

@onishiweb Team

Slide 96

Slide 96 text

@onishiweb Team

Slide 97

Slide 97 text

@onishiweb http://cssguidelin.es/ http://codeguide.co/ https://github.com/stubbornella/oocss-code-standards https://github.com/necolas/idiomatic-css https://github.com/anthonyshort/idiomatic-sass https://github.com/cxpartners/coding-standards http://isobar-idev.github.io/code-standards/ http://tmwagency.github.io/TMW-frontend-guidelines/ Team

Slide 98

Slide 98 text

@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

Slide 99

Slide 99 text

@onishiweb Team

Slide 100

Slide 100 text

@onishiweb Team

Slide 101

Slide 101 text

@onishiweb The Rules https://github.com/wearearchitect/Frontend-Rules Team

Slide 102

Slide 102 text

@onishiweb Team

Slide 103

Slide 103 text

@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

Slide 104

Slide 104 text

@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

Slide 105

Slide 105 text

@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

Slide 106

Slide 106 text

@onishiweb Code Reviews Team

Slide 107

Slide 107 text

@onishiweb Team

Slide 108

Slide 108 text

@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

Slide 109

Slide 109 text

@onishiweb Team

Slide 110

Slide 110 text

@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

Slide 111

Slide 111 text

@onishiweb is that Squeaky clean?

Slide 112

Slide 112 text

@onishiweb Architecture Squeaky

Slide 113

Slide 113 text

@onishiweb Tightly coupled Squeaky

Slide 114

Slide 114 text

@onishiweb Sass & Compass Squeaky

Slide 115

Slide 115 text

@onishiweb A Team on the same page Squeaky

Slide 116

Slide 116 text

@onishiweb Not just technical Squeaky

Slide 117

Slide 117 text

@onishiweb … Squeaky

Slide 118

Slide 118 text

@onishiweb Future

Slide 119

Slide 119 text

@onishiweb Refactoring Future

Slide 120

Slide 120 text

@onishiweb – Jack Franklin @Jack_Franklin “Refactoring is for people with their priorities in order.” Future

Slide 121

Slide 121 text

@onishiweb My refactoring journey Future

Slide 122

Slide 122 text

@onishiweb Switching to Maps Future

Slide 123

Slide 123 text

@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

Slide 124

Slide 124 text

@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

Slide 125

Slide 125 text

@onishiweb Loops Future

Slide 126

Slide 126 text

@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

Slide 127

Slide 127 text

@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

Slide 128

Slide 128 text

@onishiweb Future

Slide 129

Slide 129 text

@onishiweb ScssLint Future https://github.com/causes/scss-lint

Slide 130

Slide 130 text

@onishiweb Future

Slide 131

Slide 131 text

@onishiweb scsslint: { core: ['app/scss/core/**/*.scss'], options: { bundleExec: true, config: '.scss-lint.yml', reporterOutput: 'scss-lint-report.xml', colorizeOutput: true, maxBuffer: NaN }, }, Future

Slide 132

Slide 132 text

@onishiweb Future

Slide 133

Slide 133 text

@onishiweb uCSS / unCSS Future https://github.com/ullmark/grunt-ucss https://github.com/giakki/uncss

Slide 134

Slide 134 text

@onishiweb Shame.css http://csswizardry.com/2013/04/shame-css/ Future

Slide 135

Slide 135 text

@onishiweb core/ |- partials/ | |- pages/ | |- components/ | |- themes/ | |- shame/ | | |- _kids-activities.scss | | |- _products.scss | | |- _solve-your-stain.scss Future

Slide 136

Slide 136 text

@onishiweb Autoprefixer vs. Compass mixins Future

Slide 137

Slide 137 text

@onishiweb Performance Future

Slide 138

Slide 138 text

@onishiweb Multiple stylesheets Future http://css-tricks.com/one-two-three/

Slide 139

Slide 139 text

@onishiweb Critical path (head.css) Future

Slide 140

Slide 140 text

@onishiweb We’re all still learning

Slide 141

Slide 141 text

@onishiweb Thank You!