Sass — Rules and Conventions
1. Philosophy
- Dart Sass only — Reference implementation. Node Sass deprecated.
- SCSS syntax — CSS-compatible. No indented syntax.
- @use over @import — Modules with namespaces. No global namespace pollution.
- Variables for tokens — Colors, spacing, radii, fonts as variables.
- Mixins for patterns — Reusable style blocks with arguments.
2. Minimum Version
| Technology |
Minimum Version |
| Dart Sass |
1.70+ |
| Node.js |
22+ |
| pnpm |
11+ |
3. Installation
pnpm add -D sass
package.json scripts
{
"scripts": {
"sass:build": "sass src/styles:dist/styles --style=compressed --no-source-map",
"sass:watch": "sass src/styles:dist/styles --watch"
}
}
4. Syntax (SCSS)
// Variables
$primary: #0066cc;
$spacing: 1rem;
// Nesting
.card {
padding: $spacing;
&:hover {
background: lighten($primary, 20%);
}
.title {
font-weight: 600;
}
}
// Partials (imported via @use)
@use "variables";
@use "mixins";
5. Variables
// Global (with !default for overrides)
$primary: #0066cc !default;
$font-stack: "Inter", system-ui, sans-serif !default;
$breakpoints: (
"sm": 576px,
"md": 768px,
"lg": 992px,
"xl": 1200px,
"xxl": 1400px,
) !default;
// Scoped (in module)
@use "config" as *;
$local-var: 1rem; // Only in this file
Rules
!default on all config variables — allows overriding
- Descriptive names —
$primary not $blue
- Maps for related values — breakpoints, colors, shadows
6. Nesting
// Selector nesting
.nav {
display: flex;
&-item {
padding: 0.5rem 1rem;
}
&-link {
color: $primary;
&:hover {
color: darken($primary, 10%);
}
}
}
// Property nesting
.border {
border: {
style: solid;
width: 1px;
color: $gray-300;
}
}
// Media queries
.component {
@media (min-width: 768px) {
display: grid;
}
}
Rules Nesting
- Max 3 levels deep — avoid overly specific selectors
& for parent reference — required for pseudo-classes, modifiers
- Media queries inside component — keeps related styles together
7. Mixins & @include
// Basic mixin
@mixin flex-center {
display: flex;
justify-content: center;
align-items: center;
}
// With arguments
@mixin button-variant($bg, $color: white) {
background: $bg;
color: $color;
border: none;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
&:hover {
background: darken($bg, 10%);
}
}
// With content block
@mixin media-query($breakpoint) {
@media (min-width: $breakpoint) {
@content;
}
}
// Usage
.btn-primary {
@include button-variant($primary);
}
.card {
@include media-query(768px) {
padding: 2rem;
}
}
Rules Mixins
- Prefix with category —
button-variant, media-query, visually-hidden
- Default arguments — flexible without required params
@content for blocks — enables wrapper patterns
8. Modules (@use / @forward)
@use (import with namespace)
// styles/main.scss
@use "variables" as *; // No namespace (globals)
@use "mixins" as mx; // mx.flex-center()
@use "functions" as fn; // fn.rem(16)
@use "bootstrap/scss/bootstrap" as bs with (
$primary: #0066cc
);
@forward (re-export)
// _index.scss (barrel file)
@forward "variables";
@forward "mixins";
@forward "functions";
// main.scss
@use "abstracts" as *; // Gets all forwarded members
Rules Modules
@use once per file — cached, no duplicate CSS
as * sparingly — only for true globals (variables)
@forward for public API — hide implementation partials
with ($var: value) — configure upstream modules
9. Functions (Essential)
// Rem conversion
@function rem($px, $base: 16px) {
@return ($px / $base) * 1rem;
}
// Fluid type (clamp)
@function fluid($min, $max, $vw: 1vw) {
@return clamp($min, $vw, $max);
}
// Color manipulation
@function theme-color($name) {
@return map-get($theme-colors, $name);
}
Built-in functions (use instead of custom)
| Category |
Functions |
| Color |
lighten, darken, mix, adjust-hue, saturate, desaturate, grayscale, complement, invert, alpha, opacity |
| Math |
percentage, round, ceil, floor, abs, min, max, random, unit, unitless, comparable |
| String |
quote, unquote, to-upper-case, to-lower-case, str-length, str-slice, str-insert, str-index |
| List/Map |
length, nth, set-nth, join, append, zip, index, map-get, map-set, map-merge, map-remove, map-keys, map-values, map-has-key |
| Selector |
selector-nest, selector-append, selector-extend, selector-replace, selector-unify, is-superselector, simple-selectors |
10. Maps & Lists (Essential)
// Map
$theme-colors: (
"primary": #0066cc,
"secondary": #6c757d,
"success": #198754,
);
// Iterate
@each $name, $color in $theme-colors {
.btn-#{$name} {
@include button-variant($color);
}
}
// Get value
$primary: map-get($theme-colors, "primary");
// Merge (config + defaults)
$final-config: map-merge($defaults, $user-config);
Rules Maps & Lists
- Maps for related values — colors, breakpoints, shadows, z-indices
map-merge for config — user overrides defaults
@each for generation — DRY component variants
11. Built-in Modules (Essential)
@use "sass:color";
@use "sass:map";
@use "sass:math";
@use "sass:string";
@use "sass:list";
@use "sass:selector";
@use "sass:meta";
Common patterns
// Color palette generation
@use "sass:color";
$base: #0066cc;
$palette: (
"50": color.scale($base, $lightness: 40%),
"100": color.scale($base, $lightness: 30%),
"500": $base,
"900": color.scale($base, $lightness: -30%),
);
// Math helpers
@use "sass:math";
$cols: 12;
$gutter: 1.5rem;
$col-width: math.div(100% - ($gutter * ($cols - 1)), $cols);
12. Project Architecture (7-1 Pattern)
styles/
├── main.scss # Entry point
├── abstracts/
│ ├── _index.scss # @forward all
│ ├── _variables.scss # Tokens
│ ├── _mixins.scss # Reusable patterns
│ └── _functions.scss # Helpers
├── base/
│ ├── _reset.scss # Normalize/Reset
│ ├── _typography.scss # Base type styles
│ └── _global.scss # html, body, *
├── components/
│ ├── _index.scss
│ ├── _button.scss
│ ├── _card.scss
│ └── _form.scss
├── layout/
│ ├── _index.scss
│ ├── _header.scss
│ ├── _footer.scss
│ └── _grid.scss
├── pages/
│ ├── _index.scss
│ └── _home.scss
├── themes/
│ ├── _index.scss
│ └── _dark.scss
└── vendors/
└── _bootstrap.scss # @use bootstrap with config
main.scss
// 1. Abstracts (tokens, mixins, functions)
@use "abstracts" as *;
// 2. Vendors (3rd party with config)
@use "vendors/bootstrap" as bs;
// 3. Base (global styles)
@use "base/reset";
@use "base/typography";
@use "base/global";
// 4. Layout (macro structure)
@use "layout/header";
@use "layout/footer";
@use "layout/grid";
// 5. Components (micro UI)
@use "components/button";
@use "components/card";
@use "components/form";
// 6. Pages (specific overrides)
@use "pages/home";
// 7. Themes (last — overrides)
@use "themes/dark";
Rules Architecture
- Order matters — abstracts → vendors → base → layout
→ components → pages → themes
- One
@use per partial — clear dependency graph
- Themes last — override variables for dark mode, brand variants
13. Framework Integration
Vite
pnpm add -D sass
// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig({
css: {
preprocessorOptions: {
scss: {
api: "modern-compiler", // Dart Sass modern API
silenceDeprecations: ["import", "global-builtin"],
},
},
},
});
Astro
pnpm astro add sass
# or
pnpm add -D sass
<!-- Component.astro -->
<style lang="scss">
@use "styles/abstracts" as *;
.component { @include flex-center; }
</style>
Vite/Astro config details: see vite and astro skills.
14. Methodology
Before using ANY Sass feature/pattern not documented in
this skill:
- MCP Context7 (priority):
context7_resolve-library-id +
context7_query-docs for Sass.
- Official docs: sass-lang.com — verify current syntax + modules.
- Project config:
styles/main.scss, vite.config.ts,
package.json — verify against actual setup.
- HARD RULE: If not in this skill AND cannot be verified against
2 authoritative sources → DO NOT USE IT. Document as assumption or risk in
report to orchestrator.
15. Prohibitions
- ❌ Do not use
@import — use @use / @forward (modules)
- ❌ Do not use indented syntax (
.sass) — SCSS only
- ❌ Do not use
@extend / placeholders (%) — use mixins
- ❌ Do not nest deeper than 3 levels
- ❌ Do not use global variables without
!default
- ❌ Do not use
!global flag — use module system
- ❌ Do not duplicate CSS values — use variables/maps
- ❌ Do not commit compiled CSS — build in CI
16. References
Note: For CSS conventions, see CSS
Note: For Vite integration, see Vite
Note: For Astro integration, see
Astro
Last updated: 2026-08
1---2name: sass3description: Sass (Dart Sass) rules - SCSS syntax, variables, mixins, partials, @use/@forward, modules, 7-1 architecture, framework integration4---56# Sass — Rules and Conventions78---910## 1. Philosophy11121. **Dart Sass only** — Reference implementation. Node Sass deprecated.132. **SCSS syntax** — CSS-compatible. No indented syntax.143. **@use over @import** — Modules with namespaces. No global namespace pollution.154. **Variables for tokens** — Colors, spacing, radii, fonts as variables.165. **Mixins for patterns** — Reusable style blocks with arguments.1718---1920## 2. Minimum Version2122| Technology | Minimum Version |23| ---------- | --------------- |24| Dart Sass | 1.70+ |25| Node.js | 22+ |26| pnpm | 11+ |2728---2930## 3. Installation3132```bash33pnpm add -D sass34```3536### package.json scripts3738```json39{40 "scripts": {41 "sass:build": "sass src/styles:dist/styles --style=compressed --no-source-map",42 "sass:watch": "sass src/styles:dist/styles --watch"43 }44}45```4647---4849## 4. Syntax (SCSS)5051```scss52// Variables53$primary: #0066cc;54$spacing: 1rem;5556// Nesting57.card {58 padding: $spacing;59 &:hover {60 background: lighten($primary, 20%);61 }62 .title {63 font-weight: 600;64 }65}6667// Partials (imported via @use)68@use "variables";69@use "mixins";70```7172---7374## 5. Variables7576```scss77// Global (with !default for overrides)78$primary: #0066cc !default;79$font-stack: "Inter", system-ui, sans-serif !default;80$breakpoints: (81 "sm": 576px,82 "md": 768px,83 "lg": 992px,84 "xl": 1200px,85 "xxl": 1400px,86) !default;8788// Scoped (in module)89@use "config" as *;90$local-var: 1rem; // Only in this file91```9293### Rules9495- **`!default`** on all config variables — allows overriding96- **Descriptive names** — `$primary` not `$blue`97- **Maps for related values** — breakpoints, colors, shadows9899---100101## 6. Nesting102103```scss104// Selector nesting105.nav {106 display: flex;107 &-item {108 padding: 0.5rem 1rem;109 }110 &-link {111 color: $primary;112 &:hover {113 color: darken($primary, 10%);114 }115 }116}117118// Property nesting119.border {120 border: {121 style: solid;122 width: 1px;123 color: $gray-300;124 }125}126127// Media queries128.component {129 @media (min-width: 768px) {130 display: grid;131 }132}133```134135### Rules Nesting136137- **Max 3 levels deep** — avoid overly specific selectors138- **`&` for parent reference** — required for pseudo-classes, modifiers139- **Media queries inside component** — keeps related styles together140141---142143## 7. Mixins & @include144145```scss146// Basic mixin147@mixin flex-center {148 display: flex;149 justify-content: center;150 align-items: center;151}152153// With arguments154@mixin button-variant($bg, $color: white) {155 background: $bg;156 color: $color;157 border: none;158 padding: 0.5rem 1rem;159 border-radius: 0.375rem;160 &:hover {161 background: darken($bg, 10%);162 }163}164165// With content block166@mixin media-query($breakpoint) {167 @media (min-width: $breakpoint) {168 @content;169 }170}171172// Usage173.btn-primary {174 @include button-variant($primary);175}176177.card {178 @include media-query(768px) {179 padding: 2rem;180 }181}182```183184### Rules Mixins185186- **Prefix with category** — `button-variant`, `media-query`, `visually-hidden`187- **Default arguments** — flexible without required params188- **`@content` for blocks** — enables wrapper patterns189190---191192## 8. Modules (@use / @forward)193194### @use (import with namespace)195196```scss197// styles/main.scss198@use "variables" as *; // No namespace (globals)199@use "mixins" as mx; // mx.flex-center()200@use "functions" as fn; // fn.rem(16)201@use "bootstrap/scss/bootstrap" as bs with (202 $primary: #0066cc203);204```205206### @forward (re-export)207208```scss209// _index.scss (barrel file)210@forward "variables";211@forward "mixins";212@forward "functions";213214// main.scss215@use "abstracts" as *; // Gets all forwarded members216```217218### Rules Modules219220- **`@use` once per file** — cached, no duplicate CSS221- **`as *` sparingly** — only for true globals (variables)222- **`@forward` for public API** — hide implementation partials223- **`with ($var: value)`** — configure upstream modules224225---226227## 9. Functions (Essential)228229```scss230// Rem conversion231@function rem($px, $base: 16px) {232 @return ($px / $base) * 1rem;233}234235// Fluid type (clamp)236@function fluid($min, $max, $vw: 1vw) {237 @return clamp($min, $vw, $max);238}239240// Color manipulation241@function theme-color($name) {242 @return map-get($theme-colors, $name);243}244```245246### Built-in functions (use instead of custom)247248| Category | Functions |249| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |250| **Color** | `lighten`, `darken`, `mix`, `adjust-hue`, `saturate`, `desaturate`, `grayscale`, `complement`, `invert`, `alpha`, `opacity` |251| **Math** | `percentage`, `round`, `ceil`, `floor`, `abs`, `min`, `max`, `random`, `unit`, `unitless`, `comparable` |252| **String** | `quote`, `unquote`, `to-upper-case`, `to-lower-case`, `str-length`, `str-slice`, `str-insert`, `str-index` |253| **List/Map** | `length`, `nth`, `set-nth`, `join`, `append`, `zip`, `index`, `map-get`, `map-set`, `map-merge`, `map-remove`, `map-keys`, `map-values`, `map-has-key` |254| **Selector** | `selector-nest`, `selector-append`, `selector-extend`, `selector-replace`, `selector-unify`, `is-superselector`, `simple-selectors` |255256---257258## 10. Maps & Lists (Essential)259260```scss261// Map262$theme-colors: (263 "primary": #0066cc,264 "secondary": #6c757d,265 "success": #198754,266);267268// Iterate269@each $name, $color in $theme-colors {270 .btn-#{$name} {271 @include button-variant($color);272 }273}274275// Get value276$primary: map-get($theme-colors, "primary");277278// Merge (config + defaults)279$final-config: map-merge($defaults, $user-config);280```281282### Rules Maps & Lists283284- **Maps for related values** — colors, breakpoints, shadows, z-indices285- **`map-merge` for config** — user overrides defaults286- **`@each` for generation** — DRY component variants287288---289290## 11. Built-in Modules (Essential)291292```scss293@use "sass:color";294@use "sass:map";295@use "sass:math";296@use "sass:string";297@use "sass:list";298@use "sass:selector";299@use "sass:meta";300```301302### Common patterns303304```scss305// Color palette generation306@use "sass:color";307308$base: #0066cc;309$palette: (310 "50": color.scale($base, $lightness: 40%),311 "100": color.scale($base, $lightness: 30%),312 "500": $base,313 "900": color.scale($base, $lightness: -30%),314);315316// Math helpers317@use "sass:math";318$cols: 12;319$gutter: 1.5rem;320$col-width: math.div(100% - ($gutter * ($cols - 1)), $cols);321```322323---324325## 12. Project Architecture (7-1 Pattern)326327```text328styles/329├── main.scss # Entry point330├── abstracts/331│ ├── _index.scss # @forward all332│ ├── _variables.scss # Tokens333│ ├── _mixins.scss # Reusable patterns334│ └── _functions.scss # Helpers335├── base/336│ ├── _reset.scss # Normalize/Reset337│ ├── _typography.scss # Base type styles338│ └── _global.scss # html, body, *339├── components/340│ ├── _index.scss341│ ├── _button.scss342│ ├── _card.scss343│ └── _form.scss344├── layout/345│ ├── _index.scss346│ ├── _header.scss347│ ├── _footer.scss348│ └── _grid.scss349├── pages/350│ ├── _index.scss351│ └── _home.scss352├── themes/353│ ├── _index.scss354│ └── _dark.scss355└── vendors/356 └── _bootstrap.scss # @use bootstrap with config357```358359### main.scss360361```scss362// 1. Abstracts (tokens, mixins, functions)363@use "abstracts" as *;364365// 2. Vendors (3rd party with config)366@use "vendors/bootstrap" as bs;367368// 3. Base (global styles)369@use "base/reset";370@use "base/typography";371@use "base/global";372373// 4. Layout (macro structure)374@use "layout/header";375@use "layout/footer";376@use "layout/grid";377378// 5. Components (micro UI)379@use "components/button";380@use "components/card";381@use "components/form";382383// 6. Pages (specific overrides)384@use "pages/home";385386// 7. Themes (last — overrides)387@use "themes/dark";388```389390### Rules Architecture391392- **Order matters** — abstracts → vendors → base → layout393 → components → pages → themes394- **One `@use` per partial** — clear dependency graph395- **Themes last** — override variables for dark mode, brand variants396397---398399## 13. Framework Integration400401### Vite402403```bash404pnpm add -D sass405```406407```ts408// vite.config.ts409import { defineConfig } from "vite";410411export default defineConfig({412 css: {413 preprocessorOptions: {414 scss: {415 api: "modern-compiler", // Dart Sass modern API416 silenceDeprecations: ["import", "global-builtin"],417 },418 },419 },420});421```422423### Astro424425```bash426pnpm astro add sass427# or428pnpm add -D sass429```430431```astro432<!-- Component.astro -->433<style lang="scss">434 @use "styles/abstracts" as *;435 .component { @include flex-center; }436</style>437```438439> **Vite/Astro config details**: see `vite` and `astro` skills.440441---442443## 14. Methodology444445Before using ANY Sass feature/pattern not documented in446this skill:4474481. **MCP Context7** (priority): `context7_resolve-library-id` +449 `context7_query-docs` for Sass.4502. **Official docs**: sass-lang.com — verify current syntax + modules.4513. **Project config**: `styles/main.scss`, `vite.config.ts`,452 `package.json` — verify against actual setup.4534. **HARD RULE**: If not in this skill AND cannot be verified against454 2 authoritative sources → DO NOT USE IT. Document as assumption or risk in455 report to orchestrator.456457---458459## 15. Prohibitions460461- ❌ Do not use `@import` — use `@use` / `@forward` (modules)462- ❌ Do not use indented syntax (`.sass`) — SCSS only463- ❌ Do not use `@extend` / placeholders (`%`) — use mixins464- ❌ Do not nest deeper than 3 levels465- ❌ Do not use global variables without `!default`466- ❌ Do not use `!global` flag — use module system467- ❌ Do not duplicate CSS values — use variables/maps468- ❌ Do not commit compiled CSS — build in CI469470---471472## 16. References473474> **Note:** For CSS conventions, see [CSS](../css/SKILL.md)475> **Note:** For Vite integration, see [Vite](../vite/SKILL.md)476> **Note:** For Astro integration, see477> [Astro](../astro/SKILL.md)478479---480481Last updated: 2026-08