Sass is a CSS extension language that adds features such as variables, nesting, mixins and more. Sass (and other preprocessors, such as Less) help developers write maintainable and DRY (Don’t Repeat Yourself) code.
Sass has two different syntax options to choose from. SCSS, which has the same syntax as CSS but with the added features of Sass. Or Sass (the original syntax), which uses indentation rather than curly braces and semicolons. This tutorial is written using SCSS.
If you’re already familiar with CSS3, you’ll be able to pick up Sass relatively quickly. It does not provide any new styling properties but rather the tools to write your CSS more efficiently and make maintenance much easier.
1//Single line comments are removed when Sass is compiled to CSS.
2
3/* Multi line comments are preserved. */
4
5
6
7/* Variables
8============================== */
9
10
11
12/* You can store a CSS value (such as a color) in a variable.
13Use the '$' symbol to create a variable. */
14
15$primary-color: #A3A4FF;
16$secondary-color: #51527F;
17$body-font: 'Roboto', sans-serif;
18
19/* You can use the variables throughout your stylesheet.
20Now if you want to change a color, you only have to make the change once. */
21
22body {
23 background-color: $primary-color;
24 color: $secondary-color;
25 font-family: $body-font;
26}
27
28/* This would compile to: */
29body {
30 background-color: #A3A4FF;
31 color: #51527F;
32 font-family: 'Roboto', sans-serif;
33}
34
35/* This is much more maintainable than having to change the color
36each time it appears throughout your stylesheet. */
37
38
39
40/* Control Directives
41============================== */
42
43/* Sass lets you use @if, @else, @for, @while, and @each to control the
44 compilation of your code to CSS. */
45
46/* @if/@else blocks behave exactly as you might expect */
47
48$debug: true !default;
49
50@mixin debugmode {
51 @if $debug {
52 @debug "Debug mode enabled";
53
54 display: inline-block;
55 }
56 @else {
57 display: none;
58 }
59}
60
61.info {
62 @include debugmode;
63}
64
65/* If $debug is set to true, .info is displayed; if it's set to false then
66.info is not displayed.
67
68Note: @debug will output debugging information to the command line.
69Useful for checking variables while debugging your SCSS. */
70
71.info {
72 display: inline-block;
73}
74
75/* @for is a control loop that iterates through a range of values.
76Particularly useful for setting styles on a collection of items.
77There are two forms, "through" and "to". The former includes the last value,
78the latter stops at the last value. */
79
80@for $c from 1 to 4 {
81 div:nth-of-type(#{$c}) {
82 left: ($c - 1) * 900 / 3;
83 }
84}
85
86@for $c from 1 through 3 {
87 .myclass-#{$c} {
88 color: rgb($c * 255 / 3, $c * 255 / 3, $c * 255 / 3);
89 }
90}
91
92/* Will compile to: */
93
94div:nth-of-type(1) {
95 left: 0;
96}
97
98div:nth-of-type(2) {
99 left: 300;
100}
101
102div:nth-of-type(3) {
103 left: 600;
104}
105
106.myclass-1 {
107 color: #555555;
108}
109
110.myclass-2 {
111 color: #aaaaaa;
112}
113
114.myclass-3 {
115 color: white;
116// SASS automatically converts #FFFFFF to white
117}
118
119/* @while is very straightforward: */
120
121$columns: 4;
122$column-width: 80px;
123
124@while $columns > 0 {
125 .col-#{$columns} {
126 width: $column-width;
127 left: $column-width * ($columns - 1);
128 }
129
130 $columns: $columns - 1;
131}
132
133/* Will output the following CSS: */
134
135.col-4 {
136 width: 80px;
137 left: 240px;
138}
139
140.col-3 {
141 width: 80px;
142 left: 160px;
143}
144
145.col-2 {
146 width: 80px;
147 left: 80px;
148}
149
150.col-1 {
151 width: 80px;
152 left: 0px;
153}
154
155/* @each functions like @for, except using a list instead of ordinal values
156Note: you specify lists just like other variables, with spaces as
157delimiters. */
158
159$social-links: facebook twitter linkedin reddit;
160
161.social-links {
162 @each $sm in $social-links {
163 .icon-#{$sm} {
164 background-image: url("images/#{$sm}.png");
165 }
166 }
167}
168
169/* Which will output: */
170
171.social-links .icon-facebook {
172 background-image: url("images/facebook.png");
173}
174
175.social-links .icon-twitter {
176 background-image: url("images/twitter.png");
177}
178
179.social-links .icon-linkedin {
180 background-image: url("images/linkedin.png");
181}
182
183.social-links .icon-reddit {
184 background-image: url("images/reddit.png");
185}
186
187
188/* Mixins
189==============================*/
190
191/* If you find you are writing the same code for more than one
192element, you might want to store that code in a mixin.
193
194Use the '@mixin' directive, plus a name for your mixin. */
195
196@mixin center {
197 display: block;
198 margin-left: auto;
199 margin-right: auto;
200 left: 0;
201 right: 0;
202}
203
204/* You can use the mixin with '@include' and the mixin name. */
205
206div {
207 @include center;
208 background-color: $primary-color;
209}
210
211/* Which would compile to: */
212div {
213 display: block;
214 margin-left: auto;
215 margin-right: auto;
216 left: 0;
217 right: 0;
218 background-color: #A3A4FF;
219}
220
221/* You can use mixins to create a shorthand property. */
222
223@mixin size($width, $height) {
224 width: $width;
225 height: $height;
226}
227
228/* Which you can invoke by passing width and height arguments. */
229
230.rectangle {
231 @include size(100px, 60px);
232}
233
234.square {
235 @include size(40px, 40px);
236}
237
238/* Compiles to: */
239.rectangle {
240 width: 100px;
241 height: 60px;
242}
243
244.square {
245 width: 40px;
246 height: 40px;
247}
248
249
250
251/* Functions
252============================== */
253
254
255
256/* Sass provides functions that can be used to accomplish a variety of
257 tasks. Consider the following */
258
259/* Functions can be invoked by using their name and passing in the
260 required arguments */
261body {
262 width: round(10.25px);
263}
264
265.footer {
266 background-color: fade_out(#000000, 0.25);
267}
268
269/* Compiles to: */
270
271body {
272 width: 10px;
273}
274
275.footer {
276 background-color: rgba(0, 0, 0, 0.75);
277}
278
279/* You may also define your own functions. Functions are very similar to
280 mixins. When trying to choose between a function or a mixin, remember
281 that mixins are best for generating CSS while functions are better for
282 logic that might be used throughout your Sass code. The examples in
283 the 'Math Operators' section are ideal candidates for becoming a reusable
284 function. */
285
286/* This function will take a target size and the parent size and calculate
287 and return the percentage */
288
289@function calculate-percentage($target-size, $parent-size) {
290 @return $target-size / $parent-size * 100%;
291}
292
293$main-content: calculate-percentage(600px, 960px);
294
295.main-content {
296 width: $main-content;
297}
298
299.sidebar {
300 width: calculate-percentage(300px, 960px);
301}
302
303/* Compiles to: */
304
305.main-content {
306 width: 62.5%;
307}
308
309.sidebar {
310 width: 31.25%;
311}
312
313
314
315/* Extend (Inheritance)
316============================== */
317
318
319
320/* Extend is a way to share the properties of one selector with another. */
321
322.display {
323 @include size(5em, 5em);
324 border: 5px solid $secondary-color;
325}
326
327.display-success {
328 @extend .display;
329 border-color: #22df56;
330}
331
332/* Compiles to: */
333.display, .display-success {
334 width: 5em;
335 height: 5em;
336 border: 5px solid #51527F;
337}
338
339.display-success {
340 border-color: #22df56;
341}
342
343/* Extending a CSS statement is preferable to creating a mixin
344 because of the way Sass groups together the classes that all share
345 the same base styling. If this was done with a mixin, the width,
346 height, and border would be duplicated for each statement that
347 called the mixin. While it won't affect your workflow, it will
348 add unnecessary bloat to the files created by the Sass compiler. */
349
350
351
352/* Nesting
353============================== */
354
355
356
357/* Sass allows you to nest selectors within selectors */
358
359ul {
360 list-style-type: none;
361 margin-top: 2em;
362
363 li {
364 background-color: #FF0000;
365 }
366}
367
368/* '&' will be replaced by the parent selector. */
369/* You can also nest pseudo-classes. */
370/* Keep in mind that over-nesting will make your code less maintainable.
371Best practices recommend going no more than 3 levels deep when nesting.
372For example: */
373
374ul {
375 list-style-type: none;
376 margin-top: 2em;
377
378 li {
379 background-color: red;
380
381 &:hover {
382 background-color: blue;
383 }
384
385 a {
386 color: white;
387 }
388 }
389}
390
391/* Compiles to: */
392
393ul {
394 list-style-type: none;
395 margin-top: 2em;
396}
397
398ul li {
399 background-color: red;
400}
401
402ul li:hover {
403 background-color: blue;
404}
405
406ul li a {
407 color: white;
408}
409
410
411
412/* Partials and Imports
413============================== */
414
415
416
417/* Sass allows you to create partial files. This can help keep your Sass
418 code modularized. Partial files should begin with an '_', e.g. _reset.css.
419 Partials are not generated into CSS. */
420
421/* Consider the following CSS which we'll put in a file called _reset.css */
422
423html,
424body,
425ul,
426ol {
427 margin: 0;
428 padding: 0;
429}
430
431/* Sass offers @import which can be used to import partials into a file.
432 This differs from the traditional CSS @import statement which makes
433 another HTTP request to fetch the imported file. Sass takes the
434 imported file and combines it with the compiled code. */
435
436@import 'reset';
437
438body {
439 font-size: 16px;
440 font-family: Helvetica, Arial, Sans-serif;
441}
442
443/* Compiles to: */
444
445html, body, ul, ol {
446 margin: 0;
447 padding: 0;
448}
449
450body {
451 font-size: 16px;
452 font-family: Helvetica, Arial, Sans-serif;
453}
454
455
456
457/* Placeholder Selectors
458============================== */
459
460
461
462/* Placeholders are useful when creating a CSS statement to extend. If you
463 wanted to create a CSS statement that was exclusively used with @extend,
464 you can do so using a placeholder. Placeholders begin with a '%' instead
465 of '.' or '#'. Placeholders will not appear in the compiled CSS. */
466
467%content-window {
468 font-size: 14px;
469 padding: 10px;
470 color: #000;
471 border-radius: 4px;
472}
473
474.message-window {
475 @extend %content-window;
476 background-color: #0000ff;
477}
478
479/* Compiles to: */
480
481.message-window {
482 font-size: 14px;
483 padding: 10px;
484 color: #000;
485 border-radius: 4px;
486}
487
488.message-window {
489 background-color: #0000ff;
490}
491
492
493
494/* Math Operations
495============================== */
496
497
498
499/* Sass provides the following operators: +, -, *, /, and %. These can
500 be useful for calculating values directly in your Sass files instead
501 of using values that you've already calculated by hand. Below is an example
502 of a setting up a simple two column design. */
503
504$content-area: 960px;
505$main-content: 600px;
506$sidebar-content: 300px;
507
508$main-size: $main-content / $content-area * 100%;
509$sidebar-size: $sidebar-content / $content-area * 100%;
510$gutter: 100% - ($main-size + $sidebar-size);
511
512body {
513 width: 100%;
514}
515
516.main-content {
517 width: $main-size;
518}
519
520.sidebar {
521 width: $sidebar-size;
522}
523
524.gutter {
525 width: $gutter;
526}
527
528/* Compiles to: */
529
530body {
531 width: 100%;
532}
533
534.main-content {
535 width: 62.5%;
536}
537
538.sidebar {
539 width: 31.25%;
540}
541
542.gutter {
543 width: 6.25%;
544}
SASS or Sass? ¶
Have you ever wondered whether Sass is an acronym or not? You probably haven’t, but I’ll tell you anyway. The name of the language is a word, «Sass», and not an acronym. Because people were constantly writing it as «SASS», the creator of the language jokingly called it «Syntactically Awesome StyleSheets».
Practice Sass ¶
If you want to play with Sass in your browser, check out SassMeister. You can use either syntax, just go into the settings and select either Sass or SCSS.
Compatibility ¶
Sass can be used in any project as long as you have a program to compile it into CSS. You’ll want to verify that the CSS you’re using is compatible with your target browsers.
QuirksMode CSS and CanIUse are great resources for checking compatibility.
Further reading ¶
- Official Documentation
- The Sass Way provides tutorials (beginner-advanced) and articles.