Skip to content

Selector / Pseudo Variables

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

SyntaxWhat 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.


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.


&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;
}

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

--open: .is-open { max-height: 500px; };
.drawer&var(--open);

Generated CSS:

.drawer.is-open {
max-height: 500px;
}
--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;
}

? 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(...) 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.


CSS VariablesSelector / Pseudo Variables
Written to :root?YesNo
Becomes CSS custom property?YesNo
LifetimeLives in the browserExpanded at compile time
Typical purposeColor, spacing, scalar valuesSelector block, pseudo, modifier, composition
Typical syntaxvar(--x)var(--x) or &var(--x)