Welcome @name to another chamber of Egyptian wisdom! I am Mohamed, and today we will reveal one of the most important secrets of modern CSS - the difference between SASS variables and native CSS Custom Properties (also called CSS Variables).
Just as the ancient Egyptians had different tools for different purposes - some for building pyramids, others for drawing hieroglyphs - we too have different tools for managing values in CSS. Let's explore them!
SASS variables are processed at compile time. This means that before your code reaches the browser, SASS replaces all variables with concrete values.
1// SASS variables - compile time
2$primary-color: #3498db;
3$spacing-unit: 8px;
4$font-stack: 'Roboto', sans-serif;
5
6.button {
7 background: $primary-color;
8 padding: $spacing-unit * 2;
9 font-family: $font-stack;
10}After compiling to CSS:
1.button {
2 background: #3498db;
3 padding: 16px;
4 font-family: 'Roboto', sans-serif;
5}As you can see, SASS variables disappear in the final CSS - only concrete values remain. It's like hieroglyphs that, once translated, become plain text.
CSS Custom Properties work in the browser in real time. They are true CSS variables that can be changed dynamically!
1/* CSS Custom Properties - runtime, dynamic! */
2:root {
3 --primary-color: #3498db;
4 --spacing-unit: 8px;
5 --font-stack: 'Roboto', sans-serif;
6}
7
8.button {
9 background: var(--primary-color);
10 padding: calc(var(--spacing-unit) * 2);
11 font-family: var(--font-stack);
12}The difference: These variables remain in the final CSS and can be changed dynamically via JavaScript!
1// You can change CSS Custom Properties at runtime!
2document.documentElement.style.setProperty('--primary-color', '#e74c3c');
3
4// SASS variables CANNOT be changed at runtime - they are already compiled!SASS Variables:
1$global-color: blue;
2
3.foo {
4 $local-color: green;
5 color: $local-color; // works
6}
7
8.bar {
9 color: $local-color; // ERROR! Variable not available
10}CSS Custom Properties:
1:root {
2 --global-color: blue;
3}
4
5.foo {
6 --local-color: green;
7 color: var(--local-color); /* works */
8}
9
10.bar {
11 color: var(--local-color); /* falls back to default value or inheritance */
12}CSS Custom Properties inherit down the DOM tree - just like color or font!
SASS Variables:
1$base-size: 16px;
2$large-size: $base-size * 2; // 32px - calculated during compilation
3
4.element {
5 font-size: $large-size; // result: font-size: 32px;
6}CSS Custom Properties:
1:root {
2 --base-size: 16px;
3}
4
5.element {
6 /* You must use calc() */
7 font-size: calc(var(--base-size) * 2);
8}SASS Variables - no support for dynamic changes:
1// This WON'T WORK at runtime!
2$theme-color: #3498db;
3
4.theme-light {
5 $theme-color: #ecf0f1; // This won't change after the page loads
6}CSS Custom Properties - full dynamism:
1:root {
2 --theme-color: #3498db;
3 --background: #ffffff;
4 --text: #000000;
5}
6
7/* Dark theme - just override the variables! */
8[data-theme="dark"] {
9 --theme-color: #e74c3c;
10 --background: #2c3e50;
11 --text: #ecf0f1;
12}
13
14.page {
15 background: var(--background);
16 color: var(--text);
17}You can switch themes with a single line of JavaScript:
1document.body.setAttribute('data-theme', 'dark');1$primary-color: #3498db;
2
3@mixin button-variant($color) {
4 background: $color;
5 border-color: darken($color, 10%);
6
7 &:hover {
8 background: darken($color, 15%);
9 }
10}
11
12.btn-primary {
13 @include button-variant($primary-color);
14}1$grid-columns: 12;
2$grid-gutter: 30px;
3
4@for $i from 1 through $grid-columns {
5 .col-#{$i} {
6 width: percentage($i / $grid-columns);
7 }
8}1$breakpoint-tablet: 768px;
2
3.header {
4 padding: 20px;
5
6 @media (min-width: $breakpoint-tablet) {
7 padding: 40px;
8 }
9
10 .nav {
11 display: flex;
12
13 &__item {
14 margin: 0 10px;
15 }
16 }
17}1:root {
2 --primary-hue: 210;
3 --primary-saturation: 70%;
4 --primary-lightness: 50%;
5}
6
7.button {
8 background: hsl(
9 var(--primary-hue),
10 var(--primary-saturation),
11 var(--primary-lightness)
12 );
13}
14
15/* Change the hue dynamically in JS */1const slider = document.querySelector('#hue-slider');
2slider.addEventListener('input', (e) => {
3 document.documentElement.style.setProperty('--primary-hue', e.target.value);
4});1/* Light theme */
2:root {
3 --bg-primary: #ffffff;
4 --bg-secondary: #f8f9fa;
5 --text-primary: #212529;
6 --text-secondary: #6c757d;
7 --border-color: #dee2e6;
8}
9
10/* Dark theme */
11[data-theme="dark"] {
12 --bg-primary: #212529;
13 --bg-secondary: #343a40;
14 --text-primary: #f8f9fa;
15 --text-secondary: #adb5bd;
16 --border-color: #495057;
17}
18
19/* Components use the same variables */
20.card {
21 background: var(--bg-primary);
22 color: var(--text-primary);
23 border: 1px solid var(--border-color);
24}1.card {
2 --card-padding: 1rem;
3 --card-bg: white;
4
5 padding: var(--card-padding);
6 background: var(--card-bg);
7}
8
9.card--large {
10 --card-padding: 2rem; /* Override only padding */
11}
12
13.card--dark {
14 --card-bg: #2c3e50; /* Override only background */
15}Just as the ancient Egyptians used different tools to build their architectural wonders, you too should combine the power of SASS and CSS Custom Properties!
1// _variables.scss - SASS variables for project configuration
2$color-blue-500: #3498db;
3$color-red-500: #e74c3c;
4$spacing-base: 8px;
5
6// Generate CSS Custom Properties from SASS variables
7:root {
8 // Colors
9 --color-primary: #{$color-blue-500};
10 --color-danger: #{$color-red-500};
11
12 // Spacing
13 --spacing-xs: #{$spacing-base * 0.5};
14 --spacing-sm: #{$spacing-base};
15 --spacing-md: #{$spacing-base * 2};
16 --spacing-lg: #{$spacing-base * 3};
17}
18
19// Use SASS to generate variants
20@mixin generate-spacing-utilities {
21 @each $size, $value in (
22 'xs': var(--spacing-xs),
23 'sm': var(--spacing-sm),
24 'md': var(--spacing-md),
25 'lg': var(--spacing-lg)
26 ) {
27 .p-#{$size} {
28 padding: #{$value};
29 }
30 .m-#{$size} {
31 margin: #{$value};
32 }
33 }
34}
35
36@include generate-spacing-utilities;1// SASS - configuration and breakpoints
2$breakpoint-sm: 576px;
3$breakpoint-md: 768px;
4$breakpoint-lg: 992px;
5
6:root {
7 // Base font size - can be changed by user preferences
8 --font-size-base: 16px;
9
10 // Typographic scale
11 --font-size-xs: 0.75rem;
12 --font-size-sm: 0.875rem;
13 --font-size-md: 1rem;
14 --font-size-lg: 1.125rem;
15 --font-size-xl: 1.25rem;
16 --font-size-2xl: 1.5rem;
17 --font-size-3xl: 2rem;
18}
19
20// SASS mixin for responsive typography
21@mixin responsive-font-size($min, $max, $min-vw: $breakpoint-sm, $max-vw: $breakpoint-lg) {
22 font-size: $min;
23
24 @media (min-width: $min-vw) {
25 font-size: calc(#{$min} + (#{$max} - #{$min}) * ((100vw - #{$min-vw}) / (#{$max-vw} - #{$min-vw})));
26 }
27
28 @media (min-width: $max-vw) {
29 font-size: $max;
30 }
31}
32
33.heading {
34 @include responsive-font-size(var(--font-size-xl), var(--font-size-3xl));
35}You can now change the font size for users with accessibility preferences:
1// User selects larger fonts
2document.documentElement.style.setProperty('--font-size-base', '20px');1// Configuration in SASS
2$colors: (
3 'blue': #3498db,
4 'red': #e74c3c,
5 'green': #27ae60
6);
7
8// Generate CSS Custom Properties
9:root {
10 @each $name, $color in $colors {
11 --color-#{$name}: #{$color};
12 --color-#{$name}-light: #{lighten($color, 10%)};
13 --color-#{$name}-dark: #{darken($color, 10%)};
14 }
15}
16
17// Use in components
18.button {
19 background: var(--color-blue);
20
21 &:hover {
22 background: var(--color-blue-dark);
23 }
24}
25
26// In JavaScript you can dynamically change
27document.documentElement.style.setProperty('--color-blue', '#2ecc71');Create a theme system that combines SASS and CSS Custom Properties:
Just as pharaohs combined different materials to build their monuments, you too should combine the power of SASS and CSS Custom Properties to create a powerful, flexible, and easily maintainable style system!
Good luck, young builder of CSS hieroglyphs!