Examples
EN

Sass/SCSS

Hwaro compiles SCSS at build time with a built-in, pure-Crystal compiler. There is no dart-sass binary to install, no npm toolchain, and no C library — consistent with Hwaro's zero-external-dependency philosophy.

Quick Start

[sass]
enabled = true

Put SCSS files under static/:

static/
├── css/
│   ├── _variables.scss   # partial — never published
│   ├── _mixins.scss      # partial — never published
│   └── style.scss        # entry — compiles to /css/style.css
// static/css/style.scss
@use "variables";
@use "mixins";

.card {
  color: variables.$primary;
  &:hover { color: variables.$accent; }

  @include mixins.respond(768px) {
    padding: 2rem;
  }
}

Every non-partial *.scss compiles to a sibling .css in the output (static/css/style.scss/css/style.css), so stylesheets keep stable URLs:

<link rel="stylesheet" href="{{ url_for(path="/css/style.css") }}">

Rules

Configuration

Option Type Default Description
enabled bool false Enable SCSS compilation
minify bool true Minify compiled CSS (same minifier as the asset pipeline)

Supported Subset

Hwaro implements a practical SCSS subset — the features hand-written site stylesheets actually use:

Feature Support
$variables ✅ with !default / !global, lexical scoping and shadowing
Nested rules ✅ including selector lists (cartesian combination)
& parent selector &:hover, &.mod, BEM &__elem / &--mod
#{...} interpolation ✅ selectors, property names, values, at-rule preludes, strings, url() — full expressions inside
Partials + @use ✅ namespaces (colors.$primary), as x, as *, load-once, with (...) configuration
@forward show / hide filters, as prefix-*
@import (Sass files) ✅ classic global-merge semantics; plain-CSS forms pass through
@mixin / @include ✅ default values, keyword arguments, variadic $args..., spreads, @content blocks
@function / @return ✅ user functions callable in values, defaults/keywords/variadic, recursion
Control flow @if / @else if / @else, @each (with destructuring), @for (through/to, descending), @while
SassScript expressions ✅ arithmetic (+ - * %), comparisons, and/or/not, strings, lists, maps — see deviations for /
Built-in functions sass:math, sass:string, sass:list, sass:map, sass:meta subset + legacy global names (map-get, nth, if(), …)
@debug / @warn / @error @error fails the build with a located message
@at-root ✅ selector and block forms (no with:/without: queries)
@media / @supports in rules ✅ bubbled out of nesting automatically; feature values evaluate expressions
@keyframes, @font-face, custom properties ✅ pass through correctly
Plain CSS ✅ any valid .css compiles to itself (whitespace-normalized)

Unknown functions (calc(), var(), rgba(), clamp(), color-mix(), …) pass through untouched — arguments still evaluate (translate($x * 2, -50%) works).

@use "sass:math";
$breakpoints: (sm: 640px, md: 768px, lg: 1024px);

@function rem($px, $base: 16px) { @return math.div($px, $base) * 1rem; }

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

@each $name, $bp in $breakpoints {
  .container-#{$name} { max-width: $bp - 24px; }
}
@for $i from 1 through 12 {
  .col-#{$i} { width: math.percentage(math.div($i, 12)); }
}
.hero {
  font-size: rem(28px);
  @include respond(md) { font-size: rem(40px); }
}

Not supported (yet)

@extend, color values and color.* functions, unit conversion (pxcm), @at-root (with: ...) queries, @forward ... with (...), @content(args) / using, math.random / unique-id() (builds must stay deterministic), nested properties (font: { family: ... }), the indented .sass syntax, and source maps.

Unsupported directives fail the build with a located error — Hwaro never emits silently broken CSS:

Error [HWARO_E_CONTENT]: Sass: static/css/style.scss:14:3: @extend is not supported by hwaro's Sass subset (yet)

Expression semantics

The compiler's first duty is the plain-CSS guarantee, so expressions follow a two-tier policy:

Deviations from dart-sass

Errors

Compile failures are classified content errors (exit code 5) with path:line:column locations:

Error [HWARO_E_CONTENT]: Sass: static/css/_mixins.scss:7:12: undefined variable: "$primry"

During hwaro serve, errors show in the browser overlay and the previous output stays on disk.

Interplay with Other Features