Inheritance changes for CSS selection styling

Stephen Chenney
Stephen Chenney

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:

Text that you might expect to be blue is red.

When selected in Chrome 131, the result changes to this:

Text is now highlighted blue.

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:

The first line is green, the second blue.

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):

The first line of text is green. The second is blue but the word emphasized is green.

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:

The first line of text is green. The second line is blue.

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.