Sass meta.feature-exists() Function

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
Deprecated
sass:meta · remove in 2.0

What You’ll Learn

meta.feature-exists() belongs to the built-in sass:meta module. It once answered “does this compiler support feature X?” This page explains the recognized feature strings, why the API is deprecated, what to use instead, and five examples so you can read and remove legacy code safely.

01

Concept

Legacy feature flags

02

Status

Deprecated API

03

Module

@use "sass:meta"

04

Returns

true / false

05

Migrate

Delete or replace

06

Practice

5 examples

What Is meta.feature-exists()?

Years ago, Sass implementations differed. Authors used feature-exists("at-error") (and similar checks) to branch stylesheets for older compilers. Official docs: the function returns whether the current implementation supports $feature.

Today Dart Sass is the only officially supported implementation, and it already supports every feature this helper knows about. The Sass team therefore deprecated the function: keeping the checks no longer helps, and the API will disappear in 2.0.

💡
Beginner tip

Treat this page as a migration guide. Learn the old API so you can delete it, not so you add it to new projects.

📝 Syntax

styles.scss
@use "sass:meta";

// Deprecated — avoid in new code
meta.feature-exists($feature)

// Legacy global name (also deprecated)
feature-exists($feature)

Parameters

ParameterTypeRequiredDescription
$featureStringYesFeature name to query. Must be a string. Unrecognized names return false.

Return value

TypeResult
Booleantrue if the named feature is recognized and supported; otherwise false

📚 Recognized Feature Names

Official docs list these strings (and return false for anything else):

Feature stringMeaning
"global-variable-shadowing"A local variable shadows a global unless it uses !global.
"extend-selector-pseudoclass"@extend affects selectors nested in pseudo-classes like :not().
"units-level3"Unit arithmetic supports CSS Values and Units Level 3 units.
"at-error"The @error rule is supported.
"custom-property"Custom property values do not evaluate Sass expressions except via interpolation.

📦 Loading sass:meta

styles.scss
// Namespaced (still deprecated)
@use "sass:meta";
$ok: meta.feature-exists("at-error");

// as * (still deprecated)
@use "sass:meta" as *;
$ok: feature-exists("at-error");

// Legacy global (still deprecated)
$ok: feature-exists("at-error");

⏳ Deprecation Timeline

StageWhat happens
Dart Sass < 1.78Function works; no feature-exists deprecation warning yet.
Dart Sass 1.78+Usages warn (deprecation id: feature-exists).
Dart Sass 2.0meta.feature-exists() throws; global feature-exists() becomes a plain CSS call.

On newer Dart Sass CLIs you can silence this specific warning temporarily with --silence-deprecation=feature-exists, but removing the calls is the real fix.

🚀 What To Use Instead

Old patternModern approach
@if meta.feature-exists("at-error") { … }Delete the @if—always take the modern branch on Dart Sass.
Detect a built-in functionmeta.function-exists("name", $module: "math")
Detect a mixinmeta.mixin-exists("name")
Detect a global variablemeta.global-variable-exists("name")
First-class calc supportExpression checks such as calc(1) == 1 (per breaking-change docs)

🛠 Compatibility

This is about Sass compilers, not browsers. Feature detection runs at compile time.

Implementationfeature-exists
Dart Sass < 1.78Works (legacy)
Dart Sass 1.78+Works with deprecation warnings
Dart Sass 2.0+Removed / broken by design
LibSass / Ruby SassLegacy only—prefer migrating off both

⚡ Quick Reference

GoalCode / action
Old check (avoid)meta.feature-exists("at-error")
Best migrationDelete the check; keep modern CSS/SCSS only
Member detectionmeta.function-exists / mixin-exists / global-variable-exists
Silence warning (temporary)--silence-deprecation=feature-exists
Official notesBreaking change: feature-exists

Examples Gallery

These examples show how the deprecated API behaved so you can recognize it in old code. Prefer deleting these patterns in real projects. Open View Compiled CSS for verified output.

📚 Getting Started

Official-style checks and the full recognized catalog.

Example 1 — Basic True / False (Official Pattern)

Known feature vs unrecognized name, exposed as custom properties.

styles.scss
@use "sass:meta";

// Deprecated — for learning / migration only
.root {
  --at-error: #{meta.feature-exists("at-error")};
  --unrecognized: #{meta.feature-exists("unrecognized")};
}

How It Works

Matches the official docs: "at-error" is recognized (true); "unrecognized" is not (false).

Example 2 — All Recognized Feature Strings

Snapshot every documented feature name into CSS variables.

styles.scss
@use "sass:meta";

.features {
  --global-variable-shadowing: #{meta.feature-exists("global-variable-shadowing")};
  --extend-selector-pseudoclass: #{meta.feature-exists("extend-selector-pseudoclass")};
  --units-level3: #{meta.feature-exists("units-level3")};
  --at-error: #{meta.feature-exists("at-error")};
  --custom-property: #{meta.feature-exists("custom-property")};
}

How It Works

Most documented strings return true on modern Dart Sass. A value of false (as with units-level3 here) still shows why relying on this catalog is brittle—official guidance is to delete these checks rather than trust the flags.

📈 Legacy Patterns & Migration

Old branching, the preferred rewrite, and unknown names.

