selector.unify() belongs to the built-in sass:selector module. It builds a selector that matches only elements matched by both inputs—or returns null when there is no expressible overlap. This page covers compounds, complex pairs, safe @if guards, and five compiled examples.
01
Concept
Selector overlap
02
Module
@use "sass:selector"
03
Returns
Selector or null
04
Args
$selector1, $selector2
05
Null
Guard with @if
06
Practice
5 examples
Concept
What Is selector.unify()?
Official docs: returns a selector that matches only elements matched by both $selector1 and $selector2. If the selectors do not overlap, or if Sass cannot express that overlap as a selector, the result is null.
Simple compounds often merge: a + .disabled → a.disabled.
Incompatible types return null: a + h1.
Complex pairs can expand into multiple forms (similar ideas to @extend unification).
Official caveat: when both sides are complex, the result is not guaranteed to match every element matched by both.
💡
Beginner tip
Think Venn diagram: unify keeps the overlap. a and .disabled share a.disabled. a and h1 share nothing you can write as one element selector, so you get null.
Foundation
📝 Syntax
styles.scss
@use "sass:selector";
// Recommended
selector.unify($selector1, $selector2)
// Legacy global name
selector-unify($selector1, $selector2)
Parameters
Parameter
Type
Required
Description
$selector1
Selector
Yes
First selector to unify.
$selector2
Selector
Yes
Second selector to unify.
Return value
Type
Result
Selector
A selector matching the overlap of both inputs
null
No expressible overlap
Modules
📦 Loading sass:selector
styles.scss
// Recommended — namespaced (Dart Sass 1.23+)
@use "sass:selector";
$u: selector.unify("a", ".disabled"); // a.disabled
// Optional — bring members into scope
@use "sass:selector" as *;
$u: unify("a", ".disabled");
// Legacy global
$u: selector-unify("a", ".disabled");
Details
🎨 Official Patterns
Call
Result
unify("a", ".disabled")
a.disabled
unify("a.disabled", "a.outgoing")
a.disabled.outgoing
unify("a", "h1")
null
unify(".warning a", "main a")
.warning main a, main .warning a
The last sample shows why complex unification can emit a comma list: ancestor order can vary, so Sass lists the sensible combinations.
Compare
⚖️ unify vs is-superselector
Helper
Question it answers
Typical result
selector.unify
What selector matches both?
Selector or null
selector.is-superselector
Does A cover everything B matches?
true / false
Support
🛠 Compatibility
This is about Sass compilers, not browsers. Unification runs at compile time.
Implementation
unify
Dart Sass
Yes — prefer selector.unify (module since 1.23.0)
LibSass
Legacy selector-unify may exist; no @use "sass:selector"
Ruby Sass
Legacy selector-unify may exist; no @use "sass:selector"
Prefer current Dart Sass so the module API matches the official docs.
Cheat Sheet
⚡ Quick Reference
Goal
Code
Import selector
@use "sass:selector";
Merge compounds
selector.unify("a", ".disabled")
Check for null
$u: selector.unify(…); @if $u { … }
Print null safely
meta.inspect(selector.unify("a", "h1"))
Use as a selector
#{$u} { … } after an @if guard
Hands-On
Examples Gallery
Each example uses selector.unify at compile time (Dart Sass 1.23+). Open View Compiled CSS for verified output.
📚 Getting Started
Official docs samples, then real CSS rules.
Example 1 — Official Unify Samples
Compounds, merged classes, null, and complex pairs.
Compound builders — merge tag + class or class + class into one selector.
Complex layout tooling — unify nested contexts like warning/main links.
Debugging — print overlaps with meta.inspect, including null.
🧠 How Compilation Works
1
Pass two selectors
Call selector.unify($selector1, $selector2).
Source
2
Sass finds the overlap
Merges compounds or expands complex pairs—or returns null.
Compile
3
Guard, then interpolate
Use @if $u before #{$u} { … }.
Emit
4
✓
CSS ships
Browsers only see finished selectors like a.disabled—never null.
Watch Out
⚠️ Common Pitfalls
Interpolating null — always guard with @if or print via meta.inspect.
Assuming full coverage for complex pairs — official docs warn the result may not match every shared element.
Confusing with append — append glues strings; unify computes overlap.
Confusing with is-superselector — that returns a boolean, not a selector.
Old compilers without modules — use Dart Sass 1.23+ for @use "sass:selector".
Pro Tips
💡 Best Practices
✅ Do
Use @use "sass:selector" and selector.unify()
Store the result and check with @if $u
Use it to merge compatible compounds safely
Prefer is-superselector when you only need a yes/no
Prefer Dart Sass 1.23+
❌ Don’t
Interpolate a unify result without a null check
Assume every pair must succeed
Treat complex unify as a perfect set intersection
Expect browsers to evaluate the call
Rely on LibSass for the module API
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about selector.unify()
Build the overlap of two selectors—or get null when there is none.
5
Core concepts
📝01
API
unify(s1, s2)
Call
📦02
Module
sass:selector
@use
🔗03
Result
selector or null
Output
📚04
Complex
may expand lists
Detail
✓05
Safety
@if before emit
Guard
❓ Frequently Asked Questions
selector.unify($selector1, $selector2) returns a selector that matches only elements matched by both selectors. Example: unify("a", ".disabled") becomes a.disabled.
Official docs: it returns null if the two selectors do not match any of the same elements, or if there is no selector that can express their overlap. Example: unify("a", "h1") is null.
Complex pairs can produce a list of unified forms. Example: unify(".warning a", "main a") becomes .warning main a, main .warning a. The result is not guaranteed to cover every possible shared element when both sides are complex.
Yes. selector-unify($selector1, $selector2) is the legacy global name. Prefer selector.unify after @use "sass:selector".
Store the result in a variable and guard with @if $u { ... } before interpolating it as a selector.
Dart Sass 1.23+. LibSass and Ruby Sass do not load sass:selector with @use; they may still offer the legacy global name.
Did you know?
Official Sass docs note that unify results for complex selectors are related to @extend unification—so you may get more than one complex selector in the returned list.
selector.unify() builds the overlap of two selectors, or returns null when there is no expressible match. Guard with @if before emitting rules, and remember complex pairs can expand into multiple selectors.