SCSS in a Nutshell2015/07/20
The complete Sass/SCSS reference is located here.
Installation
Install Sass using Ruby
gem install sass
Have Sass watch over a file, and specify the output destination
sass --watch main.scss:main.css
You will almost never use this command. Instead we use Grunt to handle this.
Install Sass syntax highlighting in Sublime Text via Package Control https://packagecontrol.io/packages/Syntax%20Highlighting%20for%20Sass
- Enable Package Control
- Open the Sublime Text console.
ctrl+`
ORView > Show Console
- Run the Python code found at https://packagecontrol.io/installation
- Open the Sublime Text console.
- Install the Syntax Highlighting for Sass package
- Open the Command Pallete.
ctrl+shift+p
(Win/Linux) ORcmd+shift+p
(OSX) - Select Package Control: Install Package (and wait a bit)
- Select Syntax Highlighting for Sass
- Open the Command Pallete.
Partials
All .scss
files are compiled into their respective .css
file. Partials which are prefixed with an underscore will not generate their own .css
file. They exist for inclusion from other files.
// _partial.scss
@import 'partial'; // underscore and extension omitted
CSS Compliant
All CSS rules and syntax work in Sass. CSS in a Nutshell: /css-in-a-nutshell
Nesting
Selectors can be nested within others and are equivalent to CSS’s space separated selectors.
ul {
list-style-type: none;
li { // equivalent to the selector 'ul li'
display: block;
}
}
Parent Selector
The &
character represents the current parent selector and allows selectors to be made relative to it.
.button {
background-color: blue;
&:hover { // .button:hover
background-color: red;
}
footer & { // footer .button
background-color: green;
}
&-black { // .button-black
background-color: black;
}
}
Nested Properties
Certain properties can also be nested.
blockquote {
font: {
family: "Times New Roman", serif; // font-family
style: italics; // font-style
size: 2rem; // font-size
}
}
Extend/Inheritance
Selectors can inherit from other selectors using @extend
. If the !optional
tag is included, @extend
will be ignored if it were to cause an error (e.g. the selector doesn't exist or is conflictory). The %
selector is similar to .
/#
for classes/id's, but exists for the purpose of inheritance and won't be rendered into the output css.
p%awesome { // This ruleset won't be rendered explicitly
font-weight: bold;
}
.message {
border: 1px solid #CCCCCC;
color: #333333;
}
.message-success {
@extend .message;
border-color: green;
p {
@extend %awesome; // @extend successfully runs
@extend .something !optional; // .something doesn't exist; @extend is ignored.
}
a {
@extend %awesome !optional;
// %awesome is defined only for p
// @extend is ignored.
}
}
Variables
Variables’ scopes are within the level of selectors they are defined in, unless given the !global
flag. The !default
flag will set the variable if it isn't already defined.
$size: 15px;
$size: 30px !default; // $size is still 15px
html {
$color: #335544 !global;
background-color: $color;
}
div {
background-color: white;
color: $color;
}
Allowed variable types:
- Numbers:
1.2
,13
,10px
- Strings:
"foo"
,'bar'
,baz
- Colors:
blue
,#04A3F9
,rgba(255, 0, 0, .5)
- Booleans:
true
,false
- Nulls:
null
- Lists (space or comma separated):
1.5em 0 2em
,Helvetica, Arial, san-serif
- Maps:
(key1: value1, key2: value2)
Interpolation
Interpolation is mainly for using variables in selectors or strings.
$name: foo;
$attr: border;
p.#{$name} { // p.foo
#{$attr}-color: blue; // border-color
}
$text: "#{$name}#{$attr}"; // "fooborder"
Operations
Take care that agreeable units are in the arguments.
Numbers and Colors: +
-
*
/
%
<
>
<=
>=
==
!=
80px / 320px * 100% == 25%
#010203 + #040506 == #050709 // computed piecewise
16px + 1em // Invalid operation
10px * 10px == 100px*px // Note px*px is not a CSS unit
Strings: +
==
!=
"Foo " + Bar == "Foo Bar"
sans + -serif == sans-serif
Booleans: and
or
not
==
!=
Mixins
Mixins are reusable groups of CSS declarations which allow variable parameters. (Also accepts the parameters as lists and maps).
@mixin border($width, $style, $color, $radius: 0px) {
// $radius uses default value of 0px if not passed
border: {
color: $color;
style: $style;
width: $width;
}
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
-ms-border-radius: $radius;
border-radius: $radius;
}
}
@mixin box-shadow($shadows...) { // supports var-args
-webkit-box-shadow: $shadows;
-moz-box-shadow: $shadows;
box-shadow: $shadows;
}
.box {
@include border(1px, solid, blue);
@include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}
.circle {
@include border(
$width: 5px,
$color: green,
$style: dashed,
$radius: 50%
);
// keyword arguments
}
Mixins using a Content Block
@mixin apply-to-main {
#main {
@content;
}
}
@include apply-to-main {
background-color: blue; // #main
#logo { // #main #logo
background-image: url(/logo.gif);
}
}
Functions
Functions supports var-args and keyword arguments similar to mixins. For the list of built-in Sass functions: http://sass-lang.com/documentation/Sass/Script/Functions.html
$grid-width: 40px;
$gutter-width: 10px;
@function grid-width($n) {
@return $n * $grid-width + ($n - 1) * $gutter-width;
}
#sidebar {
width: grid-width(5); // 240px
}
Control Directives
All values are "truthy" except for false
and null
.
The @if
, @else if
, and @else
directives:
p {
@if 1 + 1 == 2 { border: 1px solid; } // true
@if "cheese" { border: 2px solid; } // true
@if 5 < 3 { border: 2px dotted; } // false
@if null { border: 3px double; } // false
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else {
color: black;
}
}
The @for
directive loops (incrementally or decrementally) a variable through a range of integers.
@for $i from 1 through 3 {
.size-#{$i} { width: 2em * $i; }
}
The @each
directive loops through lists or maps. Also supports multiple assignment.
@each $animal in puma, sea-slug, egret, salamander {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
}
}
@each $animal, $color, $cursor in (puma, black, default),
(sea-slug, blue, pointer),
(egret, white, move) {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
border: 2px solid $color;
cursor: $cursor;
}
}
The @while
directive loops while a condition is true.
$i: 6;
@while $i > 0 {
.item-#{$i} { width: 2em * $i; }
$i: $i - 2;
}