Example 3 — Legacy @if Branch (Avoid)

How older libraries gated styles on at-error support.

styles.scss
@use "sass:meta";

@mixin assert-positive($n) {
  @if meta.feature-exists("at-error") {
    @if $n <= 0 {
      @error "#{$n} must be positive";
    }
  }
  width: $n;
}

.ok {
  @include assert-positive(40px);
}

How It Works

The outer feature-exists check is redundant on Dart Sass. Prefer a plain @error without wrapping it in feature detection.

Example 4 — Preferred Migration

Same intent without feature-exists: always use modern Sass.

styles.scss
@use "sass:meta";
@use "sass:math";

// Prefer member detection (or no check at all) instead of feature-exists
@mixin power-width($base, $exp) {
  @if meta.function-exists("pow", $module: "math") {
    width: math.pow($base, $exp) * 1px;
  } @else {
    width: $base * $exp * 1px; // very old fallback — rarely needed now
  }
}

.box {
  @include power-width(2, 4);
}

How It Works

meta.function-exists targets a real member. Even better for most apps: call math.pow directly and drop the fallback branch entirely.

Example 5 — Unknown Names Always Return False

Typos and invented feature strings do not throw—they return false.

styles.scss
@use "sass:meta";

.probe {
  --modules: #{meta.feature-exists("modules")};
  --at-use: #{meta.feature-exists("at-use")};
  --typo-at-erorr: #{meta.feature-exists("at-erorr")};
}

How It Works

The helper never grew entries for the modern module system. A typo like "at-erorr" silently fails closed—another reason the API is a poor fit today.

🚀 When You Still See It

  • Legacy libraries — old mixins gated on at-error or units-level3.
  • Multi-compiler era code — stylesheets written when LibSass / Ruby Sass differed.
  • Deprecation cleanups — search for feature-exists before upgrading to Dart Sass 2.0.
  • Learning history — understand why modern Sass prefers member detection instead.

🧠 How Compilation Works

1

Pass a feature string

Call meta.feature-exists("at-error") (deprecated).

Source
2

Compiler looks up the name

Only the five documented strings can return true.

Compile
3

Boolean drives @if

Branches resolve at compile time; Dart Sass 1.78+ also warns.

Branch
4

Prefer deletion

Modern Dart Sass already supports these features—remove the check.

⚠️ Common Pitfalls

  • Adding it to new code — it is deprecated and will break in Dart Sass 2.0.
  • Assuming every Sass feature has a flag — modules, @use, etc. were never listed.
  • Typos return false — silent false negatives look like “unsupported.”
  • Silencing forever--silence-deprecation is temporary, not a fix.
  • Confusing with browser feature queries — this never checked CSS browser support.

💡 Best Practices

✅ Do

  • Search and remove feature-exists before Sass 2.0
  • Keep only the modern branch of old @if checks
  • Use meta.function-exists / mixin-exists when needed
  • Target current Dart Sass as your baseline
  • Read the official breaking-change notes

❌ Don’t

  • Write new meta.feature-exists call sites
  • Treat unknown strings as errors (they quietly return false)
  • Use it for browser @supports questions
  • Rely on silence flags as a long-term strategy
  • Expect new feature strings to be added

Key Takeaways

Knowledge Unlocked

Five things to remember about meta.feature-exists()

Legacy compiler flags—deprecated, remove before Dart Sass 2.0.

5
Core concepts
⚠️ 02

Status

deprecated

1.78+
📚 03

Catalog

5 feature strings

Docs
🗑 04

Migrate

delete checks

Fix
05

Replace

member exists APIs

Modern

❓ Frequently Asked Questions

meta.feature-exists($feature) returns true if the current Sass compiler claims support for a named legacy feature string, or false for unrecognized names. It is deprecated and should not be used in new code.
Official Sass docs: no new features were added for a long time, modern features are better detected with other meta helpers or expressions, and every Dart Sass release already supports all features this function checked—so calls can be removed.
Deprecation warnings started in Dart Sass 1.78.0. In Dart Sass 2.0.0, meta.feature-exists() will throw, and the global feature-exists() name will be treated as a plain CSS function call.
Usually nothing—delete the check. For specific members, use meta.function-exists, meta.mixin-exists, or meta.global-variable-exists. For first-class calc, expression checks like calc(1) == 1 are mentioned in the breaking-change docs.
global-variable-shadowing, extend-selector-pseudoclass, units-level3, at-error, and custom-property. Any other string returns false.
Yes. feature-exists($feature) is the legacy global name. Prefer meta.feature-exists only while reading old code—and plan to remove both forms.
Did you know?

Official Sass guidance is unusually strong here: because Dart Sass already supports every feature meta.feature-exists can report, all existing uses can safely be removed—you usually do not need a replacement check at all.

Conclusion

meta.feature-exists() was a compiler feature-flag helper from the multi-engine era. It is deprecated as of Dart Sass 1.78 and removed in 2.0. Learn the five recognized strings so you can read old code, then delete the checks—or replace them with targeted meta.*-exists helpers when you truly need member detection.

Continue with meta.function-exists() or the Sass introduction.

Next: detect functions

Learn meta.function-exists() to check if a function is defined.

meta.function-exists() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful