Skip to content

Latest commit

 

History

History
1706 lines (1295 loc) · 39.4 KB

File metadata and controls

1706 lines (1295 loc) · 39.4 KB

SCSS Basics


Q. Explain what is Sass?

Sass (which stands for 'Syntactically awesome style sheets) is an extension of CSS that enables you to use things like variables, nested rules, inline imports and more. It also helps to keep things organized and allows you to create style sheets faster.

Sass works by writing your styles in .scss (or .sass) files, which will then get compiled into a regular CSS file. The newly compiled CSS file is what gets loaded to your browser to style your web application. This allows the browser to properly apply the styles to your web page.

Sass Process

Live Demo: Sass Example

Q. What are the SCSS basic features?

1. Variables

Variables are useful for things like colors, fonts, font sizes, and certain dimensions, as you can be sure always using the same ones. Variables in SCSS start with $ sign

SCSS Style

$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}

CSS Style

body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

When the Sass is processed, it takes the variables we define for the $font-stack and $primary-color and outputs normal CSS with our variable values placed in the CSS. This can be extremely powerful when working with brand colors and keeping them consistent throughout the site.

Live Demo: Sass Variables

2. Nesting

Basic nesting refers to the ability to have a declaration inside of a declaration.

SCSS Style

nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}

CSS Style

nav ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
nav li {
  display: inline-block;
}
nav a {
  display: block;
  padding: 6px 12px;
  text-decoration: none;
}

Live Demo: Sass Nesting

3. Partials

The partial Sass files contain little snippets of CSS that can be included in other Sass files. This is a great way to modularize your CSS and help keep things easier to maintain. A partial is a Sass file named with a leading underscore. You might name it something like _partial.scss. The underscore lets Sass know that the file is only a partial file and that it should not be generated into a CSS file. Sass partials are used with the @use rule.

4. Modules

This rule loads another Sass file as a module, which means we can refer to its variables, mixins, and functions in our Sass file with a namespace based on the filename. Using a file will also include the CSS it generates in your compiled output!

SCSS Style

// _base.scss
$font-stack:    Helvetica, sans-serif;
$primary-color: #333;

body {
  font: 100% $font-stack;
  color: $primary-color;
}
// styles.scss
@use 'base';

.inverse {
  background-color: base.$primary-color;
  color: white;
}

CSS Style

body {
  font: 100% Helvetica, sans-serif;
  color: #333;
}

.inverse {
  background-color: #333;
  color: white;
}

5. Mixins

A mixin provide to make groups of CSS declarations that you want to reuse throughout your site. You can even pass in values to make your mixin more flexible.

SCSS Style

@mixin transform($property) {
  -webkit-transform: $property;
  -ms-transform: $property;
  transform: $property;
}
.box { @include transform(rotate(30deg)); }

CSS Style

.box {
  -webkit-transform: rotate(30deg);
  -ms-transform: rotate(30deg);
  transform: rotate(30deg);
}

Live Demo: Sass Mixins

6. Inheritance

Using @extend lets you share a set of CSS properties from one selector to another.

SCSS Style

/* This CSS will print because %message-shared is extended. */
%message-shared {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}

// This CSS won\'t print because %equal-heights is never extended.
%equal-heights {
  display: flex;
  flex-wrap: wrap;
}

.message {
  @extend %message-shared;
}

.success {
  @extend %message-shared;
  border-color: green;
}

.error {
  @extend %message-shared;
  border-color: red;
}

.warning {
  @extend %message-shared;
  border-color: yellow;
}

CSS Style

/* This CSS will print because %message-shared is extended. */
.message, .success, .error, .warning {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}

.success {
  border-color: green;
}

.error {
  border-color: red;
}

.warning {
  border-color: yellow;
}

Live Demo: Sass Inheritance

7. Operators

Sass has a handful of standard math operators like +, -, *, /, and %. In our example we're going to do some simple math to calculate widths for an aside & article.

SCSS Style

.container {
  width: 100%;
}

article[role="main"] {
  float: left;
  width: 600px / 960px * 100%;
}

aside[role="complementary"] {
  float: right;
  width: 300px / 960px * 100%;
}

CSS Style

.container {
  width: 100%;
}

article[role="main"] {
  float: left;
  width: 62.5%;
}

aside[role="complementary"] {
  float: right;
  width: 31.25%;
}

Q. List out the data types that Sass supports?

Sass supports the following data types:

Data Type Example
Numbers 1, 1.5, 10px, 2em
Strings "hello", 'world', bold (quoted and unquoted)
Colors #fff, red, rgb(0,0,0), hsl(0,100%,50%)
Booleans true, false
Null null
Lists 1px 2px 3px, (10px, 20px) (space or comma separated)
Maps ("key": value, "key2": value2)
Functions First-class function references via meta.get-function()
@use "sass:meta";
@use "sass:math";

$number:  42px;                          // Number
$string:  "Helvetica";                   // String
$color:   #3498db;                       // Color
$bool:    true;                          // Boolean
$null:    null;                          // Null
$list:    10px 20px 30px;               // List
$map:     ("sm": 576px, "md": 768px);   // Map

.box {
  width: $number;
  font-family: $string;
  color: $color;
  @if $bool { display: block; }
  margin: if($null == null, 0, 10px);
}

Q. Explain the @include, @mixin, @function functions and how they are used. What is %placeholder?

i) @mixin A mixin lets you make groups of CSS declarations that you want to reuse throughout your site

@mixin border-radius($radius) {
  -webkit-border-radius: $radius;
     -moz-border-radius: $radius;
      -ms-border-radius: $radius;
          border-radius: $radius;
}
.box { @include border-radius(10px); }

ii) @extend directive provides a simple way to allow a selector to inherit/extend the styles of another one.

.message {
  border: 1px solid #ccc;
  padding: 10px;
  color: #333;
}

.success {
  @extend .message;
  border-color: green;
}

.error {
  @extend .message;
  border-color: red;
}

iii) %placeholder are classes that aren’t output when your SCSS is compiled

%awesome {
    width: 100%;
    height: 100%;
}
body {
    @extend %awesome;
}
p {
    @extend %awesome;
}
/* Output */
body, p {
    width: 100%;
    height: 100%;
}

Q. What is file splitting and why should you use it?

File splitting helps organize your CSS into multiple files, decreasing page load time and making things easier to manage. How you decide to split them up is up to you, but it can be useful to separate files by component. For example, we can have all button styles in a file called _buttons.scss or all your header-specific styles in a file called _header.scss, main file, say _app.scss, and we can import those files by writing @import 'buttons';

Q. What is the @content directive used for?

The @content directive is used inside a @mixin to allow the caller to pass a block of styles into the mixin. This makes mixins more flexible by acting as a placeholder for content passed via @include.

@mixin respond-to($breakpoint) {
  @if $breakpoint == "small" {
    @media (max-width: 767px) { @content; }
  } @else if $breakpoint == "medium" {
    @media (min-width: 768px) and (max-width: 1024px) { @content; }
  }
}

.sidebar {
  width: 300px;

  @include respond-to("small") {
    width: 100%;
  }
}

Compiled CSS:

.sidebar {
  width: 300px;
}
@media (max-width: 767px) {
  .sidebar {
    width: 100%;
  }
}

Q. What is wrong with Sass nesting?

Over-nesting is the most common pitfall. It produces overly specific CSS selectors, increases file size, hurts performance, and makes styles hard to override.

Bad (over-nested):

nav {
  ul {
    li {
      a {
        span { color: red; }
      }
    }
  }
}

Compiled CSS (overly specific):

nav ul li a span { color: red; }

Good practice: Limit nesting to a maximum of 3 levels deep. Use BEM or flat selectors where possible.

.nav__link {
  color: blue;

  &:hover { color: red; }
}

Q. What is variable interpolation in Sass?

Variable interpolation (#{}) allows you to embed the value of a Sass variable into a selector, property name, or string — anywhere that a plain variable $var cannot be used directly.

$property: margin;
$side: top;
$theme: "dark";

.box-#{$theme} {
  #{$property}-#{$side}: 10px;
}

Compiled CSS:

.box-dark {
  margin-top: 10px;
}

Q. What is the difference between SCSS and Sass?

Both are syntaxes for the same preprocessor. The key differences are:

