Sass @warn Rule

Beginner
10 min read
Updated: Nov 2026
5 examples
CSS + Warnings

Definition and Usage

When writing mixins and functions, you may want to discourage certain arguments — legacy values, typos you still handle, or suboptimal API use. The Sass @warn rule is built for that. Write @warn <expression>; (usually a string). Sass prints the value plus a stack trace, but does not stop compilation.

Unlike @error, CSS can still be emitted after a warning. Use @debug for temporary value inspection while developing.

Official intent.

Per the Sass docs: guide callers away from deprecated or suboptimal usage without breaking their build.

Not in the CSS file.

Warnings go to the terminal / build log. Browsers never see @warn.

Soft, not fatal.

If continuing would produce broken CSS, use @error instead of @warn.

Syntax

SCSS
@use "sass:list";

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not list.index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  @include prefix(transform, rotate(15deg), wekbit ms);
}

Pattern: check a condition → @warn with a clear message → keep emitting styles (or remap and continue).

vs @error / @debug

Pick the right messaging rule:

RuleStops compile?Best for
@warnNoDeprecations, typos you still handle, soft tips
@errorYesInvalid API use that must not ship CSS
@debugNoTemporary value inspection while developing

SCSS Examples

Every example still produces CSS. Open View Compiled CSS and View Compiler Warning to see both sides of @warn.

Example 1 — Unknown Prefix Tip

Official-style mixin: warn on a typo, but still output the prefix.

SCSS
@use "sass:list";

$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not list.index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  // Oops, we typo'd "webkit" as "wekbit"!
  @include prefix(transform, rotate(15deg), wekbit ms);
}

How It Works

  1. wekbit is not in $known-prefixes.
  2. @warn prints the message and a stack trace.
  3. Compilation continues — CSS still ships.
  4. Output includes the typo prefix plus real transform.

Example 2 — Deprecate & Remap

Warn about a legacy size, then map it to the modern value.

SCSS
@mixin button($size: md) {
  @if $size == xl {
    @warn "The xl size is deprecated. Use lg instead.";
    $size: lg;
  }

  @if $size == sm {
    padding: 0.25rem 0.5rem;
    font-size: 0.875rem;
  } @else if $size == md {
    padding: 0.5rem 1rem;
    font-size: 1rem;
  } @else {
    padding: 0.75rem 1.25rem;
    font-size: 1.125rem;
  }
}

.cta {
  @include button(xl);
}

How It Works

  1. Legacy xl triggers the warning.
  2. Remap to lg so callers keep working.
  3. CSS uses the lg sizes during the migration window.
  4. Message tells callers what to switch to.

Example 3 — Soft Type Fallback

Warn on a bad type, return a safe default, and keep compiling.

SCSS
@use "sass:meta";
@use "sass:math";

@function scale-opacity($value) {
  @if meta.type-of($value) != number {
    @warn "scale-opacity() expected a number; got #{meta.type-of($value)}. Using 1.";
    @return 1;
  }
  @return math.div($value, 100);
}

.card {
  opacity: scale-opacity(80);
}

.broken {
  opacity: scale-opacity("eighty");
}

How It Works

  1. Valid 80 becomes opacity 0.8.
  2. Invalid string warns and falls back to 1.
  3. Both selectors still compile.
  4. For strict public APIs, prefer @error over a default.

Example 4 — Unknown Theme Key

Fall back to primary when a token name is missing.

SCSS
@use "sass:map";

@mixin theme-color($name) {
  $palette: (
    primary: #036,
    accent: #c45,
  );

  @if not map.has-key($palette, $name) {
    @warn "Unknown theme color `#{$name}`. Falling back to primary.";
    $name: primary;
  }

  color: map.get($palette, $name);
}

.text {
  @include theme-color(accent);
}

.miss {
  @include theme-color(neon);
}

How It Works

  1. accent resolves to #c45.
  2. neon is missing, so Sass warns.
  3. Fallback to primary keeps a color on the page.
  4. Build succeeds while the token name gets fixed.

Example 5 — Deprecated Function Alias

Keep an old name working while steering callers to the new one.

SCSS
@function fg($args...) {
  @warn "The fg() function is deprecated. Call foreground() instead.";
  @return foreground($args...);
}

@function foreground($color) {
  @return $color;
}

.title {
  color: fg(#222);
}

How It Works

  1. Old name fg() still works.
  2. $args... forwards every argument.
  3. Warning pushes migration to foreground().
  4. CSS result is unchanged during the rename period.

Edge Cases & Pitfalls

Most @warn mistakes are wrong severity, vague messages, or warning noise.

severity

Do not soft-warn fatal bugs

If CSS would be wrong or unsafe, use @error. Soft warnings hide breakages in CI.

message

Say what to do next

Include the bad value and the preferred alternative: "Use lg instead."

noise

Avoid warning on every call forever

Deprecation windows should end. Remove the alias once callers migrate.

debug

Not a debugger

Temporary value dumps belong in @debug, not long-lived @warn calls.

Sass Support

@warn is a core Sass messaging at-rule. Warning format varies slightly by implementation and build tool; continuing the compile is consistent.

ImplementationStatus
Dart SassSupported (recommended)
LibSass / node-sassSupported (deprecated toolchain)
Ruby SassSupported (end-of-life)
BrowsersN/A — warnings stay in the build log

Prefer Dart Sass for new projects. SCSS and indented syntax both support @warn.

Key Takeaways

  • Soft signal: @warn prints a message + stack and keeps compiling.
  • Guide callers on deprecations, typos, and suboptimal API use.
  • Still emit CSS (or remap) after the warning.
  • Fatal mistakes? Use @error. Inspecting? Use @debug.

One line: @warn is your yellow light for Sass APIs — clear guidance without stopping the build.

Compile Notes

@warn never reaches the browser. Conceptual flow:

flow.txt
1. Call a mixin / function with arguments
2. Hit a soft check (@if + recoverable case)
3. @warn prints message + stack to the build log
4. Continue: remap, fall back, or emit as-is
5. CSS still compiles for the stylesheet

Frequently Asked Questions

It prints the value of an expression (usually a string) plus a stack trace for the user, but unlike @error it does not stop Sass from compiling the stylesheet.
Use it to discourage legacy or suboptimal arguments, flag typos that you still handle, announce deprecations, or guide callers without breaking their build.
@warn continues compilation and still emits CSS. @error aborts the compile. Prefer @error when continuing would produce broken output.
No. Warnings go to the compiler / terminal / build log. The CSS may still include whatever styles your mixin emitted after the warning.
Build tools and Sass CLIs often have quiet or fatal-warning options. Exact flags depend on your Sass version and bundler—check Dart Sass docs for --quiet and related options.
No. Soft warnings are for recoverable cases. If the API cannot continue safely, use @error instead.

Next: Sass @debug Rule

Print values during development without stopping the compile.

Sass @debug Rule →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful