Operators & Expressions
Introduction to SASS Operators
SASS provides a comprehensive set of operators that allow you to perform calculations, comparisons, and logical operations directly in your stylesheets. These operators enable you to create dynamic, maintainable CSS by computing values based on variables, performing mathematical operations, and implementing conditional logic.
Why Use Operators?
Operators in SASS provide several benefits:
- Dynamic calculations: Compute values instead of hardcoding them
- Maintainability: Change base values and let calculations update automatically
- Consistency: Use mathematical relationships to ensure proportional sizing
- Logic: Make style decisions based on conditions
- Flexibility: Create adaptive systems that respond to configuration changes
Arithmetic Operators
Addition (+)
Add numbers together. Units must be compatible or one operand must be unitless:
Addition Examples
$base-padding: 1rem;
$extra-padding: 0.5rem;
.element {
padding: $base-padding + $extra-padding; // 1.5rem
margin: 10px + 5px; // 15px
width: 50% + 10%; // 60%
}
// String concatenation with +
$family: "Helvetica";
$fallback: "Arial";
$font-stack: $family + ", " + $fallback; // "Helvetica, Arial"
// Adding unitless to unit
.box {
width: 100px + 20; // 120px (unitless treated as same unit)
}
10px + 5rem will cause a compilation error. Convert units first or use calc() for CSS-level calculations.
Subtraction (-)
Subtract one number from another:
Subtraction Examples
$container-width: 1200px;
$sidebar-width: 300px;
.content {
width: $container-width - $sidebar-width; // 900px
}
// Negative values
$spacing: 20px;
.element {
margin-top: -$spacing; // -20px
}
// Percentage calculations
.column {
width: 100% - 20%; // 80%
}
Multiplication (*)
Multiply numbers. At most one operand can have a unit:
Multiplication Examples
$base-size: 16px;
$multiplier: 1.5;
.heading {
font-size: $base-size * $multiplier; // 24px
}
// Creating scales
$spacing-unit: 8px;
.mt-1 { margin-top: $spacing-unit * 1; } // 8px
.mt-2 { margin-top: $spacing-unit * 2; } // 16px
.mt-3 { margin-top: $spacing-unit * 3; } // 24px
// Grid calculations
$columns: 12;
$column-width: 100% / $columns;
.col-3 { width: $column-width * 3; } // 25%
10px * 2px is invalid because it would result in px², which isn't a valid CSS unit.
Division (/) - The Modern Approach
In modern SASS (Dart SASS), the / operator no longer performs division because CSS uses / for font shorthand and other properties. Use math.div() instead:
Modern Division with math.div()
@use "sass:math";
$container-width: 1200px;
$columns: 12;
.column {
width: math.div($container-width, $columns); // 100px
}
// Percentage calculations
.half-width {
width: math.div(100%, 2); // 50%
}
// Complex calculations
$spacing-base: 32px;
.element {
margin: math.div($spacing-base, 4); // 8px
padding: math.div($spacing-base, 2); // 16px
}
Legacy Division Behavior
In older SASS versions, / performed division in certain contexts:
Legacy Division (Avoid in New Code)
// Old way (deprecated)
.element {
width: (100px / 2); // 50px (with parentheses)
width: $width / 2; // 50px (with variable)
width: 100px / 2px; // 100px / 2px (preserved as CSS)
}
// Modern equivalent
@use "sass:math";
.element {
width: math.div(100px, 2); // 50px
width: math.div($width, 2); // 50px
}
@use "sass:math" and math.div() for division in new SASS projects. This makes your code future-proof and explicit about your intentions.
Modulo (%)
Get the remainder of division:
Modulo Examples
// Check if number is even or odd
@function is-even($number) {
@return $number % 2 == 0;
}
// Alternate row colors
@for $i from 1 through 10 {
.row-#{$i} {
@if $i % 2 == 0 {
background: #f0f0f0; // Even rows
} @else {
background: white; // Odd rows
}
}
}
// Circular indexing
$colors: red, green, blue;
@for $i from 1 through 10 {
$index: $i % length($colors);
@if $index == 0 { $index: length($colors); }
.item-#{$i} {
color: nth($colors, $index);
}
}
String Concatenation
Combining Strings with +
Join strings together using the addition operator:
String Concatenation
$prefix: "mobile";
$suffix: "menu";
$class-name: $prefix + "-" + $suffix; // "mobile-menu"
// Quote handling
$quoted: "hello" + " world"; // "hello world" (quoted)
$unquoted: hello + " world"; // hello world (unquoted)
// Practical usage
$image-path: "/images/";
$image-name: "logo.png";
.logo {
background-image: url($image-path + $image-name);
// Result: url(/images/logo.png)
}
#{} when you need more control over quoting.
Color Arithmetic
Mathematical Operations on Colors
SASS allows arithmetic operations on colors, operating on each RGB channel separately:
Color Arithmetic
// Addition
$color1: #102030;
$color2: #010101;
$result: $color1 + $color2; // #112131
// Subtraction
$color: #123456;
$adjusted: $color - #001111; // #112345
// Multiplication (use carefully)
$base-color: #222222;
$brighter: $base-color * 2; // #444444
// Division (legacy - avoid)
// Use color functions instead!
lighten(), darken(), saturate(), adjust-color() instead for predictable, perceptually accurate results.
Comparison Operators
Equality and Inequality
Compare values for equality:
Equality Operators
// Equality (==)
$size: 16px;
@if $size == 16px {
.text { font-size: $size; }
}
// Inequality (!=)
$theme: "dark";
@if $theme != "light" {
body { background: #333; }
}
// Type matters
@debug 1 == 1px; // false (different units)
@debug "10" == 10; // false (string vs number)
@debug true == true; // true
Relational Operators
Compare numerical values:
Relational Comparisons
$breakpoint: 768px;
$screen-width: 1024px;
// Less than (<)
@if $screen-width < 1200px {
.container { max-width: 960px; }
}
// Greater than (>)
@if $breakpoint > 600px {
.sidebar { display: block; }
}
// Less than or equal (<=)
@if $screen-width <= 768px {
.mobile-nav { display: flex; }
}
// Greater than or equal (>=)
@if $breakpoint >= 768px {
.desktop-header { display: block; }
}
// Practical responsive mixin
@mixin respond-above($breakpoint) {
@if $breakpoint > 0 {
@media (min-width: $breakpoint) {
@content;
}
}
}
Logical Operators
AND Operator
Both conditions must be true:
Logical AND
$is-mobile: true;
$has-touch: true;
@if $is-mobile and $has-touch {
.app {
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
}
// Multiple conditions
$width: 320px;
$height: 568px;
@if $width >= 320px and $width <= 480px and $height < 600px {
.container { padding: 10px; }
}
OR Operator
At least one condition must be true:
Logical OR
$theme: "dark";
$high-contrast: false;
@if $theme == "dark" or $high-contrast {
body {
background: #000;
color: #fff;
}
}
// Multiple alternatives
$device: "tablet";
@if $device == "mobile" or $device == "tablet" {
.layout { display: flex; flex-direction: column; }
}
NOT Operator
Negate a boolean value:
Logical NOT
$is-production: false;
@if not $is-production {
.debug-panel { display: block; }
}
// Combined with other operators
$enable-animations: true;
$reduced-motion: false;
@if $enable-animations and not $reduced-motion {
.element { transition: all 0.3s ease; }
}
Complex Logical Expressions
Combining Logical Operators
$screen-width: 1024px;
$is-mobile: false;
$is-tablet: true;
$orientation: "landscape";
@if ($is-mobile or $is-tablet) and $screen-width > 768px {
.navigation { display: flex; justify-content: space-between; }
}
@if not $is-mobile and ($orientation == "landscape" or $screen-width > 1200px) {
.sidebar { width: 300px; }
}
// Validation function
@function is-valid-breakpoint($bp) {
@return $bp > 0 and $bp < 2000px and unit($bp) == "px";
}
Using calc() with SASS Variables
Combining SASS and CSS Calculations
Use CSS calc() for calculations that need to happen at runtime or involve mixed units:
calc() Integration
$sidebar-width: 250px;
$gap: 20px;
.content {
// SASS can't combine px and percentage at compile time
width: calc(100% - #{$sidebar-width} - #{$gap});
}
// Responsive spacing
$base-spacing: 1rem;
.element {
margin: calc(#{$base-spacing} + 2vw);
padding: calc(#{$base-spacing} * 2);
}
// Dynamic calculations with CSS custom properties
:root {
--sidebar-width: 250px;
}
.content {
// Pure CSS
width: calc(100% - var(--sidebar-width) - 20px);
}
Order of Operations
Operator Precedence
SASS follows standard mathematical order of operations:
Precedence Rules
// 1. Parentheses (highest priority)
$result: (10 + 5) * 2; // 30 (not 20)
// 2. Multiplication, Division, Modulo
$result: 10 + 5 * 2; // 20 (5*2 first, then +10)
// 3. Addition, Subtraction
$result: 10 - 5 + 3; // 8 (left to right)
// Practical example
$base: 16px;
$scale: 1.5;
$spacing: 8px;
.element {
// Clear order with parentheses
font-size: $base * $scale; // 24px
margin: ($base + $spacing) * 2; // 48px
padding: $base + $spacing * 2; // 32px (spacing*2 first)
}
Unit Handling
Working with Units
Understanding how SASS handles units in operations:
Unit Operations
// Same units
$a: 10px + 5px; // 15px ✓
$b: 20% - 5%; // 15% ✓
// Unitless with unit
$c: 100px + 10; // 110px ✓ (10 treated as px)
$d: 10 + 100px; // 110px ✓
// Different units (ERROR)
// $e: 10px + 5rem; // ✗ Compilation error!
// Multiplication (only one can have unit)
$f: 10px * 2; // 20px ✓
$g: 2 * 10px; // 20px ✓
// $h: 10px * 2px; // ✗ Error! Would be px²
// Division
@use "sass:math";
$i: math.div(20px, 2); // 10px ✓
$j: math.div(20px, 5px); // 4 (unitless) ✓
Unit Conversion Functions
Converting Between Units
@use "sass:math";
// Strip units
@function strip-unit($number) {
@if math.is-unitless($number) {
@return $number;
}
@return math.div($number, $number * 0 + 1);
}
$value: strip-unit(16px); // 16
// Add unit
@function add-unit($number, $unit) {
$unitless: strip-unit($number);
@return $unitless * 1#{$unit};
}
// Convert rem to px (assumes 16px base)
@function rem-to-px($rem) {
@return strip-unit($rem) * 16px;
}
$px-value: rem-to-px(1.5rem); // 24px
Exercise 1: Fluid Typography System
Create a fluid typography calculator using operators:
- Define min and max font sizes (e.g., 16px to 24px)
- Define min and max viewport widths (e.g., 320px to 1200px)
- Create a function that calculates the rate of change
- Generate a calc() expression for fluid scaling
- Create mixins for h1-h6 with different min/max ranges
- Test with different viewport scenarios
Exercise 2: Grid Calculator
Build a flexible grid system with operator-based calculations:
- Define container width, number of columns, and gutter size
- Calculate column width using division: (container - gutters) / columns
- Create a function: column-width($span, $total-columns)
- Handle different gutter sizes (inside, outside, between)
- Generate classes for column spans (1-12)
- Add responsive calculations for different breakpoints
Exercise 3: Color Shade Generator
Create a shade/tint system using operators and conditionals:
- Define a base color
- Create a function that generates lighter shades (1-5)
- Create a function that generates darker shades (1-5)
- Use comparison operators to ensure shades stay within valid ranges
- Generate CSS custom properties for each shade
- Create utility classes: .bg-primary-light-1, .bg-primary-dark-2, etc.
Summary
In this lesson, you mastered:
- Arithmetic operators: +, -, *, /, % for mathematical calculations
- Modern division with math.div() from the sass:math module
- String concatenation with the + operator
- Color arithmetic and why to prefer color functions
- Comparison operators: ==, !=, <, >, <=, >= for conditional logic
- Logical operators: and, or, not for complex conditions
- Integrating SASS variables with CSS calc() function
- Operator precedence and order of operations
- Unit handling, compatibility, and conversion techniques
Operators are essential for creating dynamic, calculation-based stylesheets. They enable you to build flexible design systems that automatically adjust based on base values, create mathematical relationships between elements, and implement sophisticated conditional logic. Combined with variables and functions, operators form the computational foundation of advanced SASS development.