Feature SCSS Sass (Indented)
File extension .scss .sass
Syntax style CSS-like (curly braces {}, semicolons ;) Indentation-based (no braces or semicolons)
CSS compatibility Valid CSS is valid SCSS Not compatible with plain CSS
Popularity More widely used Less common

SCSS:

$color: red;
body {
  color: $color;
}

Sass (indented):

$color: red
body
  color: $color

Q. What are the advantages/disadvantages of using CSS preprocessors?

Advantages:

  • Variables, nesting, mixins, and functions reduce repetition (DRY code)
  • Modular file organization via @use and @forward
  • Better maintainability for large stylesheets
  • Built-in math and color functions
  • Source maps for easier debugging

Disadvantages:

  • Requires a build/compilation step
  • Debugging compiled CSS can be harder without source maps
  • Over-nesting leads to specificity problems
  • Learning curve for new developers
  • Adds tooling complexity to the project

Q. Explain what is the use of Mixin function in Sass? What is the meaning of DRY-ing out a mixin?

A @mixin allows you to define reusable blocks of CSS declarations that can be included anywhere with @include. They support arguments, default values, and @content blocks.

@mixin flex-center($direction: row) {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: $direction;
}

.card {
  @include flex-center(column);
}

DRY-ing out a mixin means refactoring repeated CSS patterns into a single mixin so the same code is not duplicated across multiple selectors. "DRY" stands for Don't Repeat Yourself. Instead of writing vendor-prefixed or repeated declarations in every rule, you write them once inside a mixin and @include it wherever needed.

Q. Explain what Sass Maps is and what is the use of Sass Maps?

A Sass map is a data structure that stores key-value pairs, similar to a dictionary or object in programming languages. Maps are useful for grouping related values such as theme colors, breakpoints, or spacing scales.

$theme-colors: (
  "primary":   #3498db,
  "secondary": #2ecc71,
  "danger":    #e74c3c,
);

// Access a value
.btn-primary {
  background-color: map.get($theme-colors, "primary");
}

// Loop over a map
@use "sass:map";

@each $name, $color in $theme-colors {
  .text-#{$name} {
    color: $color;
  }
}

Compiled CSS:

