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

Examples

A walk through three small SCSS projects — design tokens, a responsive grid, and a themed component library — that together exercise variables, maps, functions, mixins, modules, breakpoints, and dark mode. Copy them as starting points for your own design system.

Tokens, grid, and a themed Button

EXAMPLE
// ============================================================
// 1) _tokens.scss — design tokens as data
// ============================================================
@use 'sass:map';

$tokens: (
  'space': ('xs': .25rem, 'sm': .5rem, 'md': 1rem, 'lg': 2rem, 'xl': 4rem),
  'radius': ('sm': 4px, 'md': 8px, 'lg': 16px, 'pill': 999px),
  'shadow': (
    'sm': 0 1px 2px rgba(0,0,0,.06),
    'md': 0 4px 12px rgba(0,0,0,.10),
    'lg': 0 12px 30px rgba(0,0,0,.18),
  ),
  'color': (
    'brand-500': #2563eb, 'brand-600': #1e40af,
    'gray-50': #f8fafc, 'gray-900': #0f172a,
    'success': #16a34a, 'danger': #dc2626,
  ),
);

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

// ============================================================
// 2) _grid.scss — a 12-column responsive grid mixin
// ============================================================
@use './tokens' as t;
@use 'sass:math';

$breakpoints: ('sm': 480px, 'md': 768px, 'lg': 1024px, 'xl': 1280px);

@mixin respond-to($name) {
  @if not map-has-key($breakpoints, $name) { @error 'unknown bp #{$name}'; }
  @media (min-width: map-get($breakpoints, $name)) { @content; }
}

.grid {
  display: grid;
  gap: t.token('space', 'md');
  grid-template-columns: repeat(12, 1fr);
}

.col-12 { grid-column: span 12; }
@include respond-to('md') {
  .col-md-6 { grid-column: span 6; }
  .col-md-4 { grid-column: span 4; }
}
@include respond-to('lg') {
  .col-lg-3 { grid-column: span 3; }
}

// ============================================================
// 3) _button.scss — themable component using CSS variables
// ============================================================
@use './tokens' as t;

:root {
  --btn-bg:     #{t.token('color','brand-500')};
  --btn-bg-h:   #{t.token('color','brand-600')};
  --btn-fg:     white;
  --btn-radius: #{t.token('radius','md')};
  --btn-px:     #{t.token('space','md')};
  --btn-py:     #{t.token('space','sm')};
}

[data-theme='dark'] {
  --btn-bg:   #{t.token('color','gray-50')};
  --btn-bg-h: #{t.token('color','brand-500')};
  --btn-fg:   #{t.token('color','gray-900')};
}

.btn {
  display: inline-flex; align-items: center; gap: t.token('space','sm');
  padding: var(--btn-py) var(--btn-px);
  border-radius: var(--btn-radius);
  background: var(--btn-bg); color: var(--btn-fg);
  border: 0; cursor: pointer;
  box-shadow: t.token('shadow','sm');
  transition: background .15s ease, box-shadow .15s ease;

  &:hover  { background: var(--btn-bg-h); box-shadow: t.token('shadow','md'); }
  &:focus-visible { outline: 2px solid t.token('color','brand-500'); outline-offset: 2px; }
  &[disabled] { opacity: .5; cursor: not-allowed; }
}

.btn--danger { --btn-bg: #{t.token('color','danger')}; --btn-bg-h: #b91c1c; }
.btn--ghost  { --btn-bg: transparent; --btn-fg: #{t.token('color','brand-500')};
                box-shadow: inset 0 0 0 1px #{t.token('color','brand-500')}; }

Why it matters

Tokens + CSS variables is the combination that scales: SCSS gives you compile-time enforcement and naming, CSS variables give you runtime theming. Hand-edit fewer files for a brand refresh, and let pages flip themes without a bundle reload.

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

Example

Example
// Common patterns — see the lesson body.
$brand: #04AA6D;
Try it Yourself »

Discussion

Loading…