CSS Custom Properties in Highlight Pseudos
The CSS highlight inheritance model describes the process for inheriting the CSSproperties of the various highlight pseudo elements:
::selection
controlling the appearance of selected content::spelling-error
controlling the appearance of misspelled word markers::grammar-error
controlling how grammar errors are marked::target-text
controlling the appearance of the string matching a target-text URL::highlight
defining the appearance of a named highlight, accessed via the CSS highlight API
The inheritance model is intended to generate more intuitive behavior for examples
like the one below, where we would expect the second line to be entirely blue
because the <em>
is a child of the blue paragraph that typically would
inherit properties from the paragraph:
<style>
::selection /* = *::selection (universal) */ {
color: lightgreen;
}
.blue::selection {
color: blue;
}
</style>
<p>Some <em>lightgreen</em> text</p>
<p class="blue">Some <em>lightgreen</em> text that one would expect to be blue</p>
<script>
range = new Range();
range.setStart(document.body, 0);
range.setEnd(document.body, 3)
document.getSelection().addRange(range);
</script>
Before this model was standardized, web developers achieved the same effect using CSS custom properties. The selection highlight could make use of a custom property defined on the originating element (the element that is selected). Being defined on the originating element tree, those custom properties were inherited, so a universal highlight would effectively inherit the properties of its parent. Here’s what it looks like:
<style>
:root {
--selection-color: lightgreen;
}
::selection /* = *::selection (universal) */ {
color: var(--selection-color);
}
.blue {
--selection-color: blue;
}
</style>
<p>Some <em>lightgreen</em> text</p>
<p class="blue">Some <em>lightgreen</em> text that is also blue</p>
<script>
range = new Range();
range.setStart(document.body, 0);
range.setEnd(document.body, 3)
document.getSelection().addRange(range);
</script>
In the example, all selection highlights use the value of --selection-color
as
the selection text color. The <em>
element inherits the property value of blue
from its parent <p>
and hence has a blue highlight.
This approach to selection inheritance was promoted in Stack Overflow posts and other places, even in posts that did not discuss inheritance. The problem is that the new highlight inheritance model, as previously specified, broke this behavior in a way that required significant changes for web sites making use of the former approach. At the prompting of developer advocates, the CSS Working Group decided to change the specified behavior of custom properties with highlight pseudos to support the existing recommended approach.
Custom Properties for Highlights #
The updated behavior for custom properties in highlight pseudos is that highlight
properties that have var(...)
references take the property values from the originating
element. In addition, custom properties defined in the highlight pseudo itself will
be ignored. The example above works with this new approach, so content making use
of it will not break when highlight inheritance is enabled in browsers.
Note that this explicitly conflicts with the previous guidance, which was to define the custom properties on the highlight pseudos, with only the root highlight inheriting custom properties from the document root element.
The change is implemented behind a flag in Chrome 126 and higher, as is expected to be enabled by default as early as Chrome 130. To see the effects right now, enable “Experimental Web Platform features” via chrome://flags in M126 Chrome (Canary at the time of writing).
A Unified Approach for Derived Properties in Highlights #
There are other situations in which properties are disallowed on highlight pseudos yet
those properties are necessary to resolve variables. For example, lengths that use
font based units, such as 0.5em
cannot use font-size from a highlight pseudo
because font-size is not allowed in highlights. Similarly container-based units
or viewport units. The general rule is that the highlight will get whatever value it needs
from the originating element, and that now includes custom property values.