iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up
Next »

Summary

A one-screen summary of modern SCSS: the module system, design tokens as data, mixins with @content, breakpoints, and the lint rules that keep the codebase consistent. Use it to onboard a new developer or audit a stylesheet during a code review.

SCSS in one screen

EXAMPLE
// ===== 1) Modules (@use / @forward) replace @import =====
@use 'tokens' as t;            // namespaced as t.$primary
@use 'tokens' as *;            // (rare) no namespace
@forward 'colors';             // re-export

.btn { color: t.$primary; }

// ===== 2) Tokens as data — design system in one map =====
@use 'sass:map';

$tokens: (
  'color':  ('brand': (500: #2563eb, 600: #1e40af),
             'gray':  (50: #f8fafc, 900: #0f172a)),
  'space':  ('xs': .25rem, 'sm': .5rem, 'md': 1rem, 'lg': 2rem),
  'radius': ('sm': 4px, 'md': 8px, 'pill': 999px),
);

@function token($path...) {
  $v: $tokens;
  @each $k in $path { $v: map.get($v, $k); }
  @if $v == null { @error 'Unknown token: #{$path}'; }
  @return $v;
}

// ===== 3) Mixins with @content and arguments =====
@mixin hover-only { @media (hover: hover) and (pointer: fine) { &:hover { @content; } } }
@mixin shadow($level: 'sm') { box-shadow: token('shadow', $level); }

.link { @include hover-only { text-decoration: underline; } }

// ===== 4) Breakpoints from a map =====
$bp: ('sm': 480px, 'md': 768px, 'lg': 1024px, 'xl': 1280px);
@mixin respond-to($name) {
  @if not map.has-key($bp, $name) { @error 'Unknown bp #{$name}'; }
  @media (min-width: map.get($bp, $name)) { @content; }
}
.card {
  padding: 1rem;
  @include respond-to('md') { padding: 1.5rem; }
}

// ===== 5) Math.div replaces / =====
@use 'sass:math';
$col: math.div(100%, 12);     // 8.333%

// ===== 6) Loops generate utility classes =====
@each $name, $value in map.get($tokens, 'space') {
  .p-#{$name} { padding: $value; }
  .m-#{$name} { margin: $value; }
}

// ===== 7) Theming via CSS variables =====
:root { --btn-bg: #{token('color', 'brand', 500)}; --btn-fg: white; }
.theme-dark { --btn-bg: #{token('color', 'gray', 50)}; --btn-fg: #{token('color', 'gray', 900)}; }
.btn { background: var(--btn-bg); color: var(--btn-fg); }

// ===== 8) Placeholder selectors (%) for shared base styles =====
%card-base { padding: 1rem; border-radius: token('radius', 'md'); }
.callout, .alert { @extend %card-base; }

// ===== 9) Color functions live in 'sass:color' =====
@use 'sass:color';
.btn:hover { background: color.adjust(token('color','brand',500), $lightness: -8%); }

// ===== 10) Lint with Stylelint =====
// .stylelintrc.json
// {
//   "extends": ["stylelint-config-standard-scss", "stylelint-config-recess-order"],
//   "rules": {
//     "at-rule-disallowed-list": ["import"],   // ban legacy @import
//     "color-no-hex": [true, { "message": "Use token() instead of literal hex." }],
//     "scss/dollar-variable-pattern": "^[a-z][a-zA-Z0-9]+$"
//   }
// }

// ===== 11) Decision matrix =====
// - One-off value?           -> arbitrary literal (only here)
// - Used 2+ times?            -> add to a map and reference via token()
// - Component-specific tweak? -> a class with composed utilities
// - Brand-wide change?        -> update the token; the system propagates

// ===== 12) Pitfalls =====
// - Mixing @import and @use (compile errors)
// - Editing token values without bumping the visual regression tests
// - Long property: value chains that are easier as a mixin (e.g. flex centering)
// - 'darken' / 'lighten' deprecation -> use color.adjust

Why it matters

Tokens as data + CSS variables is the combination that scales. SCSS validates names at compile time; CSS variables let theming flip at runtime. A new dark mode, a brand refresh, or a per-tenant palette all become single-file edits instead of project-wide find-and-replace.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Next: modern Sass modules, CSS custom properties together, design-token pipelines.
Try it Yourself »

Discussion

Loading…

Next »