SCSS Error Handling and Debugging (@debug, @warn, @error)
1. @debug Directive for Development Logging
| Directive | Syntax | Output | Use Case |
|---|---|---|---|
| @debug | @debug $value; |
Prints to stderr | Development logging |
| Multiple Values | @debug $var1, $var2; |
Comma-separated output | Compare values |
| Expressions | @debug 10px + 5px; |
Evaluated result | Test calculations |
| Type Inspection | @debug type-of($var); |
Data type | Type checking |
| Map Inspection | @debug map-keys($map); |
Map structure | Debug data structures |
Example: Basic debugging with @debug
// Simple value debugging
$primary-color: #1976d2;
@debug $primary-color;
// Output: styles.scss:2 DEBUG: #1976d2
// Multiple values
$width: 300px;
$height: 200px;
@debug "Width:", $width, "Height:", $height;
// Output: styles.scss:5 DEBUG: "Width:", 300px, "Height:", 200px
// Expression debugging
@debug 100px / 16px;
// Output: styles.scss:7 DEBUG: 6.25
// Type checking
$value: "hello";
@debug type-of($value);
// Output: styles.scss:9 DEBUG: string
// Map debugging
$theme: (
primary: #1976d2,
secondary: #dc004e
);
@debug map-keys($theme);
// Output: styles.scss:13 DEBUG: primary, secondary
@debug map-get($theme, primary);
// Output: styles.scss:15 DEBUG: #1976d2
Example: Advanced debugging techniques
@use 'sass:meta';
@use 'sass:map';
// Debug function for formatted output
@mixin debug-info($label, $value) {
@debug "=== #{$label} ===";
@debug " Type: #{meta.type-of($value)}";
@debug " Value: #{$value}";
@if meta.type-of($value) == 'map' {
@debug " Keys: #{map.keys($value)}";
@debug " Values: #{map.values($value)}";
} @else if meta.type-of($value) == 'list' {
@debug " Length: #{length($value)}";
@debug " Items: #{$value}";
}
}
// Usage
$colors: (
primary: #1976d2,
secondary: #dc004e,
success: #4caf50
);
@include debug-info('Theme Colors', $colors);
// Output:
// === Theme Colors ===
// Type: map
// Value: (primary: #1976d2, secondary: #dc004e, success: #4caf50)
// Keys: primary, secondary, success
// Values: #1976d2, #dc004e, #4caf50
// Conditional debugging
$debug-mode: true;
@mixin debug($message) {
@if $debug-mode {
@debug $message;
}
}
// Function debugging
@function calculate-rem($px) {
@debug "Converting: #{$px}px to rem";
$rem: $px / 16;
@debug "Result: #{$rem}rem";
@return $rem * 1rem;
}
$font-size: calculate-rem(18);
// Output:
// Converting: 18px to rem
// Result: 1.125rem
Example: Debug breakpoint in compilation
// Debug during loop iterations
$breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
);
@each $name, $size in $breakpoints {
@debug "Processing breakpoint: #{$name} = #{$size}";
@media (min-width: $size) {
.container-#{$name} {
@debug " Creating .container-#{$name}";
max-width: $size;
}
}
}
// Debug color transformations
@function debug-color-transform($color, $operation, $amount) {
@debug "Original color: #{$color}";
$result: null;
@if $operation == 'lighten' {
$result: lighten($color, $amount);
} @else if $operation == 'darken' {
$result: darken($color, $amount);
}
@debug "After #{$operation}(#{$amount}): #{$result}";
@return $result;
}
$base: #1976d2;
$lighter: debug-color-transform($base, 'lighten', 20%);
// Output:
// Original color: #1976d2
// After lighten(20%): #64b5f6
2. @warn Directive for Deprecation Warnings
| Directive | Behavior | Use Case | Impact |
|---|---|---|---|
| @warn | Prints warning, continues compilation | Deprecation notices | Non-fatal alerts |
| Stack Trace | Shows file and line number | Track warning source | Easy debugging |
| Conditional Warnings | Warn based on conditions | Value validation | Better error messages |
| --quiet | Suppress warnings with flag | Production builds | Clean output |
Example: Deprecation warnings
// Deprecation warning for old API
@mixin old-button($color) {
@warn "The old-button mixin is deprecated. Use new-button instead.";
background: $color;
padding: 10px 20px;
}
// Better deprecation with migration path
@mixin legacy-grid($cols: 12) {
@warn "legacy-grid is deprecated since v2.0. " +
"Use CSS Grid with grid-template-columns instead. " +
"See: https://docs.example.com/migration";
width: 100% / $cols;
float: left;
}
// Warn about parameter changes
@mixin button($bg-color, $text-color: null) {
@if $text-color == null {
@warn "The text-color parameter will become required in v3.0. " +
"Please provide an explicit text color.";
$text-color: white; // Fallback
}
background: $bg-color;
color: $text-color;
}
// Usage triggers warning:
.my-button {
@include button(#1976d2);
// Warning: The text-color parameter will become required in v3.0...
}
Example: Value validation warnings
@use 'sass:math';
@use 'sass:meta';
// Warn about invalid values
@function safe-divide($a, $b) {
@if $b == 0 {
@warn "Division by zero! Returning 0 instead.";
@return 0;
}
@return math.div($a, $b);
}
// Warn about type mismatches
@mixin font-size($size) {
@if meta.type-of($size) != 'number' {
@warn "font-size expects a number, got #{meta.type-of($size)}: #{$size}";
@return;
}
@if not math.is-unitless($size) and math.unit($size) != 'px' and math.unit($size) != 'rem' {
@warn "font-size expects px or rem units, got: #{math.unit($size)}";
}
font-size: $size;
}
// Warn about out-of-range values
@mixin opacity($value) {
@if $value < 0 or $value > 1 {
@warn "Opacity should be between 0 and 1, got: #{$value}. Clamping value.";
$value: math.clamp(0, $value, 1);
}
opacity: $value;
}
// Warn about browser compatibility
@mixin backdrop-filter($value) {
@warn "backdrop-filter has limited browser support. " +
"Consider providing a fallback background color.";
backdrop-filter: $value;
-webkit-backdrop-filter: $value;
}
// Warn about performance concerns
@mixin deep-nesting-check($level) {
@if $level > 3 {
@warn "Nesting level #{$level} detected. " +
"Deep nesting (>3 levels) can hurt performance and specificity.";
}
}
Example: Configuration and environment warnings
// Warn about missing configuration
$config: () !default;
@function get-config($key) {
@if not map-has-key($config, $key) {
@warn "Configuration key '#{$key}' not found. Using default value.";
@return null;
}
@return map-get($config, $key);
}
// Warn about conflicting settings
$use-flexbox: true !default;
$use-float: true !default;
@if $use-flexbox and $use-float {
@warn "Both flexbox and float layout systems are enabled. " +
"This may cause conflicts. Disable one in your configuration.";
}
// Environment-specific warnings
$environment: 'development' !default;
@if $environment == 'production' {
@if $debug-mode == true {
@warn "Debug mode is enabled in production environment! " +
"Set $debug-mode: false for production.";
}
}
// Warn about large file sizes
@mixin check-utility-classes($count) {
@if $count > 100 {
@warn "Generating #{$count} utility classes. " +
"Consider using a utility framework or PurgeCSS to reduce CSS size.";
}
}
3. @error Directive for Custom Error Messages
| Directive | Behavior | Use Case | Impact |
|---|---|---|---|
| @error | Stops compilation immediately | Critical validation failures | Prevents broken output |
| Required Parameters | Validate required arguments | Function/mixin safety | Better API contracts |
| Type Validation | Ensure correct data types | Type safety | Catch bugs early |
| Range Validation | Check value boundaries | Prevent invalid CSS | Guaranteed valid output |
Example: Parameter validation with @error
@use 'sass:meta';
@use 'sass:list';
// Validate required parameters
@function calculate-spacing($multiplier) {
@if $multiplier == null {
@error "calculate-spacing() requires a $multiplier parameter.";
}
@return $multiplier * 8px;
}
// Type validation
@mixin text-color($color) {
@if meta.type-of($color) != 'color' {
@error "text-color() expects a color, got #{meta.type-of($color)}: #{$color}";
}
color: $color;
}
// Multiple allowed types
@function parse-size($value) {
$type: meta.type-of($value);
@if $type != 'number' and $type != 'string' {
@error "parse-size() expects number or string, got #{$type}: #{$value}";
}
@return $value;
}
// Enum-like validation
@mixin text-align($align) {
$valid-values: ('left', 'center', 'right', 'justify');
@if not list.index($valid-values, $align) {
@error "text-align() expects one of #{$valid-values}, got: #{$align}";
}
text-align: $align;
}
// Usage that triggers error:
.element {
@include text-align('middle'); // ❌ Error!
// Error: text-align() expects one of ("left", "center", "right", "justify"), got: "middle"
}
Example: Range and value validation
@use 'sass:math';
// Range validation
@function clamp-opacity($value) {
@if meta.type-of($value) != 'number' {
@error "Opacity must be a number, got: #{$value}";
}
@if $value < 0 or $value > 1 {
@error "Opacity must be between 0 and 1, got: #{$value}";
}
@return $value;
}
// Unit validation
@function validate-spacing($value) {
@if not math.is-unitless($value) {
$unit: math.unit($value);
$valid-units: ('px', 'rem', 'em', '%');
@if not index($valid-units, $unit) {
@error "Spacing must use px, rem, em, or %, got: #{$unit}";
}
}
@return $value;
}
// Positive number validation
@function positive-number($value, $name: 'value') {
@if meta.type-of($value) != 'number' {
@error "#{$name} must be a number, got: #{meta.type-of($value)}";
}
@if $value <= 0 {
@error "#{$name} must be positive, got: #{$value}";
}
@return $value;
}
// Grid columns validation
@mixin grid-columns($count) {
@if $count < 1 or $count > 12 {
@error "Grid columns must be between 1 and 12, got: #{$count}";
}
@if $count != math.round($count) {
@error "Grid columns must be an integer, got: #{$count}";
}
grid-template-columns: repeat($count, 1fr);
}
Example: Configuration and dependency validation
@use 'sass:map';
// Validate required configuration
$theme-config: () !default;
@function require-config($key) {
@if not map.has-key($theme-config, $key) {
@error "Missing required configuration: '#{$key}'. " +
"Please define $theme-config: (#{$key}: ...) before importing.";
}
@return map.get($theme-config, $key);
}
// Validate map structure
@function validate-theme($theme) {
$required-keys: ('primary', 'secondary', 'background', 'text');
@each $key in $required-keys {
@if not map.has-key($theme, $key) {
@error "Theme missing required key: '#{$key}'. " +
"Required keys: #{$required-keys}";
}
}
@return $theme;
}
// Validate version compatibility
$sass-version: '1.69.0' !default;
@function check-version($min-version) {
// Simple version check (in real code, parse properly)
@if $sass-version < $min-version {
@error "This library requires Sass #{$min-version} or higher. " +
"You are using Sass #{$sass-version}. Please upgrade.";
}
@return true;
}
// Validate mutual exclusivity
@mixin validate-layout-mode($mode) {
$valid-modes: ('flex', 'grid', 'float');
@if not index($valid-modes, $mode) {
@error "Invalid layout mode: '#{$mode}'. " +
"Must be one of: #{$valid-modes}";
}
}
// Check for circular dependencies
$_importing: () !global;
@mixin check-circular-import($module-name) {
@if index($_importing, $module-name) {
@error "Circular import detected: #{$module-name} is already being imported. " +
"Import stack: #{$_importing}";
}
$_importing: append($_importing, $module-name) !global;
}
4. Stack Trace Reading and Error Resolution
| Stack Trace Part | Information | How to Read | Action |
|---|---|---|---|
| Error Message | What went wrong | First line of output | Understand the problem |
| File Path | Where error occurred | filename.scss:line:column |
Navigate to file |
| Backtrace | Call chain | Indented list of calls | Trace execution path |
| Source Excerpt | Code context | Lines around error | See actual code |
| Caret (^) | Exact error position | Points to character | Pinpoint issue |
Example: Reading a typical Sass error
// Error output example:
Error: Undefined variable.
╷
3 │ color: $primry-color; // Typo!
│ ^^^^^^^^^^^^^
╵
styles.scss 3:10 root stylesheet
// Breaking it down:
// 1. "Undefined variable" - The problem
// 2. Line 3, Column 10 - Exact location
// 3. The caret points to the typo: $primry-color
// 4. Should be: $primary-color
// Resolution:
.button {
color: $primary-color; // Fixed!
}
Example: Understanding nested stack traces
// Complex error with multiple levels
Error: $color: transparant is not a color.
╷
8 │ background: mix(white, $color, 20%);
│ ^^^^^^^^^^^^^^^^^^^^^^^
╵
_functions.scss 8:15 lighten-color()
_theme.scss 15:12 create-theme()
main.scss 23:3 root stylesheet
// Reading the stack trace (bottom to top):
// 1. main.scss:23 - Called create-theme()
// 2. _theme.scss:15 - create-theme() called lighten-color()
// 3. _functions.scss:8 - lighten-color() tried to mix colors
// 4. Error: 'transparant' is not a color (typo: should be 'transparent')
// Trace the error path:
// main.scss
@use 'theme';
$my-theme: create-theme('transparant'); // ❌ Typo here!
// _theme.scss
@use 'functions';
@function create-theme($bg) {
@return lighten-color($bg); // Passes typo to next function
}
// _functions.scss
@function lighten-color($color) {
@return mix(white, $color, 20%); // ❌ Fails here because $color is invalid
}
// Resolution:
$my-theme: create-theme('transparent'); // ✅ Fixed!
Example: Common error patterns and solutions
// 1. Undefined Variable
// Error: Undefined variable.
$primary: #1976d2;
.button { color: $priamry; } // Typo
// Solution: Fix spelling or import the file with the variable
// 2. Invalid CSS
// Error: Expected expression.
.box {
width: ; // Missing value
}
// Solution: Provide a value
// 3. Type Error
// Error: $weight: "bold" is not a number.
font-weight: mix(400, "bold", 50%); // Can't mix number and string
// Solution: Use correct types
// 4. Division
// Error: Undefined operation "300px / 16".
font-size: 300px / 16; // Sass doesn't auto-divide
// Solution: Use math.div()
@use 'sass:math';
font-size: math.div(300px, 16);
// 5. Missing Import
// Error: Undefined mixin.
.button { @include flex-center; } // Mixin not imported
// Solution: @use the file containing the mixin
// 6. Circular Import
// Error: Module loop: circular import
// _a.scss imports _b.scss, _b.scss imports _a.scss
// Solution: Refactor to break the cycle
// 7. Invalid Selector
// Error: Invalid CSS after "...": expected selector
.#{$var} {
.& { } // Can't use & at start
}
// Solution: &.class or .class&
// 8. Map Error
// Error: (primary: #1976d2, secondary: #dc004e) is not a color.
$colors: (primary: #1976d2);
background: $colors; // Trying to use map as color
// Solution: background: map.get($colors, primary);
// 9. Incompatible Units
// Error: Incompatible units px and %.
width: 100px + 50%; // Can't add different units
// Solution: Use calc() or convert units
// 10. @extend Outside
// Error: @extend may only be used within style rules.
@extend %placeholder; // At root level
// Solution: Move inside a selector
5. Debugging Tools (VS Code, DevTools) Integration
| Tool | Feature | Platform | Use Case |
|---|---|---|---|
| Chrome DevTools | Source maps, CSS inspector | Chrome, Edge | Live debugging |
| Firefox DevTools | Style editor, source maps | Firefox | CSS debugging |
| Safari Web Inspector | Styles pane, sources | Safari | macOS/iOS debugging |
| VS Code Debugger | Breakpoints in SCSS | VS Code | Pre-compilation debug |
| Sass Playground | Online compiler | Web | Quick testing |
| Source Maps | Map CSS to SCSS | All browsers | Find original source |
Example: Chrome DevTools debugging workflow
// 1. Enable source maps in compilation
sass --watch --source-map src/scss:dist/css
// 2. Source SCSS file: src/scss/components/_button.scss
.button {
$bg: #1976d2;
$padding: 12px 24px;
background: $bg;
padding: $padding;
&:hover {
background: darken($bg, 10%);
}
}
// 3. In Chrome DevTools:
// - Open DevTools (F12)
// - Navigate to Sources tab
// - Expand "webpack://" or "scss://" folder
// - Find src/scss/components/_button.scss
// - See original SCSS with variables!
// 4. Inspect element shows:
// ┌─────────────────────────────────────┐
// │ Styles │
// ├─────────────────────────────────────┤
// │ .button │
// │ background: #1976d2; │
// │ _button.scss:5 │ ← Click to see SCSS
// │ padding: 12px 24px; │
// │ _button.scss:6 │
// └─────────────────────────────────────┘
// 5. Edit SCSS directly (with workspace):
// - Right-click source folder → "Add folder to workspace"
// - Allow access
// - Edit SCSS in DevTools Sources tab
// - Changes save to disk automatically
// - Sass watch mode recompiles
// - Page updates with new styles
// 6. Override styles temporarily:
// - In Elements → Styles pane
// - Add/modify CSS
// - See which SCSS file it came from
// - Update the actual SCSS file
Example: VS Code SCSS debugging setup
// .vscode/tasks.json - Compile task
{
"version": "2.0.0",
"tasks": [
{
"label": "Watch Sass",
"type": "shell",
"command": "sass",
"args": [
"--watch",
"--style=expanded",
"--source-map",
"src/scss:dist/css"
],
"problemMatcher": ["$sass"],
"isBackground": true,
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
// .vscode/launch.json - Debug configuration
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Debug in Chrome",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"sourceMaps": true,
"preLaunchTask": "Watch Sass"
}
]
}
// VS Code Extensions for SCSS:
// 1. Sass (.sass) - Syntax highlighting
// 2. SCSS IntelliSense - Autocomplete
// 3. SCSS Formatter - Code formatting
// 4. Live Sass Compiler - Auto-compile with output
// Usage:
// 1. Press Ctrl+Shift+B to start Sass watcher
// 2. Press F5 to launch debugger
// 3. Set breakpoints in JavaScript (not SCSS)
// 4. Inspect styles in integrated browser
Example: Source map debugging techniques
// Generate detailed source maps
sass --watch \
--embed-sources \
--source-map \
--source-map-urls=relative \
src/scss:dist/css
// Result: main.css.map
{
"version": 3,
"sourceRoot": "",
"sources": [
"../src/scss/main.scss",
"../src/scss/_variables.scss",
"../src/scss/components/_button.scss"
],
"sourcesContent": [
"@use 'variables';\n@use 'components/button';",
"$primary: #1976d2;",
".button { background: $primary; }"
],
"names": [],
"mappings": "AAEA;EACE;EACA;;AAEA;EACE"
}
// Browser DevTools features:
// 1. Click CSS property → jumps to SCSS line
// 2. See variable name instead of computed value
// 3. Edit SCSS (with workspaces)
// 4. Search across SCSS files
// 5. Set CSS breakpoints (pause when style applied)
// Debugging without source maps:
// ❌ Elements → Styles shows:
// main.css:234 { background: #1976d2; }
// (No way to know which SCSS file)
// ✅ With source maps:
// _button.scss:12 { background: $primary; }
// (Shows exact SCSS file and line)
6. Common SCSS Compilation Errors and Fixes
| Error Pattern | Cause | Solution | Prevention |
|---|---|---|---|
| Undefined Variable | Typo or missing import | Check spelling, import file | Use linter, IDE autocomplete |
| Module Not Found | Wrong path in @use/@import | Verify file path | Consistent file structure |
| Type Mismatch | Wrong data type | Validate input types | Add type checks |
| Division Error | Using / for division | Use math.div() | Always use math module |
| Circular Import | A imports B, B imports A | Refactor architecture | One-way dependencies |
| @extend Outside Rule | @extend at root level | Move inside selector | Use mixins instead |
Example: Error prevention patterns
// 1. Defensive function design
@use 'sass:meta';
@use 'sass:math';
@function safe-divide($a, $b, $fallback: 0) {
// Validate types
@if meta.type-of($a) != 'number' or meta.type-of($b) != 'number' {
@warn "safe-divide expects numbers, got: #{$a}, #{$b}";
@return $fallback;
}
// Check for zero division
@if $b == 0 {
@warn "Division by zero, returning fallback: #{$fallback}";
@return $fallback;
}
@return math.div($a, $b);
}
// 2. Null-safe map access
@function get-or-default($map, $key, $default: null) {
@if not meta.type-of($map) == 'map' {
@error "Expected map, got: #{meta.type-of($map)}";
}
@if map.has-key($map, $key) {
@return map.get($map, $key);
}
@if $default == null {
@warn "Key '#{$key}' not found in map and no default provided";
}
@return $default;
}
// 3. Runtime type checking
@mixin type-safe-property($property, $value, $allowed-types...) {
$type: meta.type-of($value);
@if not index($allowed-types, $type) {
@error "#{$property} expects one of #{$allowed-types}, got: #{$type}";
}
#{$property}: $value;
}
// Usage
.element {
@include type-safe-property('padding', 20px, 'number');
@include type-safe-property('color', #000, 'color', 'string');
}
// 4. Import guard pattern
$_module-loaded: false !default;
@if $_module-loaded {
@error "This module has already been loaded. Avoid importing it multiple times.";
}
$_module-loaded: true !global;
// 5. Version compatibility check
@if not function-exists('math.div') {
@error "This code requires Sass 1.33.0 or higher for math.div(). " +
"Please upgrade your Sass version.";
}
Example: Debugging helpers library
// _debug.scss - Reusable debugging utilities
@use 'sass:meta';
@use 'sass:map';
@use 'sass:list';
// Visual debugging overlay
@mixin debug-outline($color: red) {
outline: 2px solid $color !important;
outline-offset: -2px;
}
// Show all elements
@mixin debug-all($color: rgba(255, 0, 0, 0.2)) {
* {
@include debug-outline($color);
}
}
// Print variable with formatting
@mixin debug-var($name, $value) {
@debug "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━";
@debug "Variable: #{$name}";
@debug " Type: #{meta.type-of($value)}";
@debug " Value: #{$value}";
@if meta.type-of($value) == 'map' {
@debug " Keys: #{map.keys($value)}";
} @else if meta.type-of($value) == 'list' {
@debug " Length: #{list.length($value)}";
}
@debug "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━";
}
// Performance timing
$_debug-timers: () !default;
@mixin start-timer($name) {
// In real implementation, use timestamp
@debug "[TIMER] Started: #{$name}";
}
@mixin end-timer($name) {
@debug "[TIMER] Ended: #{$name}";
}
// Assertion helper
@mixin assert-equals($actual, $expected, $message: '') {
@if $actual != $expected {
@error "Assertion failed: #{$message}\n" +
" Expected: #{$expected}\n" +
" Actual: #{$actual}";
} @else {
@debug "✓ Assertion passed: #{$message}";
}
}
// Usage examples
$primary: #1976d2;
@include debug-var('Primary Color', $primary);
@include start-timer('compilation');
// ... your code ...
@include end-timer('compilation');
@include assert-equals(10px + 5px, 15px, 'Basic math');
Example: Error recovery strategies
// Graceful degradation
@function get-color($theme, $key) {
// Try to get from theme
@if map.has-key($theme, $key) {
@return map.get($theme, $key);
}
// Fallback to default colors
@warn "Color '#{$key}' not found in theme, using default";
$defaults: (
primary: #1976d2,
secondary: #dc004e,
background: #ffffff,
text: #000000
);
@if map.has-key($defaults, $key) {
@return map.get($defaults, $key);
}
// Last resort
@error "Color '#{$key}' not found in theme or defaults";
}
// Try-catch pattern (error suppression)
@function try-parse-number($value) {
@if meta.type-of($value) == 'number' {
@return $value;
}
// Try to parse string to number
@if meta.type-of($value) == 'string' {
@if str-index($value, 'px') {
// In real implementation, parse the number
@warn "String contains px, attempting conversion";
@return 0px; // Placeholder
}
}
@warn "Cannot parse '#{$value}' as number, returning 0";
@return 0;
}
// Validation with auto-correction
@function validate-spacing($value) {
// Must be positive
@if $value < 0 {
@warn "Spacing cannot be negative (#{$value}), using absolute value";
@return abs($value);
}
// Warn about large values
@if $value > 100px {
@warn "Unusually large spacing value: #{$value}";
}
@return $value;
}
// Progressive enhancement
@mixin with-fallback($property, $modern-value, $fallback-value) {
#{$property}: $fallback-value; // Fallback first
@supports (#{$property}: #{$modern-value}) {
#{$property}: $modern-value; // Modern override
}
}
// Usage
.element {
@include with-fallback(
'display',
'grid',
'block'
);
}
Error Handling Best Practices
- @debug: Use for development logging and inspecting values
- @warn: Use for deprecations and non-critical issues
- @error: Use for critical failures that should stop compilation
- Validate early: Check types and ranges at function entry
- Meaningful messages: Include context, expected values, and solutions
- Source maps: Essential for production debugging - map CSS back to SCSS
- Stack traces: Read bottom-to-top to trace error origin
- Defensive coding: Add guards, defaults, and null checks
Note: Enable source maps in development and staging environments
for effective debugging. In production, disable them unless you need to debug live issues, as they expose your
source code structure.