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

Exercises

Six drills to lock in modern SCSS habits — modules, maps, mixins with @content, responsive tokens, and dark-mode-friendly components. Try each in your own scratch file before peeking at the solution.

Six SCSS drills with answers

EXAMPLE
// ============================================================
// Drill 1 — Replace a legacy @import with @use
// ============================================================
// GIVEN:
// @import 'tokens';        // exposes $primary, $radius
// .btn { color: $primary; border-radius: $radius; }
//
// TASK: convert to @use without losing variable access.
//
// SOLUTION:
@use 'tokens';
.btn { color: tokens.$primary; border-radius: tokens.$radius; }
// Or alias:
//   @use 'tokens' as t;  .btn { color: t.$primary; }

// ============================================================
// Drill 2 — A token map you can read deeply
// ============================================================
// TASK: build $tokens with nested colour ramps and a 'token()' function
// SOLUTION:
@use 'sass:map';
$tokens: (
  'color': (
    'brand': (500: #2563eb, 600: #1e40af),
    'gray':  (50: #f8fafc, 900: #0f172a),
  ),
  'space': ('sm': .5rem, 'md': 1rem, 'lg': 2rem),
);
@function token($path...) {
  $v: $tokens;
  @each $k in $path { $v: map.get($v, $k); }
  @if $v == null { @error 'Unknown token: #{$path}'; }
  @return $v;
}
.brand { color: token('color','brand', 500); padding: token('space','md'); }

// ============================================================
// Drill 3 — A mixin that takes a block (@content)
// ============================================================
// TASK: write 'hover-only' that emits the body only on devices that hover.
// SOLUTION:
@mixin hover-only { @media (hover: hover) and (pointer: fine) { &:hover { @content; } } }
.link { @include hover-only { text-decoration: underline; } }

// ============================================================
// Drill 4 — Mobile-first breakpoint mixin 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; } }

// ============================================================
// Drill 5 — Themable component via CSS variables
// ============================================================
// TASK: build .btn whose colour can flip per .theme-dark without recompiling.
// SOLUTION:
: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);
  padding: token('space','sm') token('space','md');
  border-radius: 6px; border: 0;
}

// ============================================================
// Drill 6 — Generate utility classes from a map
// ============================================================
@each $name, $value in map.get($tokens, 'space') {
  .p-#{$name} { padding: $value; }
  .px-#{$name} { padding-inline: $value; }
  .my-#{$name} { margin-block: $value; }
}

// ============================================================
// Scoring
// ============================================================
// 6 / 6 -> can run a codebase migration off @import this afternoon
// 4 / 6 -> bookmark the sass:map docs
// < 4   -> revisit the sass/cheatsheet lesson

Why it matters

Convert your stylesheets off @import as soon as your team can land a single PR doing it. Run `npx sass-migrator module .` and review the diff — most teams cut their stylesheet bundle, fix shadowing bugs, and unlock per-module namespacing in one sitting.

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

Example

Example
// Fill in: @____ button($bg) { background: $bg; }
Try it Yourself »

Discussion

Loading…