Abstract
The matches() function is proposed to enhance the conditional application of styles in CSS by checking if the current element matches a specified selector. This function complements the recently accepted new if() function, providing a more semantic and readable way to handle conditional logic within CSS properties.
Motivation
The current method of conditionally applying styles in CSS often involves the use of arguably complex techniques like emulating boolean values using integers (0 and 1) or toggles using empty values (The --var: ; hack...), both of which can become complex and less readable.
The introduction of if() allows for clearer conditionality using boolean logic. However, the need to conditionally style elements based on their selector remains verbose and needs and is only really doable via addtl rules/selectors in the cascade, even if it would be simpler inline in some cases. The matches() function aims to address this by allowing a direct approach to conditionally setting styles based on selector matches.
This would also bring greater parity with the related JS Element.prototype.matches method.
Syntax
- selector: A CSS selector to check against the current element.
Usage
The matches() function can be used inside any CSS property value expression where conditional styles are necessary based on whether the current element matches a specified selector.
Example 1: Basic example
.item {
--symbol: if(matches(.favorite) ? "🧡" : "🩶");
&::before {
content: var(--symbol);
}
}
In this example, the --symbol custom property is conditionally set to different emoji characters based on whether the .item element has the .favorite class.
Comparison to existing methods
Example 2.1: Without if() and matches()
.item {
--symbol: "🩶";
&::before {
content: var(--symbol);
}
&.favorite {
--symbol: "🧡";
}
}
This traditional approach involves redundant code as it sets the same property (--symbol) in multiple places.
Example 2.2: Using if() and matches()
.item {
--symbol: if(matches(.favorite) ? "🧡" : "🩶");
&::before {
content: var(--symbol);
}
}
This approach reduces redundancy and centralizes the logic for setting the --symbol property.
A case for boolean expressions outside if()
I've opened a separate proposal (#10593) focused on supporting a new "boolean" custom property type, which could hypothetically be valid and type-safe even outside of if(). If that's accepted, an example using a math-based switch like the one below could be simplified to use boolean logic.
Example 3.1: Using a math-based switch
This example uses a math-based switch to zero out values when a condition is not met.
label {
--selected: 0;
&:has(:checked) { --selected: 1; }
grid-template-columns: auto calc(var(--selected) * 20px);
svg { opacity: var(--selected); }
}
Example 3.2: Using matches() and if()
This moves the conditions inline, but they're a bit complex, so it's not ideal that we have to repeat the conditions in both values.
label {
grid-template-columns: auto if(matches(:has(:checked)) ? 20px : 0);
svg { opacity: if(matches(:has(:checked)) ? 1 : 0); }
}
Example 3.3: Using matches() and if()
Using reusable boolean values can offload some of this complexity.
label {
--selected: matches(:has(:checked));
grid-template-columns: auto if(var(--selected) ? 20px : 0);
svg { opacity: if(var(--selected) ? 1 : 0); }
}
Abstract
The
matches()function is proposed to enhance the conditional application of styles in CSS by checking if the current element matches a specified selector. This function complements the recently accepted newif()function, providing a more semantic and readable way to handle conditional logic within CSS properties.Motivation
The current method of conditionally applying styles in CSS often involves the use of arguably complex techniques like emulating boolean values using integers (
0and1) or toggles using empty values (The --var: ; hack...), both of which can become complex and less readable.The introduction of
if()allows for clearer conditionality using boolean logic. However, the need to conditionally style elements based on their selector remains verbose and needs and is only really doable via addtl rules/selectors in the cascade, even if it would be simpler inline in some cases. Thematches()function aims to address this by allowing a direct approach to conditionally setting styles based on selector matches.This would also bring greater parity with the related JS
Element.prototype.matchesmethod.Syntax
Usage
The
matches()function can be used inside any CSS property value expression where conditional styles are necessary based on whether the current element matches a specified selector.Example 1: Basic example
In this example, the
--symbolcustom property is conditionally set to different emoji characters based on whether the.itemelement has the.favoriteclass.Comparison to existing methods
Example 2.1: Without
if()andmatches()This traditional approach involves redundant code as it sets the same property (
--symbol) in multiple places.Example 2.2: Using
if()andmatches()This approach reduces redundancy and centralizes the logic for setting the
--symbolproperty.A case for boolean expressions outside
if()I've opened a separate proposal (#10593) focused on supporting a new "boolean" custom property type, which could hypothetically be valid and type-safe even outside of
if(). If that's accepted, an example using a math-based switch like the one below could be simplified to use boolean logic.Example 3.1: Using a math-based switch
This example uses a math-based switch to zero out values when a condition is not met.
Example 3.2: Using
matches()andif()This moves the conditions inline, but they're a bit complex, so it's not ideal that we have to repeat the conditions in both values.
Example 3.3: Using
matches()andif()Using reusable boolean values can offload some of this complexity.