Chapter 15: Sass Introspection
Sass: Introspection Functions — almost all of them live in the sass:meta module.
This is the part where Sass lets you “look inside itself” — inspect what variables, functions, mixins exist, get references to them, call functions dynamically, load CSS conditionally, check types, and more.
It’s like giving Sass reflection capabilities (in programming terms). You rarely need it for everyday styling, but it’s invaluable when:
- Building reusable libraries / design systems / frameworks
- Writing generic utilities that adapt to what’s available
- Creating dynamic theming or plugin-like behavior
- Debugging large codebases
- Doing advanced meta-programming (passing functions/mixins around)
In 2026 (Dart Sass 1.97+), everything is loaded via @use ‘sass:meta’; — no more old globals.
1. Loading the Module (Always!)
|
0 1 2 3 4 5 6 7 |
@use 'sass:meta' as meta; // 'meta' alias is very common // or @use 'sass:meta'; → meta.get-function(...) |
2. The Most Important sass:meta Functions (2026 Practical List)
Here are the ones you’ll actually use or see in real code.
A. meta.get-function($name, $css: false, $module: null)
→ Returns a function value reference (so you can pass it around and call it later with meta.call())
This is huge for higher-order functions.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
@use 'sass:meta' as meta; @use 'sass:string' as str; @function apply-to-each($list, $fn-ref) { $result: (); @each $item in $list { $result: list.append($result, meta.call($fn-ref, $item)); } @return $result; } @function add-exclamation($str) { @return $str + "!"; } $phrases: "Hello" "Sass" "Rocks"; @debug apply-to-each($phrases, meta.get-function("add-exclamation")); // ("Hello!", "Sass!", "Rocks!") |
Real usage pattern – filter with custom predicate:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
@function contains-helvetica($font) { @return string.index($font, "Helvetica") != null; } $fonts: "Arial" "Helvetica Neue" "Georgia" "Helvetica"; $helvetica-fonts: apply-to-each($fonts, meta.get-function("contains-helvetica")); // → list of fonts that contain "Helvetica" |
B. meta.call($function, $args…)
→ Invokes a function reference returned by get-function()
See example above — it’s the counterpart to get-function().
C. meta.keywords($args)
→ When a mixin/function receives variable arguments ($args…), this returns a map of the keyword arguments passed.
Super useful for flexible mixins.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
@use 'sass:meta' as meta; @mixin syntax-highlight($args...) { @debug meta.keywords($args); // (string: #080, comment: #800, variable: #60b) code.string { color: map.get(meta.keywords($args), "string"); } code.comment { color: map.get(meta.keywords($args), "comment"); } // ... } @include syntax-highlight( $string: #008000, $comment: #800000, $variable: #6060b0 ); |
Use case: Create very flexible utility mixins (like theme-colors(…), spacing(…)).
D. meta.inspect($value)
→ Returns a debug string representation of any Sass value (map, list, function, color, etc.)
Great for @debug logging.
|
0 1 2 3 4 5 6 7 8 9 10 |
@debug meta.inspect( (a: 1, b: 2px) ); // → (a: 1, b: 2px) @debug meta.inspect(meta.get-function("darken")); // → get-function("darken") |
Use case: Debugging complex data structures during development.
E. meta.module-functions($module-namespace)
→ Returns a map of all functions in a loaded module (name → function value)
|
0 1 2 3 4 5 6 7 8 9 10 |
@use 'sass:meta' as meta; @use 'sass:math' as m; @debug meta.module-functions("math"); // → ("abs": get-function("abs"), "ceil": ..., "clamp": ..., ...) |
Use case: Auto-generate documentation, test suites, or dynamic dispatch.
F. meta.module-variables($module-namespace)
→ Map of all variables exported from a module
|
0 1 2 3 4 5 6 7 8 9 10 |
@use 'sass:meta' as meta; @use 'themes' as th; @debug meta.module-variables("th"); // → ("light": (...), "dark": (...), "primary": #6c5ce7, ...) |
Use case: Theme inspection, auto-generate CSS variables from Sass maps.
G. meta.accepts-content($mixin-ref)
→ true if the mixin can accept @content block
|
0 1 2 3 4 5 6 |
@debug meta.accepts-content(meta.get-mixin("media-query")); // true or false |
Use case: Write generic wrapper mixins that conditionally use @content.
H. meta.get-mixin($name, $module: null)
→ Similar to get-function, but for mixins (returns mixin value)
Rarely used directly, but exists for symmetry.
I. meta.load-css($url, $with: ())
→ Dynamically loads and includes CSS from another file (with optional variable overrides)
Very powerful for component libraries.
|
0 1 2 3 4 5 6 7 8 9 10 |
@use 'sass:meta' as meta; .component { @include meta.load-css("path/to/third-party-reset.css"); } |
Or with overrides:
|
0 1 2 3 4 5 6 7 8 9 |
@include meta.load-css("buttons.scss" with ( $btn-padding: 1rem 2rem, $btn-radius: 999px )); |
Use case: Scoped third-party CSS, lazy-loading styles, modular components.
3. Quick Summary Table – When to Reach for sass:meta
| You want to… | Use this | Typical Context |
|---|---|---|
| Pass a function/mixin to another function | get-function(), call() | Higher-order utilities |
| Access keyword args in … mixin | keywords() | Flexible APIs |
| Debug complex values nicely | inspect() | Development |
| List all functions/variables in a module | module-functions(), module-variables() | Library introspection |
| Load CSS dynamically with overrides | load-css() | Component systems |
| Check if mixin accepts @content | accepts-content() | Generic wrappers |
4. Gotchas & 2026 Notes
- sass:meta is Dart Sass only (not LibSass/Ruby Sass — but nobody uses those anymore)
- Function/mixin references cannot be stored in variables/maps/lists directly in some older versions — but fully supported now
- load-css() outputs CSS only (no variables/mixins leak out unless you @forward)
- Avoid overusing — introspection is powerful but makes code harder to follow
- Deprecations: old feature-exists(), plain string call() — use module style
You’ve now unlocked the introspection layer of Sass — this is where library authors live!
Next — want to combine sass:meta + sass:selector + maps to build a really dynamic component factory? Or start putting together a small modular project structure using everything we’ve learned (variables → maps → mixins → functions → meta)?
Just tell me — we’re at expert level now! 🚀
