Sass/SCSS Basics

Difficulty: Intermediate

Question

What is Sass/SCSS? What features does it add to CSS?

Answer

Sass (Syntactically Awesome Style Sheets) is a CSS preprocessor that compiles to regular CSS.

SCSS (Sassy CSS) uses CSS-like syntax with braces. Sass uses indentation-based syntax.

Key features: 1. Variables ($color-primary: blue) 2. Nesting (reduces repetition) 3. Mixins (reusable style blocks with parameters) 4. Partials & imports (split CSS into files) 5. Functions (compute values) 6. Extend/inheritance (@extend .base-class) 7. Operators (math in CSS) 8. Control flow (@if, @for, @each)

Note: Modern CSS now has variables, nesting, and :is(). Sass is less essential but still widely used.

Code examples

Variables, Nesting, and Partials

// _variables.scss (partial - starts with _)
$color-primary: #3b82f6;
$color-text: #1f2937;
$radius: 0.5rem;
$shadow: 0 1px 3px rgb(0 0 0 / 0.1);

// _base.scss
@use 'variables' as v;

body {
  color: v.$color-text;
  font-family: 'Inter', sans-serif;
}

// components/_card.scss
@use '../variables' as v;

.card {
  border-radius: v.$radius;
  box-shadow: v.$shadow;

  // Nesting (compiles to .card__title)
  &__title {
    font-size: 1.25rem;
    font-weight: 600;
  }

  &__body {
    padding: 1.5rem;
  }

  // Modifier
  &--featured {
    border: 2px solid v.$color-primary;
  }

  // Pseudo-class nesting
  &:hover {
    box-shadow: 0 4px 12px rgb(0 0 0 / 0.15);
  }
}

Partials (prefixed with _) don't generate separate CSS files. @use replaces @import (which is deprecated). & refers to the parent selector.

Mixins and Functions

// Mixin: reusable block with parameters
@mixin flex-center($direction: row) {
  display: flex;
  flex-direction: $direction;
  justify-content: center;
  align-items: center;
}

.hero {
  @include flex-center(column);
  min-height: 100vh;
}

// Mixin with content block
@mixin responsive($breakpoint) {
  @if $breakpoint == tablet {
    @media (min-width: 768px) { @content; }
  } @else if $breakpoint == desktop {
    @media (min-width: 1024px) { @content; }
  }
}

.grid {
  grid-template-columns: 1fr;

  @include responsive(tablet) {
    grid-template-columns: repeat(2, 1fr);
  }
  @include responsive(desktop) {
    grid-template-columns: repeat(3, 1fr);
  }
}

// Function: returns a value
@function rem($px) {
  @return calc($px / 16) * 1rem;
}
h1 { font-size: rem(32); } // 2rem

Mixins insert blocks of CSS (@include). Functions return values. Mixins with @content act as wrappers - perfect for media queries.

Extend, Loops, and Maps

// @extend: share styles (use sparingly)
%button-base {
  padding: 0.75rem 1.5rem;
  border-radius: 0.375rem;
  font-weight: 500;
  cursor: pointer;
}
.btn-primary {
  @extend %button-base;
  background: #3b82f6;
  color: white;
}
.btn-danger {
  @extend %button-base;
  background: #ef4444;
  color: white;
}
// % = placeholder selector (doesn't output on its own)

// Maps (like JS objects)
$colors: (
  primary: #3b82f6,
  success: #10b981,
  danger: #ef4444,
  warning: #f59e0b,
);

// Loop to generate utility classes
@each $name, $color in $colors {
  .text-#{$name} { color: $color; }
  .bg-#{$name} { background: $color; }
}
// Generates: .text-primary, .bg-primary, etc.

// For loop
@for $i from 1 through 5 {
  .mt-#{$i} { margin-top: $i * 0.25rem; }
}

% placeholder selectors only output when extended. @each loops generate repetitive classes (like Tailwind's utility classes). String interpolation uses #{$var}.

Key points

Concepts covered

Sass, SCSS, Variables, Mixins, Nesting, Partials, Functions