Published: October 8, 2024
From Chrome 131 CSS highlight inheritance is changing for the ::selection
and
::target-text
pseudo-classes. This is to create a more intuitive model for
inheritance and align with the recently added ::highlight
, ::spelling-error
and
::grammar-error
pseudo-classes. This post explains the change, which shouldn't
cause a visible impact for most sites.
Selection styling
Styling the appearance of selected text can convey meaning to users, such as the purpose of the selected content or the inability to select the text at all. GitHub, for example, colors selected code differently from selected directory structure.
CSS supports selection styling with the
::selection
pseudo-element, one of a set of pseudo-elements known as
highlight pseudo-elements.
These pseudo-elements control how text appears under various user,
browser, or script driven actions. Apart from selection, you can style spelling
errors (::spelling-error
), grammar errors (::grammar-error
), URL-embedded text
targets (::target-text
), and script generated highlights (::highlight
).
As with any collection of CSS properties, the inheritance behavior is an
important consideration when designing a site. In general, developers expect CSS
properties to either be inherited through the DOM element tree (for example,
font
), or not inherited at all (for example, background
).
Changes to selection behavior in Chrome 131
Consider this document fragment:
p {
color: red;
}
.blue::selection {
color: blue;
}
<p class="blue">Some <em>emphasized</em> text that one would expect to be blue</p>
The fragment's style declarations modify the color of selected text,
with one rule matching all elements and one matching those with class "blue"
.
When selected in Chrome 130 or earlier, this is the result:
When selected in Chrome 131, the result changes to this:
What has changed? The inheritance behavior of selection properties has
historically been implemented through originating element inheritance, where
the selection uses the properties from a ::selection
that matches the element
being selected. Chrome versions 130 and earlier use this model, where the
emphasized text has no matching ::selection
because the .blue::selection
only matches elements with the "blue"
class, which the <em>
element lacks.
Chrome 131 enables new behavior whereby elements inherit selection behavior from
their parent. In the preceding example, the <em>
element has no ::selection
matching itself, so it inherits the <p>
element's selection colors. This is
referred to as CSS highlight inheritance and you can try it out in earlier
Chrome versions by enabling Experimental Web Platform features in
chrome://flags
.
Sites that rely on selection properties not inheriting are likely to see changes in the appearance of selected text, but evidence from bug reports suggests there are few use cases for such behavior.
CSS Custom Properties for selection still work
Many sites simulate CSS highlight inheritance through the use of CSS custom properties. Custom properties are inherited through the element tree, giving the "inherit from parent" outcome with a code snippet like this:
:root {
--selection-color: lightgreen;
}
::selection {
color: var(--selection-color);
}
.blue {
--selection-color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text that is blue</p>
This is the result when selected in both Chrome 130 and 131:
Here every element inherits some value for the --selection-color
property
through the element tree, and this color is used when text is selected. Elements
with the .blue
class and their descendants are blue when selected, and other
elements are light green. Many sites use this technique and it is the method
recommended on Stack Overflow.
To maintain compatibility the CSS highlight inheritance model specifies that
::selection
(and other CSS highlight pseudo-elements) inherit custom property
values from their originating element (the element that they are being applied
to). Sites using this method should remain unaffected by the changes in Chrome
131.
Custom properties defined on the ::selection
pseudo-element itself are ignored
to avoid competing inheritance behaviors. You must define the properties on the
element itself, and then reference them in the pseudo element.
Universal Selectors for ::selection
disable highlight inheritance
Sites not using CSS custom properties may have been using a universal selector to set the selected text color. Like the following CSS, for example:
::selection /* = *::selection (universal) */ {
color: lightgreen;
}
.blue::selection {
color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>
This is the result when selected in both Chrome 130 (and earlier) and Chrome 131 (and later):
CSS highlight inheritance does not cause the second emphasized text to inherit
blue from its parent because the universal selector matches the <em>
element
and applies the universal highlight color, light green.
To gain the benefits of CSS highlight inheritance, change the universal selector to match only the root, which will then be inherited by its descendants:
:root::selection {
color: lightgreen;
}
.blue::selection {
color: blue;
}
<p>Some <em>emphasized</em> text</p>
<p class="blue">Some <em>emphasized</em> text</p>
The result in Chrome 131 looks like this:
If your site modifies selection colors but does not use custom properties, it is
likely that you have a universal selector for the ::selection
pseudo. The good
news is that your site won't break with this change in Chrome, but you will
miss out on any ergonomic benefits from highlight inheritance.
::target-text
styling is also changing
All of the behaviors and changes described here apply to the ::target-text
pseudo-element as they do to ::selection
. The use cases for more than one
target text styling on a single site are limited, and the feature is quite new,
so your site is highly unlikely to change in ::target-text
behavior.
Why this change?
When the other highlight pseudo-elements were in development, the CSS Working
Group resolved to implement inheritance with the highlight inheritance model.
This was already the method in the specification of the ::selection
pseudo-element, but browsers did not implement it. The non-selection
pseudo-elements use highlight inheritance, where the pseudo-element is inherited
as if it were a property. That is, elements inherit the highlight
pseudo-elements from their document parent.
In the interests of consistency across all highlight pseudos the CSS Working
Group reiterated support for highlight inheritance for ::selection
, and
browsers are working to launch the new behavior, while trying not to break
existing sites.
Try it out
The following CodePen demonstrates the changes. Try it out in Chrome 131.