.btn-primary { background-color: #3498db; }
.text-primary { color: #3498db; }
.text-secondary { color: #2ecc71; }
.text-danger { color: #e74c3c; }

Q. Explain how Sass comments are different from regular CSS?

Sass supports two types of comments:

Type Syntax Appears in compiled CSS?
Loud (CSS) comment /* ... */ Yes (preserved in output)
Silent (Sass) comment // ... No (stripped from output)
// This comment will NOT appear in the compiled CSS

/* This comment WILL appear in the compiled CSS */

.box {
  color: red; // inline silent comment — removed
  /* inline loud comment — kept */
}

Q. Does Sass support inline comments?

Yes. Sass supports // single-line (silent) comments that do not appear in the compiled CSS output, in addition to the standard CSS /* */ multi-line comments which are preserved.

$primary: #333; // silent — stripped from output

/* loud comment — kept in output */
body {
  color: $primary;
}

Q. Explain when can you use the %placeholders in Sass?

%placeholders (silent/abstract classes) are selectors defined with % that produce no CSS output on their own — they only generate output when extended with @extend. Use them when:

  • You want shared styles without a standalone CSS class in the output
  • You want to avoid repeating the same set of rules across multiple selectors
%visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

.sr-only {
  @extend %visually-hidden;
}

.skip-link {
  @extend %visually-hidden;
}

Compiled CSS:

.sr-only, .skip-link {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

Q. Is it possible to nest variables within variables in Sass?

Sass does not support direct variable interpolation of one variable inside another variable's value at declaration time. However, you can use interpolation (#{}) to dynamically build variable names and use them in selectors or property names. For values, you compose them at use time.

$size: "large";
$font-large: 2rem;
$font-small: 1rem;

// Use a map instead for dynamic variable lookups
$font-sizes: (
  "large": 2rem,
  "small": 1rem,
);

.heading {
  font-size: map.get($font-sizes, $size); // 2rem
}

Q. What are Sass cons and pros?

Pros:

  • Reduces CSS repetition with variables, mixins, and functions
  • Modular architecture via @use / @forward
  • Nesting mirrors HTML structure for readability
  • Built-in color, math, string, and list functions
  • Large community, well-maintained, integrates with most build tools

Cons:

  • Requires compilation — adds a build step
  • Debugging can be complex without source maps
  • Over-nesting creates overly specific and brittle CSS
  • Teammates unfamiliar with Sass need onboarding
  • Global namespace issues (mitigated by @use but older @import still common)

Q. Explain how Mixins is useful?

Mixins let you define reusable groups of CSS declarations with optional parameters. This eliminates duplication and centralizes changes.

@mixin box-shadow($x: 0, $y: 2px, $blur: 6px, $color: rgba(0,0,0,0.2)) {
  -webkit-box-shadow: $x $y $blur $color;
          box-shadow: $x $y $blur $color;
}

.card {
  @include box-shadow();
}

.modal {
  @include box-shadow(0, 4px, 12px, rgba(0,0,0,0.4));
}

Benefits: vendor-prefix management, responsive breakpoints, theming utilities, and any repetitive pattern can be abstracted into a mixin.

Q. What are the similarities between LESS and Sass?

  • Both are CSS preprocessors that extend plain CSS
  • Both support variables, nesting, mixins, and imports
  • Both support arithmetic operations on values
  • Both support functions (color manipulation, math, string)
  • Both compile to standard CSS
  • Both support comments (// and /* */)
  • Both have support in major build tools (webpack, Vite, Gulp)

The main difference is syntax and ecosystem: Sass uses $ for variables and is written in Dart; LESS uses @ for variables and runs on JavaScript.

Q. Explain what is the use of &combinator ?

The & (parent selector) combinator references the current parent selector. It is used to create pseudo-classes, pseudo-elements, modifier classes, and BEM-style naming without repeating the parent selector.

.button {
  background: blue;

  &:hover        { background: darkblue; }   // .button:hover
  &:focus        { outline: 2px solid; }      // .button:focus
  &::before      { content: ""; }             // .button::before
  &--primary     { background: green; }       // .button--primary (BEM modifier)
  &.is-disabled  { opacity: 0.5; }            // .button.is-disabled
}

Q. What is the way to write a placeholder selector in Sass?

A placeholder selector is written with a % prefix. It is never output as a CSS rule on its own — it only generates CSS when another selector extends it with @extend.

%reset-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.nav-list {
  @extend %reset-list;
}

.breadcrumb {
  @extend %reset-list;
}

Compiled CSS:

.nav-list, .breadcrumb {
  margin: 0;
  padding: 0;
  list-style: none;
}

Q. What are number operations in Sass?

Sass supports standard arithmetic operators on numbers: +, -, *, / (via math.div()), and % (modulo). The sass:math module is required for division in modern Sass.

@use "sass:math";

$base: 16px;

.container {
  width: $base * 60;                    // 960px
  padding: math.div($base, 2);          // 8px
  margin: $base + 4px;                  // 20px
  font-size: $base - 2px;               // 14px
  opacity: math.percentage(math.div(3, 4)); // 75%
}

Note: The / operator for division is deprecated in modern Sass. Use math.div() instead.

Q. Explain @if, @else, @for, @include, @at-root, @extend, @error, @debug directives?

Directive Purpose
@if / @else Conditional logic based on expressions
@for Loop a fixed number of times
@include Include a mixin's styles
@at-root Emit rules at the root of the stylesheet, outside the current nesting
@extend Inherit styles from another selector or placeholder
@error Throw a fatal error and stop compilation
@debug Print a debug message to the console during compilation
@use "sass:math";

// @if / @else
@mixin theme-color($theme) {
  @if $theme == dark {
    background: #111;
    color: #fff;
  } @else {
    background: #fff;
    color: #111;
  }
}

// @for
@for $i from 1 through 4 {
  .col-#{$i} { width: math.percentage(math.div($i, 4)); }
}

// @at-root
.parent {
  color: red;
  @at-root .child { color: blue; } // outputs .child { ... } at root level
}

// @error / @debug
@mixin font-size($size) {
  @if type-of($size) != number {
    @error "Expected a number, got #{$size}.";
  }
  @debug "font-size set to #{$size}";
  font-size: $size;
}

Q. Which directive displays an error message in SASS?

The @error directive displays a fatal error message and stops compilation. The @warn directive shows a warning without stopping, and @debug prints a debug value to the console.

@mixin set-color($color) {
  @if type-of($color) != color {
    @error "#{$color} is not a valid color.";
  }
  color: $color;
}

.box {
  @include set-color(notacolor); // Error: notacolor is not a valid color.
}

Q. How many output styles are there in sass?

The Dart Sass compiler (current standard) supports 2 output styles:

Style Description
expanded Default — each property on its own line, human-readable
compressed Minified — all whitespace removed for production

Note: Older Ruby Sass/LibSass supported 4 styles (nested, expanded, compact, compressed), but nested and compact are no longer supported in Dart Sass.

# Dart Sass CLI
sass input.scss output.css --style=expanded
sass input.scss output.css --style=compressed

Q. Which symbol is used to refer parent selector in sass?

The & (ampersand) symbol refers to the parent selector inside a nested rule.

.link {
  color: blue;
  &:hover   { color: darkblue; }  // .link:hover
  &--active { font-weight: bold; } // .link--active (BEM modifier)
}

Compiled CSS:

.link { color: blue; }
.link:hover { color: darkblue; }
.link--active { font-weight: bold; }

Q. What is the difference between @use and @import in Sass?

@use is the modern replacement for @import, introduced in Dart Sass. @import is deprecated and will eventually be removed.

Feature @import (deprecated) @use (modern)
Namespace Global — all variables/mixins pollute global scope Namespaced by filename
Loaded multiple times? Yes — re-executes file each time No — file loaded only once
Private members Not supported Prefix with - or _ to make private
Configuration Not possible Use with keyword
Recommended No Yes

@import (old, deprecated):

// _variables.scss
$primary: #3498db;

// main.scss
@import 'variables';
body { color: $primary; } // direct access — no namespace

@use (modern):

// _variables.scss
$primary: #3498db;
$-secret: #999; // private — not accessible outside

// main.scss
@use 'variables';
body { color: variables.$primary; } // namespaced access

@use with alias:

@use 'variables' as v;
body { color: v.$primary; }

@use with wildcard (use sparingly):

@use 'variables' as *;
body { color: $primary; } // no namespace — like @import

Q. What is @forward in Sass and how does it differ from @use?

@forward loads a Sass file and makes its public members (variables, mixins, functions) available to files that @use the current file. It is used to build a single entry-point index file that re-exports multiple partials.

Rule Purpose
@use Load a module for use within the current file
@forward Re-export a module's members so downstream files can access them
// _colors.scss
$primary: #3498db;
$danger: #e74c3c;

// _typography.scss
$font-base: 1rem;
$font-lg: 1.5rem;

// _index.scss  ← entry point
@forward 'colors';
@forward 'typography';

// main.scss
@use 'index' as tokens;   // gets everything from _index.scss

body {
  color: tokens.$primary;
  font-size: tokens.$font-base;
}

@forward with show / hide:

// Only expose $primary, hide $danger
@forward 'colors' show $primary;

// Hide specific members
@forward 'colors' hide $danger;

@forward with as prefix:

@forward 'colors' as color-*;
// $primary becomes $color-primary for consumers

Q. What is the difference between a Sass @function and a @mixin?

Feature @function @mixin
Returns A value (number, color, string, etc.) A block of CSS declarations
Used with Assigned to a property value @include directive
Purpose Compute and return a value Output reusable styles
@content Not supported Supported

@function — returns a computed value:

@use "sass:math";

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

@function clamp-fluid($min, $max, $min-vw: 320px, $max-vw: 1280px) {
  $slope: math.div($max - $min, $max-vw - $min-vw);
  $intercept: $min - $slope * $min-vw;
  @return clamp(#{$min}, #{$intercept} + #{$slope * 100}vw, #{$max});
}

h1 {
  font-size: rem(32px);          // 2rem
  margin-bottom: rem(24px);      // 1.5rem
}

@mixin — outputs CSS declarations:

@mixin visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  clip: rect(0,0,0,0);
  overflow: hidden;
}

.sr-only { @include visually-hidden; }

Rule of thumb: Use @function when you need a computed value; use @mixin when you need to output multiple CSS properties.

Q. What is the difference between @extend and @mixin? When would you use one over the other?

Feature @extend @mixin
Output Groups selectors (a, b { ... }) Duplicates declarations in each selector
Arguments / parameters Not supported Supported
Works across media queries No — not allowed across different breakpoints Yes
Produces smallest CSS Yes (when used well) No
Recommended for Static shared styles, placeholders Configurable, parameterized patterns

@extend (selectors are grouped):

%btn-base {
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
}

.btn-primary {
  @extend %btn-base;
  background: blue;
}

.btn-danger {
  @extend %btn-base;
  background: red;
}

Compiled CSS:

.btn-primary, .btn-danger { padding: 8px 16px; border-radius: 4px; cursor: pointer; }
.btn-primary { background: blue; }
.btn-danger { background: red; }

@mixin (declarations duplicated but configurable):

@mixin btn($bg) {
  padding: 8px 16px;
  border-radius: 4px;
  background: $bg;
}

.btn-primary { @include btn(blue); }
.btn-danger  { @include btn(red); }

Use @extend / %placeholder for purely static, shared property sets.
Use @mixin whenever you need parameters, @content, or use inside @media blocks.

Q. What are Sass lists and how do you work with them?

A Sass list is an ordered collection of values, separated by spaces or commas. Lists are immutable — functions return new lists rather than modifying the original.

@use "sass:list";

$sizes: 8px 16px 24px 32px;             // space-separated
$breakpoints: (576px, 768px, 992px);    // comma-separated

// list.length()
$count: list.length($sizes);            // 4

// list.nth()
$md: list.nth($sizes, 3);              // 24px (1-based index)

// list.append()
$sizes-extended: list.append($sizes, 48px);

// list.join()
$all: list.join($sizes, $sizes-extended);

// Iterate with @each
@each $size in $sizes {
  .m-#{$size} { margin: $size; }
}

Compiled CSS (from @each):

.m-8px  { margin: 8px; }
.m-16px { margin: 16px; }
.m-24px { margin: 24px; }
.m-32px { margin: 32px; }

Q. Explain @each and @while loop directives in Sass?

@each iterates over a list or map:

// Iterate over a list
$colors: red, green, blue;

@each $color in $colors {
  .text-#{$color} { color: $color; }
}

// Iterate over a map (destructuring)
$icons: ("home": "\f015", "user": "\f007", "gear": "\f013");

@each $name, $code in $icons {
  .icon-#{$name}::before { content: $code; }
}

// Multiple assignment (list of lists)
$sizes: ("sm" 576px), ("md" 768px), ("lg" 992px);

@each $label, $value in $sizes {
  .container-#{$label} { max-width: $value; }
}

@while loops as long as a condition is true (use sparingly — @for or @each is preferred):

@use "sass:math";

$i: 1;
@while $i <= 5 {
  .opacity-#{$i * 10} { opacity: math.div($i, 10); }
  $i: $i + 1;
}

Compiled CSS:

.opacity-10 { opacity: 0.1; }
.opacity-20 { opacity: 0.2; }
/* ... */
.opacity-50 { opacity: 0.5; }

Q. What is the difference between Sass variables and CSS custom properties (CSS variables)?

Feature Sass Variables ($var) CSS Custom Properties (--var)
Resolved at Compile time — static Runtime — dynamic
Available in browser DevTools No — compiled away Yes — inspectable and editable
Can be changed by JavaScript No Yes — element.style.setProperty('--color', 'red')
Scope Sass lexical scope CSS cascade / DOM scope
Works inside calc() Limited Yes — calc(var(--size) * 2)
Supports fallback No Yes — var(--color, red)
Inherited through DOM No Yes
Useful for theming/dark mode No Yes
// Sass variable — resolved at compile time
$primary: #3498db;

.btn { background: $primary; }

// CSS custom property — lives in the browser
:root {
  --primary: #{$primary}; // use #{} to embed Sass value into CSS var
}

.btn-dynamic {
  background: var(--primary);
}

Best practice: Use Sass variables for build-time values (breakpoints, spacing scale, base font size). Use CSS custom properties for runtime theming, dark mode, and values that JavaScript needs to read or modify.

Q. What is variable scope in Sass? What are the !default and !global flags?

Variable scope: Sass variables are lexically scoped. A variable declared inside a rule, mixin, or function is local to that block and not accessible outside it.

$color: red;   // global

.box {
  $color: blue;  // local — shadows global inside this block
  color: $color; // blue
}

p { color: $color; } // red — global unaffected

!global flag: Assigns or modifies a variable in the global scope from inside a local block (use sparingly):

$theme: light;  // global

@mixin set-dark() {
  $theme: dark !global; // modifies the global $theme
}

@include set-dark();
// $theme is now "dark" globally

!default flag: Sets a variable only if it is not already defined or is null. Used in libraries and design-token files so consumers can override defaults before @use:

// _config.scss (library file)
$primary: #3498db !default;
$font-size: 16px  !default;

// main.scss (consumer)
$primary: hotpink;         // override BEFORE @use
@use 'config';

.btn { background: config.$primary; } // hotpink — consumer wins

Q. What are Sass built-in modules? List the main ones and give examples.

Dart Sass ships with built-in modules loaded via @use "sass:<module>":

Module Purpose
sass:math Math functions: math.div(), math.round(), math.pow(), math.percentage()
sass:color Color manipulation: color.adjust(), color.mix(), color.scale(), color.channel()
sass:string String functions: string.quote(), string.slice(), string.length(), string.to-upper-case()
sass:list List functions: list.nth(), list.length(), list.append(), list.join()
sass:map Map functions: map.get(), map.set(), map.merge(), map.keys(), map.values()
sass:selector Selector inspection: selector.parse(), selector.extend()
sass:meta Meta-programming: meta.type-of(), meta.get-function(), meta.call(), meta.load-css()
@use "sass:math";
@use "sass:color";
@use "sass:map";
@use "sass:string";

$palette: ("primary": #3498db, "danger": #e74c3c);

.btn-hover {
  // math
  width: math.percentage(math.div(3, 4));   // 75%

  // color — darken primary by 10%
  background: color.adjust(map.get($palette, "primary"), $lightness: -10%);

  // color.scale() — relative scaling (safer than adjust)
  border-color: color.scale(map.get($palette, "primary"), $saturation: 20%);

  // string
  font-family: string.quote(Helvetica);     // "Helvetica"
}

Q. What are rest/splat arguments (...) in Sass mixins and functions?

Sass supports rest arguments (also called splat arguments) using .... They allow a mixin or function to accept any number of arguments, collected into a list or map.

Rest arguments in mixins:

@mixin transitions($transitions...) {
  transition: $transitions;
}

.box {
  // Pass multiple transitions
  @include transitions(color 0.3s ease, background 0.5s linear, opacity 0.2s);
}

Compiled CSS:

.box {
  transition: color 0.3s ease, background 0.5s linear, opacity 0.2s;
}

Splat operator when calling — expand a list/map into arguments:

@mixin box-shadow($x, $y, $blur, $color) {
  box-shadow: $x $y $blur $color;
}

$args: 0px 4px 8px rgba(0,0,0,0.3);

.card {
  @include box-shadow($args...); // expands list into positional args
}

Keyword splat from a map:

$kwargs: ("x": 0, "y": 2px, "blur": 6px, "color": rgba(0,0,0,0.2));

.card {
  @include box-shadow($kwargs...); // map keys map to parameter names
}

Q. How do you implement a theming system using SCSS?

A scalable theming approach uses CSS custom properties (runtime) defined from Sass maps (build-time), combined with a theme mixin or data attribute selector.

// _tokens.scss
$themes: (
  "light": (
    "bg":      #ffffff,
    "text":    #111111,
    "primary": #3498db,
    "surface": #f5f5f5,
  ),
  "dark": (
    "bg":      #111111,
    "text":    #f5f5f5,
    "primary": #64b5f6,
    "surface": #1e1e1e,
  ),
);

// _theme.scss
@use 'tokens';
@use 'sass:map';

@mixin define-theme($theme-map) {
  @each $token, $value in $theme-map {
    --#{$token}: #{$value};
  }
}

:root {
  @include define-theme(map.get(tokens.$themes, "light"));
}

[data-theme="dark"] {
  @include define-theme(map.get(tokens.$themes, "dark"));
}

// Component usage
.card {
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--primary);
}

Switching theme with JavaScript:

document.documentElement.setAttribute('data-theme', 'dark');

Q. What is BEM methodology and how does SCSS support it?

BEM (Block, Element, Modifier) is a CSS naming convention that produces flat, predictable, and collision-free class names.

  • Block — standalone component: .card
  • Element — part of a block: .card__title, .card__image
  • Modifier — variant of a block or element: .card--featured, .card__title--large

SCSS's & (parent selector) makes BEM clean to write without repeating the block name:

.card {
  padding: 16px;
  border: 1px solid #ddd;
  border-radius: 8px;

  // Elements
  &__image {
    width: 100%;
    object-fit: cover;
  }

  &__title {
    font-size: 1.25rem;
    margin: 0 0 8px;

    // Element modifier
    &--large { font-size: 1.75rem; }
  }

  &__body {
    font-size: 0.875rem;
    color: #555;
  }

  // Block modifiers
  &--featured {
    border-color: #3498db;
    box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  }

  &--compact {
    padding: 8px;
  }
}

Compiled CSS selectors:

.card { }
.card__image { }
.card__title { }
.card__title--large { }
.card__body { }
.card--featured { }
.card--compact { }

Avoid deeply nesting BEM inside SCSS — keep it one level of nesting inside the Block.

Q. How do you create a responsive breakpoint mixin system in SCSS?

A breakpoint mixin wraps @media queries so breakpoints are defined once in a map and reused consistently throughout the codebase.

// _breakpoints.scss
$breakpoints: (
  "xs": 0,
  "sm": 576px,
  "md": 768px,
  "lg": 992px,
  "xl": 1200px,
  "xxl": 1400px,
);

@use "sass:map";

// Mobile-first (min-width)
@mixin bp-up($name) {
  $value: map.get($breakpoints, $name);
  @if $value == null {
    @error "Breakpoint `#{$name}` not found. Available: #{map.keys($breakpoints)}";
  }
  @if $value == 0 {
    @content; // xs — no media query needed
  } @else {
    @media (min-width: $value) { @content; }
  }
}

// Desktop-first (max-width)
@mixin bp-down($name) {
  $value: map.get($breakpoints, $name);
  @media (max-width: ($value - 0.02px)) { @content; }
}

// Between two breakpoints
@mixin bp-between($lower, $upper) {
  $min: map.get($breakpoints, $lower);
  $max: map.get($breakpoints, $upper);
  @media (min-width: $min) and (max-width: ($max - 0.02px)) { @content; }
}

Usage:

@use 'breakpoints' as *;

.container {
  padding: 16px;

  @include bp-up("md") { padding: 24px; }
  @include bp-up("xl") { padding: 32px; }
}

.sidebar {
  display: none;
  @include bp-up("lg") { display: block; width: 280px; }
}

Q. How do you configure Sass with webpack (sass-loader) and Vite?

webpack with sass-loader:

npm install --save-dev sass sass-loader css-loader style-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          'style-loader',   // 3. inject styles into DOM
          'css-loader',     // 2. resolve @use / @forward imports
          {
            loader: 'sass-loader',  // 1. compile SCSS → CSS
            options: {
              sassOptions: {
                style: 'compressed',     // output style
                loadPaths: ['src/styles'], // resolve paths
              },
            },
          },
        ],
      },
    ],
  },
};

Vite (built-in SCSS support):

npm install --save-dev sass
// vite.config.js
export default {
  css: {
    preprocessorOptions: {
      scss: {
        // Automatically import tokens into every file
        additionalData: `@use "@/styles/tokens" as *;`,
        style: 'compressed',
      },
    },
  },
};

Usage in a component (React/Vue):

import './Button.scss';           // plain import
import styles from './Card.module.scss'; // CSS Modules

In Vite, Sass is processed automatically for any .scss file — no extra plugin required.