Introduction to Sass
Sass (Syntactically Awesome Style Sheets) is a CSS preprocessor that extends CSS with features like variables, nesting, mixins, and functions. It makes CSS more maintainable, reusable, and powerful.
What is Sass?
Sass is a preprocessor that compiles to CSS. It adds powerful features to CSS while maintaining backward compatibility. There are two syntaxes: SCSS (Sassy CSS) and Sass (indented syntax).
SCSS vs Sass
// SCSS (recommended)
.container {
width: 100%;
.item {
color: red;
}
}
// Sass (indented)
.container
width: 100%
.item
color: red
Installation and Setup
Using npm
npm install -g sass
Using Ruby (if you have Ruby installed)
gem install sass
Compilation
# Watch a file
sass --watch input.scss output.css
# Watch a directory
sass --watch src/sass:dist/css
Variables
Variables store reusable values like colors, fonts, and sizes.
// Variables
$primary-color: #007bff;
$font-stack: 'Helvetica Neue', Helvetica, Arial, sans-serif;
$border-radius: 4px;
// Usage
.button {
background-color: $primary-color;
font-family: $font-stack;
border-radius: $border-radius;
}
Variable Scope
$global-var: global;
.container {
$local-var: local; // Only available in this scope
color: $global-var; // Works
background: $local-var; // Works
}
.outside {
color: $global-var; // Works
background: $local-var; // Error: undefined
}
Default Values
$font-size: 16px !default;
.button {
font-size: $font-size;
}
Nesting
Nesting allows you to write CSS that mirrors your HTML structure.
.nav {
background: #333;
ul {
list-style: none;
margin: 0;
padding: 0;
li {
display: inline-block;
a {
color: white;
text-decoration: none;
padding: 10px;
&:hover {
background: #555;
}
}
}
}
}
Compiles to:
.nav {
background: #333;
}
.nav ul {
list-style: none;
margin: 0;
padding: 0;
}
.nav ul li {
display: inline-block;
}
.nav ul li a {
color: white;
text-decoration: none;
padding: 10px;
}
.nav ul li a:hover {
background: #555;
}
Partials and Imports
Partials are Sass files that contain reusable code snippets.
// _variables.scss
$primary: #007bff;
$secondary: #6c757d;
// _mixins.scss
@mixin button($color) {
background: $color;
border: 1px solid darken($color, 10%);
border-radius: 4px;
padding: 10px 20px;
}
// main.scss
@import 'variables';
@import 'mixins';
.button-primary {
@include button($primary);
}
.button-secondary {
@include button($secondary);
}
Mixins
Mixins are reusable blocks of CSS that can accept parameters.
// Basic mixin
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
border-radius: $radius;
}
.box {
@include border-radius(10px);
}
// Mixin with default values
@mixin box-shadow($x: 0, $y: 2px, $blur: 4px, $color: rgba(0,0,0,0.1)) {
-webkit-box-shadow: $x $y $blur $color;
-moz-box-shadow: $x $y $blur $color;
box-shadow: $x $y $blur $color;
}
.card {
@include box-shadow(0, 4px, 8px, rgba(0,0,0,0.2));
}
// Content blocks
@mixin media-query($breakpoint) {
@if $breakpoint == tablet {
@media (min-width: 768px) { @content; }
} @else if $breakpoint == desktop {
@media (min-width: 1024px) { @content; }
}
}
.container {
width: 100%;
@include media-query(tablet) {
width: 750px;
}
@include media-query(desktop) {
width: 970px;
}
}
Functions
Functions perform calculations and return values.
// Built-in functions
$width: 100px;
$double: $width * 2; // 200px
// Custom functions
@function calculate-rem($size) {
$rem-size: $size / 16px;
@return #{$rem-size}rem;
}
.heading {
font-size: calculate-rem(32px); // 2rem
}
// Color functions
$color: #007bff;
.darker {
background: darken($color, 10%);
}
.lighter {
background: lighten($color, 10%);
}
.saturated {
background: saturate($color, 20%);
}
Inheritance
Extend existing selectors with additional properties.
// Placeholder selector
%button-base {
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.button-primary {
@extend %button-base;
background: #007bff;
color: white;
}
.button-secondary {
@extend %button-base;
background: #6c757d;
color: white;
}
Control Directives
@if / @else
@mixin button-variant($color, $background) {
color: $color;
background: $background;
@if lightness($background) < 50% {
border-color: lighten($background, 20%);
} @else {
border-color: darken($background, 20%);
}
}
@for
@for $i from 1 through 3 {
.col-#{$i} {
width: 100% / $i;
}
}
@each
$colors: (primary: #007bff, secondary: #6c757d, success: #28a745);
@each $name, $color in $colors {
.text-#{$name} {
color: $color;
}
}
@while
$i: 1;
@while $i <= 3 {
.item-#{$i} {
width: 100px * $i;
}
$i: $i + 1;
}
Maps
Maps are key-value data structures.
$breakpoints: (
small: 576px,
medium: 768px,
large: 992px,
extra-large: 1200px
);
@mixin media-query($size) {
@if map-has-key($breakpoints, $size) {
@media (min-width: map-get($breakpoints, $size)) {
@content;
}
}
}
.container {
width: 100%;
@include media-query(medium) {
width: 750px;
}
}
Best Practices
File Organization
sass/
├── base/
│ ├── _reset.scss
│ ├── _typography.scss
│ └── _colors.scss
├── components/
│ ├── _buttons.scss
│ ├── _cards.scss
│ └── _forms.scss
├── layout/
│ ├── _header.scss
│ ├── _footer.scss
│ └── _sidebar.scss
├── pages/
│ ├── _home.scss
│ └── _about.scss
├── utils/
│ ├── _variables.scss
│ ├── _functions.scss
│ └── _mixins.scss
└── main.scss
Naming Conventions
- Use hyphens for variable names:
$primary-color - Use descriptive names:
$button-paddinginstead of$bp - Follow BEM methodology for classes
Performance
- Avoid deeply nested selectors
- Use
&for pseudo-classes and modifiers - Minimize the use of
@extend(can bloat CSS) - Use placeholders for extends when possible
Integration with Build Tools
Webpack
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
}
};
Gulp
const gulp = require('gulp');
const sass = require('gulp-sass');
gulp.task('sass', function() {
return gulp.src('src/scss/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('dist/css'));
});
Debugging
Source Maps
Enable source maps for easier debugging:
sass --watch --source-map src/scss:dist/css
Sass Error Messages
Sass provides detailed error messages with file names and line numbers.
Migration from CSS
Start small by converting existing CSS files to SCSS:
- Rename
.cssfiles to.scss - Add variables for repeated values
- Use nesting for related selectors
- Create mixins for repeated patterns
- Split into partials for organization
Sass enhances CSS with powerful features while maintaining the familiarity of CSS syntax. It helps create more maintainable, scalable, and efficient stylesheets.
