On Github una / slides-intro-to-sass
Syntactically Awesome Style Sheets: Sass is the most mature, stable, and powerful professional grade CSS extension language in the world. sass-lang.com
Sass is a CSS preprocessor.
Simply put -- Sass converts into CSS. Thats all. Sass solves a lot of problems that CSS has. you only ever edit your sass files. don't touch the CSS.navbar .nav .dropdown-toggle .caret, .navbar .nav .open.dropdown .caret { border-top-color: #ffffff; } .navbar .nav .active .caret { opacity: 1; filter: alpha(opacity=100); } .navbar .nav .open > .dropdown-toggle, .navbar .nav .active > .dropdown-toggle, .navbar .nav .open.active > .dropdown-toggle { background-color: transparent; } .navbar .nav .active > .dropdown-toggle:hover { color: #ffffff; } .navbar .nav.pull-right .dropdown-menu { left: auto; right: 0; } .navbar .nav.pull-right .dropdown-menu:before { left: auto; right: 12px; } .navbar .nav.pull-right .dropdown-menu:after { left: auto; right: 13px; } .breadcrumb { padding: 7px 14px; margin: 0 0 18px; background-color: #fbfbfb; background-image: -moz-linear-gradient(top, #ffffff, #f5f5f5); background-image: -ms-linear-gradient(top, #ffffff, #f5f5f5); background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), to(#f5f5f5)); background-image: -webkit-linear-gradient(top, #ffffff, #f5f5f5); background-image: -o-linear-gradient(top, #ffffff, #f5f5f5); background-image: linear-gradient(top, #ffffff, #f5f5f5); background-repeat: repeat-x; filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0); border: 1px solid #ddd; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: inset 0 1px 0 #ffffff; -moz-box-shadow: inset 0 1px 0 #ffffff; box-shadow: inset 0 1px 0 #ffffff; } .breadcrumb li { display: inline-block; text-shadow: 0 1px 0 #ffffff; } .breadcrumb .divider { padding: 0 5px; color: #999999; } .breadcrumb .active a { color: #333333; } .pagination { height: 36px; margin: 18px 0; } .pagination ul { display: inline-block; *display: inline; /* IE7 inline-block hack */ *zoom: 1; margin-left: 0; margin-bottom: 0; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); } .pagination li { display: inline; } .pagination a { float: left; padding: 0 14px; line-height: 34px; text-decoration: none; border: 1px solid #ddd; border-left-width: 0; } .pagination a:hover, .pagination .active a { background-color: #f5f5f5; } .pagination .active a { color: #999999; cursor: default; } .pagination .disabled a, .pagination .disabled a:hover { color: #999999; background-color: transparent; cursor: default; } .pagination li:first-child a { border-left-width: 1px; -webkit-border-radius: 3px 0 0 3px; -moz-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; } .pagination li:last-child a { -webkit-border-radius: 0 3px 3px 0; -moz-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; } .pagination-centered { text-align: center; } .pagination-right { text-align: right; } .pager { margin-left: 0; margin-bottom: 18px; list-style: none; text-align: center; *zoom: 1; } .pager:before, .pager:after { display: table; content: ""; } .pager:after { clear: both; } .pager li { display: inline; } .pager a { display: inline-block; padding: 5px 14px; background-color: #fff; border: 1px solid #ddd; -webkit-border-radius: 15px; -moz-border-radius: 15px; border-radius: 15px; } .pager a:hover { text-decoration: none; background-color: #f5f5f5; } .pager .next a { float: right; } .pager .previous a { float: left; }
Watching folders
#sidebar width: 30% background-color: #faaVariables: ! Assignment: =
#sidebar { width: 30%; background-color: #faa; }
Placeholders for values used multiple times.
$open-sans-stack: 'Open Sans', Arial, Helvetica, sans-serif; $pink: #c69; body { font-family: $open-sans-stack; } h2 { color: $pink; }
body { font-family: "Open Sans", sans-serif; } h2 { color: #c69; }
Variables should be abstracted into themes.
// variables.scss $open-sans-stack: 'Open Sans', Arial, Helvetica, sans-serif; $pink: #c69; // theme.scss $font--copy: $open-sans-stack; $header--color: $pink; // typography.scss body { font-family: $open-sans-stack; } h2 { color: $header--color; }
body { font-family: "Open Sans", sans-serif; } h2 { color: #c69; }
Nesting allows you to organize your code in relevant chunks
.sidebar { float: left; h2 { font-size: 1.2em; } }
.sidebar { float: left; } .sidebar h2 { font-size: 1.2em; }
Do not do this.
body { sidebar { .news-section { .description { a { color: #f00; } } } } }
body sidebar .news-section .description a { color: #f00; }
$blue: #00f; .blue-link { color: $blue; &:hover, &:focus { color: mix($blue, white, 50%); } }
.blue-link { color: #00f; } .blue-link:hover, .blue-link:focus { color: #7f7fff; }
.unicorn { .set-one & { display: none; } } .button--large { .sidebar & { font-size: 80%; } }
.set-one .unicorn { display: none; } .sidebar .button--large { font-size: 80%; }
Extending will append the element to recieve the style block.
.kitten { background-image: url("../img/kitten.png"); } .kitten-with-hat { @extend .kitten; &:after { content: " "; background-image: url("../img/hat.png"); } }
.kitten, .kitten-with-hat { background-image: url("../img/kitten.png"); } .kitten-with-hat:after { content: " "; background-image: url("../img/hat.png"); }
Placeholders are "invisible" until extended
$pink: #c69; $blue: #00f; // I'm not real yet %link { text-decoration: none; font-weight: 300; } .pink-link { @extend %link; //extending color: $pink; } .blue-link { @extend %link; //extending color: #00f; }
.pink-link, .blue-link { text-decoration: none; font-weight: 300; } .pink-link { color: #c69; } .blue-link { color: #00f; }
Sass files are split into "partials" for better organization.
@import "vendors/bootstrap"; @import "vendors/jquery-ui"; @import "utils/variables"; @import "utils/functions"; @import "utils/mixins"; @import "utils/placeholders"; @import "base/reset"; @import "base/typography"; @import "layout/navigation"; @import "layout/grid"; @import "layout/header"; @import "layout/footer"; @import "layout/sidebar"; @import "layout/forms"; @import "components/buttons"; @import "components/carousel"; @import "components/cover"; @import "components/dropdown"; @import "pages/home"; @import "pages/contact"; @import "themes/theme"; @import "themes/admin";
Mixins are blocks of code you @include
@mixin center-block { display: block; margin-left: auto; margin-right: auto; } .nyan-cat { width: 450px; @include center-block; //including here }
.nyan-cat { width: 450px; display: block; margin-left: auto; margin-right: auto; }
Mixins can accept parameters, making them even more flexible
@mixin box-shadow($shadow) { -webkit-box-shadow: $shadow; -moz-box-shadow: $shadow; box-shadow: $shadow; } .box { @include box-shadow(0 0 0 3px #aaa) }
.box { -webkit-box-shadow: 0 0 0 3px #aaa; -moz-box-shadow: 0 0 0 3px #aaa; box-shadow: 0 0 0 3px #aaa; }
@mixin shadows($shadows...) { box-shadow: $shadows; }
Mixins can take a variety of args, including @content blocks.
//mixin @mixin smaller-than($width) { @media (max-width: $width) { @content; } } @mixin larger-than($width) { @media (min-width: $width) { @content; } } //usage .heading { font-size: 2em; @include smaller-than(300px) { font-size: 1.5em; } @include larger-than(768px) { font-size: 3em; } }
.heading { font-size: 2em; } @media (max-width: 300px) { .heading { font-size: 1.5em; } } @media (min-width: 768px) { .heading { font-size: 3em; } }
$social-icons: twitter, facebook, instagram, dribbble;
$types: text #f00, photo #c69, video #c0ffee, link #bada55;
Note: Sass Lists start at 1, not 0.
$types: text #f00, photo #c69, video #c0ffee, link #bada55; @each $type in $types { .post-type-#{nth($type, 1)} .post-icon{ background: nth($type, 2); } }
.post-type-text .post-icon { background: #f00; } .post-type-photo .post-icon { background: #c69; } .post-type-video .post-icon { background: #c0ffee; } .post-type-link .post-icon { background: #bada55; }
Maps are structured in key: value pairs and accessed with map-get($map-name, key).
$breakpoints: ( small: 767px, medium: 992px, large: 1200px ); .sidebar { width: 30%; @media (max-width: map-get($breakpoints, small)) { width: 100%; } }
.sidebar { width: 30%; } @media (max-width: 767px) { .sidebar { width: 100%; } }
@import 'compass'; $colors: ( tomato rgb(255,99,71) 'rgb(255,99,71)', 'cornflowerblue' rgb(100,149,237) 'rgb(100,149,237)', gold rgb(255,215,0) 'rgb(255,215,0)', hotpink rgb(255,105,180) 'rgb(255,105,180)', ); @each $color in $colors { $var-name: nth($color, 1); $hex: nth($color, 2); $css-name: nth($color, 3); .color-box.#{$var-name} { @include contrasted($hex); &:before { content: '#{$var-name}'; } &:after { content: '#{$css-name}'; } } }
.color-box.tomato { background-color: tomato; color: #000; } .color-box.tomato:before { content: "tomato"; } .color-box.tomato:after { content: "rgb(255,99,71)"; } .color-box.cornflowerblue { background-color: cornflowerblue; color: #000; } .color-box.cornflowerblue:before { content: "cornflowerblue"; } .color-box.cornflowerblue:after { content: "rgb(100,149,237)"; } .color-box.gold { background-color: gold; color: #000; } .color-box.gold:before { content: "gold"; } .color-box.gold:after { content: "rgb(255,215,0)"; } .color-box.hotpink { background-color: hotpink; color: #000; } .color-box.hotpink:before { content: "hotpink"; } .color-box.hotpink:after { content: "rgb(255,105,180)"; }
For loop using through
$columns: 4; @for $i from 1 through $columns { .cols-#{$i} { width: ((100 / $columns) * $i) * 1%; } }
.cols-1 { width: 25%; } .cols-2 { width: 50%; } .cols-3 { width: 75%; } .cols-4 { width: 100%; }
For loop using to
$columns: 4; @for $i from 1 to $columns { .cols-#{$i} { width: ((100 / $columns) * $i) * 1%; } }
.cols-1 { width: 25%; } .cols-2 { width: 50%; } .cols-3 { width: 75%; }
Input:
p { color: #010203 + #040506; }
01 + 04 = 05, 02 + 05 = 07, and 03 + 06 = 09
Computed Value:
p { color: #050709; }
See the Pen Experiments with Sass Color Functions by KatieK (@KatieK2) on CodePen.
See the Pen Dadgumit, Blowouts by KatieK (@KatieK2) on CodePen.
//our map of breakpoints from earlier $breakpoints: ( small: 767px, medium: 992px, large: 1200px ); //mixin using map-get @mixin smaller-than($point-name) { $width: map-get($breakpoints, $point-name); @media (max-width: $width) { @content; } } @mixin larger-than($point-name) { $width: map-get($breakpoints, $point-name); @media (min-width: $width) { @content; } } //usage .heading { font-size: 2em; @include smaller-than(small) { font-size: 1.5em; } @include larger-than(medium) { font-size: 3em; } }
.heading { font-size: 2em; } @media (max-width: 300px) { .heading { font-size: 1.5em; } } @media (min-width: 768px) { .heading { font-size: 3em; } }
Mixins can take values and run logic loops.
See the Pen Sassy Shape Machine Mixin by Una Kravets (@unax3) on CodePen.
Putting it to use.
See the Pen Sassy CSS Puppy by Una Kravets (@unax3) on CodePen.
$__color-palette: ( 'blue': ( core: #4178be, 10: #c0e6ff, 20: #7cc7ff, 30: #5aaafa, 40: #5596e6, 50: #4178be, 60: #325c80, 70: #264a60, 80: #1d3649, 90: #152935, 100: #010205 ), 'green': ( core: #4b8400, 10: #c8f08f, 20: #b4e051, 30: #8cd211, 40: #6eb400, 50: #4b8400, 60: #2d660a, 70: #144d14, 80: #0a3c02, 90: #0c2808, 100: #010200 ), 'teal': ( core: #008571, 10: #a7fae6, 20: #6eedd8, 30: #41d6c3, 40: #00b4a0, 50: #008571, 60: #006d5d, 70: #005448, 80: #003c32, 90: #012b22, 100: #000202 ), 'purple': ( core: #9855d4, 10: #eed2ff, 20: #d7aaff, 30: #ba8ff7, 40: #af6ee8, 50: #9855d4, 60: #734098, 70: #562f72, 80: #412356, 90: #311a41, 100: #030103 ), 'magenta': ( core: #db2780, 10: #ffd2ff, 20: #ff9eee, 30: #ff71d4, 40: #ff3ca0, 50: #db2780, 60: #a6266e, 70: #7c1c58, 80: #601146, 90: #3a0b2e, 100: #040102 ) );
// Import the IBM Color Palette @import '../variables/colors'; ////////////////////////////// // Color Palette // // Gets the specified color from the color palette // // Usage: // // background: color('blue', 80); // #1D3649 // background: color('blue'); // #4178BE ////////////////////////////// @function color($color, $tone: 'core') { // Add a little helper so tone can be passed as single digit number @if type-of($tone) == 'number' { @if $tone % 10 == $tone { $tone: $tone * 10; } } @return map-get(map-get($__color-palette, $color), $tone); }
A better look at functions.scss
// Import the IBM Color Palette @import '../variables/colors'; ////////////////////////////// // Color Palette // // Gets the specified color from the color palette // // Usage: // // background: color('blue', 80); // #1D3649 // background: color('blue'); // #4178BE ////////////////////////////// @function color($color, $tone: 'core') { // Add a little helper so tone can be passed as single digit number @if type-of($tone) == 'number' { @if $tone % 10 == $tone { $tone: $tone * 10; } } @return map-get(map-get($__color-palette, $color), $tone); }
See the Pen Pure CSS 3D animated icosidodecahedron (pentagonal gyrobirotunda) by Ana Tudor (@thebabydino) on CodePen.
See the Pen Cube truncation sequence (pure CSS 3D animation) by Ana Tudor (@thebabydino) on CodePen.