1npm i -D node-sass
add a script to package.json
1"start": "node-sass -o css scss"
-o
is for output folder, which in our case is css
.
Partials let you compile multiple files into one and organize your code better.
Partials are created by prepending an underscore to the file name, for example _variables.scss
When importing a partial file into another file, you can just mention the file name, no need to mention the underscore or the file extension. For example
1@import "variables";
The difference between Sass partial imports and normal CSS imports is that Sass partials get combined into one file, meaning only one call to the resource, where as normal CSS imports result in multiple files and multiple resource calls. For example, in your main.scss
you have
1@import "reset";
2@import "variables";
3@import "colors";
4@import "typography";
5@import "layout";
They will all get combined into main.css
and you still get only one file. The resulting file would have the code from all the partial files (instead of just @import statements which call other files).
.
├── css
│ └── main.css
└── scss
├── _colors.scss
├── _layout.scss
├── _reset.scss
├── _typography.scss
├── _variables.scss
└── main.scss
If you were to do it in CSS, you’d have 6 different files total and 6 calls to resources and files will only load one by one.
You can of course do regular css imports in Sass too, if that is what you want.
Order matters when importing files, because cascade!
&
represents the parent selector, i.e. the direct parent. It’s meaning changes based on where it is nested&:hover
and &::before
, they can be nested too&
is great for naming conventions.menu li a
, do .menu-link
You can nest styles. For example
1.menu {
2 background: white;
3
4 a {
5 color: red;
6 font-weight: bold;
7 text-decoration: none;
8
9 &:hover {
10 text-decoration: underline;
11 }
12 }
13}
would compile to
1.menu {
2 background: white; }
3 .menu a {
4 color: red;
5 font-weight: bold;
6 text-decoration: none; }
7 .menu a:hover {
8 text-decoration: underline; }
&
is great for naming conventions. You can do a whole SUIT CSSS or BEM naming like so
1.Tweet {
2 &-header {}
3 &-avatar {}
4 &-bodyText {}
5 &.is-expanded {}
6}
will compile to
1.Tweet {}
2 .Tweet .Tweet-header {}
3 .Tweet .Tweet-avatar {}
4 .Tweet .Tweet-bodyText {}
5 .Tweet.is-expanded {}
$
, first letter after $
can’t be a number{}
is a CSS declaration block)#{$variable}
(interpolation is fancy word for using variables as placeholders - which then get evaluated and replaced with their corresponding values, kinda like template literals in JavaScript). This allows us to re-use verbose text. For example1$wom: women-of-marvel-universe;
2
3.#{$wom} {content: "#{$wom}"}
will compile to
1.women-of-marvel-universe {
2 content: "women-of-marvel-universe"; }
Interpolation also helps with naming conventions
1$wom: women-of-marvel-universe;
2
3.#{$wom} { content: "#{$wom}"; }
4
5.#{$wom}-text { color: #eee; }
6.#{$wom}-cape { background: purple; }
will compile to
1.women-of-marvel-universe {
2 content: "women-of-marvel-universe"; }
3
4.women-of-marvel-universe-text {
5 color: #eee; }
6
7.women-of-marvel-universe-cape {
8 background: purple; }
lighten()
darken()
mix()
mixes two colors. Takes an optional third argument, the percentage of the base color to mix, default is 50%. For example1color: mix($base-color, yellow, 25%)
Here it is going to mix 25%
of $base-color
with yellow
1color: mix(blue, green, 75%) // #006040
complement()
function returns the complimentary color - 180 degrees opposite on the color wheel.1$color1: complement(white); // white
2$color2: complement(black); // black
3$color3: complement(blue); // yellow
4$color4: complement(red); // cyan
5$color5: complement(green); // purple
6$color6: complement(orange); // #005aff
7$color7: complement(magenta); // lime
transparentize()
makes a color more transparent by decreasing the opacity. It’ll take a color and convert it to rgba
with the alpha channel (opacity) adjusted. For example1color: transparentize(mix(blue, yellow, 75%), .2) // rgba(0, 96, 64, 0.8)
scale-color()
fluidly scales one or more properties of a colorMixins are like functions. You can provide arguments, default argument values, use conditionals and more. You define a mixin with @mixin foo
and use that mixin with @include foo
null
as the default argument value. To use optional arguments, you need to use named arguments when including the mixin (named arguments just means that you provide the argument name as well as the value, like $border: 1px solid red
)$transitions...
The elipses ...
means you have a variable number of arguments (kinda like rest parameters in ES6 JavaScript)1$color-brand: #f00;
2
3@mixin box ($background: #eee, $color: $color-brand, $border: null) {
4 width: 100px;
5 padding: 1em;
6 background: $background;
7 color: $color;
8 border: $border;
9}
To use
1.box {
2 @include box($border: 1px solid blue);
3}
will output
1.box {
2 width: 100px;
3 padding: 1em;
4 background: #eee;
5 color: #f00;
6 border: 1px solid blue; }
@content
directive let’s you add custom styles when the mixin is included@extend
let’s you share a set of CSS properties from one slector to another.
@extend
only extends one class, it will not extend the nested classes. It will however extend the pseudo elements (::before
, :hover
etc.) on the class you are extending%
lets you define a placeholder selector for a class@content
directive, extends don’t. For example, mixins allow contents to be passed when included@function
and used like any other sass function foo()
@return
a value 1// Function to detremine typographic scale
2$ratio: 1.2;
3
4@function font-scale ($exponent) {
5 $value: 1;
6
7 @for $i from 1 through $exponent {
8 $value: $value * ratio;
9
10 @debug value is $value; // print out values for each iteration in the console
11 }
12
13 @return $value; // functions must return a value
14}
15
16.stuff { font-size: font-scale(6); } // need to use the function somewhere to see debug in action
DEBUG: value is 1.2
DEBUG: value is 1.44
DEBUG: value is 1.728
DEBUG: value is 2.0736
DEBUG: value is 2.48832
DEBUG: value is 2.98598