This variable family is for reusing selector-based parts. The difference from normal value variables is:
- not written to
:root - does not produce CSS custom properties
- expanded at compile time
Two Usage Forms
Section titled “Two Usage Forms”| Syntax | What it does |
|---|---|
var(--x) | Expands a selector block independently or inside a nested context |
&var(--x) | Appends the resolved selector part without a space to preceding text |
This distinction is two usage forms within the same family.
1) Usage as Selector Block
Section titled “1) Usage as Selector Block”You can store a selector block as a variable and expand it with var(--x):
--card: .card { color: #ccc; };
var(--card);Generated CSS:
.card { color: #ccc;}Inside a nested context:
--card: .card { color: #ccc; };
.card-top { padding: 16px; var(--card);}Generated CSS:
.card-top { padding: 16px;}
.card-top .card { color: #ccc;}In this call the .card selector expands under the parent block.
2) Usage as Pseudo / Composition
Section titled “2) Usage as Pseudo / Composition”&var(--x) is used for pseudo selectors or modifier parts:
--hovered: :hover { opacity: 0.85; };
.btn&var(--hovered);Generated CSS:
.btn:hover { opacity: 0.85;}In this usage :hover is appended without a space to .btn.
Inside a nested context:
--hovered: :hover { opacity: 0.85; };
.card { padding: 16px; &var(--hovered);}Generated CSS:
.card { padding: 16px;}
.card:hover { opacity: 0.85;}Combined Usage
Section titled “Combined Usage”Both selector expansion and composition can be used in the same block:
--card: .card { color: #1a1a2e; };--hovered: :hover { opacity: 0.85; };
.card-top { padding: 16px; var(--card); &var(--hovered);}Generated CSS:
.card-top { padding: 16px;}
.card-top .card { color: #1a1a2e;}
.card-top:hover { opacity: 0.85;}Here:
var(--card)expands a child selector&var(--hovered)does composition on the same selector
Different Composition Examples
Section titled “Different Composition Examples”Modifier Class
Section titled “Modifier Class”--open: .is-open { max-height: 500px; };
.drawer&var(--open);Generated CSS:
.drawer.is-open { max-height: 500px;}Focus State
Section titled “Focus State”--focused: :focus-visible { outline: 2px solid #2060ff; outline-offset: 2px; };
.btn&var(--focused);Generated CSS:
.btn:focus-visible { outline: 2px solid #2060ff; outline-offset: 2px;}Usage With Observed
Section titled “Usage With Observed”? or ?! can be appended to the final selector tail produced by &var(...). That is, the selector formed after composition is processed as observed.
--hovered: :hover { opacity: 0.85; };--active: .is-active { outline: 2px solid #2060ff; };
.card &var(--hovered)? { transform: translateY(-2px); }.card &var(--active)?! { box-shadow: 0 10px 26px rgba(22, 61, 120, 0.18); }The selector equivalents of these examples are:
.card:hover?.card.is-active?!
The rule does not change:
- marker must be at the end
- must be written without a space
- pseudo and modifier class compositions can be observed in the same way
&var(...) Inside Declaration Value
Section titled “&var(...) Inside Declaration Value”&var(...) works not only in selectors but also in declaration values.
--letters: [A-F];
.token { color: #AA&var(--letters[2]);}Generated CSS:
.token { color: #AAC;}Here the value C is appended without a space to #AA.
Difference from CSS Variables
Section titled “Difference from CSS Variables”| CSS Variables | Selector / Pseudo Variables | |
|---|---|---|
Written to :root? | Yes | No |
| Becomes CSS custom property? | Yes | No |
| Lifetime | Lives in the browser | Expanded at compile time |
| Typical purpose | Color, spacing, scalar values | Selector block, pseudo, modifier, composition |
| Typical syntax | var(--x) | var(--x) or &var(--x) |