Chrome 144 lately shipped ::search-text, which is now one in every of a number of highlight-related pseudo-elements. This one selects find-in-page textual content, which is the textual content that will get highlighted if you do a Ctrl/Command + F-type seek for one thing on a web page and matches are discovered.
By default, ::search-text matches are yellow whereas the present goal (::search-text:present) is orange, however ::search-text allows us to alter that.
I’ll admit, I hadn’t actually been following these spotlight pseudo-elements. Up till now, I didn’t even know that there was a reputation for them, however I’m glad there may be as a result of that makes it simpler to spherical all of them up and examine them, which is precisely what I’m going to do right here at the moment, because it’s not tremendous apparent what they do primarily based on the identify of the pseudo-element. I’ll additionally clarify why we’re in a position to customise them, and recommend how.
The several types of spotlight pseudo-elements
| Pseudo-selector | Selects… | Notes |
|---|---|---|
::search-text |
Discover-in-page matches | ::search-text:present selects the present goal |
::target-text |
Textual content fragments | Textual content fragments enable for programmatic highlighting utilizing URL parameters. When you’re referred to a web site by a search engine, it would use textual content fragments, which is why ::target-text is well confused with ::search-text. |
::choice |
Textual content highlighted utilizing the pointer | |
::spotlight() |
Customized highlights as outlined by JavaScript’s Customized Spotlight API | |
::spelling-error |
Incorrectly spelled phrases | Just about applies to editable content material solely |
::grammar-error |
Incorrect grammar | Just about applies to editable content material solely |
And let’s not neglect in regards to the HTML factor both, which is what I’m utilizing within the demos under.
What ought to spotlight pseudo-elements appear like?
The query is, if all of them (apart from ::spotlight()) have default styling, why would we have to choose them with pseudo-elements? The reason being accessibility (colour distinction, particularly) and value (emphasis). For instance, if the default yellow background of ::search-text doesn’t distinction effectively sufficient with the textual content colour, or if it doesn’t stand out towards the background of the container, then you definately’ll need to change that.
I’m certain there are a lot of methods to unravel this (I need to hear “problem accepted” within the feedback), however the very best answer that I’ve provide you with makes use of relative colour syntax. I took incorrect turns with each background-clip: textual content and backdrop-filter: invert(1) earlier than realizing that many CSS properties are off-limits in relation to spotlight pseudo-elements:
physique {
--background: #38003c;
background: var(--background);
mark,
::choice,
::target-text,
::search-text {
/* Match colour to background */
colour: var(--background);
/* Convert to RGB then subtract channel worth from channel most (255) */
background: rgb(from var(--background) calc(255 - r) calc(255 - g) calc(255 - b));
}
}
Your browser may not assist that but, so right here’s a video that reveals how the highlighted textual content adapts to background colour adjustments.
What’s occurring right here is that I’m changing the container’s background colour to RGB format after which subtracting the worth of every channel (r, g, and b) from the utmost channel worth of 255, inverting every channel and the general colour. This colour is then set because the background colour of the highlighting, making certain that it stands out it doesn’t matter what, and due to the brand new CodePen slideVars, you possibly can fiddle with the demo to see this in motion. You would possibly have the ability to do that with colour codecs apart from RGB, however RGB is the simplest.
In order that covers the usability, however what in regards to the accessibility?
Properly, the highlighting’s textual content colour is identical because the container’s background colour as a result of we all know that it’s the inverse of the highlighting’s background colour. Whereas this doesn’t imply that the 2 colours can have accessible distinction, it appears as if they may more often than not (you need to at all times examine colour distinction utilizing colour distinction instruments, regardless).
When you don’t just like the randomness of inverting colours, that’s comprehensible. You may completely decide colours and write conditional CSS for them manually as an alternative, however discovering accessible colours that stand out towards the completely different backdrops of your design for the entire several types of spotlight pseudo-elements, whereas accounting for different viewing modes equivalent to darkish mode, is a headache. Moreover, I feel sure UI components (e.g., highlights, errors, focus indicators) ought to be ugly. They ought to stand out in a brutalist kind of method and really feel disconnected from the design’s colour palette. They need to demand most consideration by deliberately not becoming in.
Understand that the several types of spotlight pseudo-elements needs to be visually distinctive too, for apparent causes, but additionally in case two differing types overlap one another (e.g., the consumer selects textual content at the moment matched by find-in-page). Subsequently, within the amended code snippet under, mark, ::choice, ::target-text, and ::search-text all have barely completely different backgrounds.
I’ve left mark unchanged, the r worth of ::choice because it was, the g worth of ::target-text because it was, and the b worth of ::search-text because it was, so these final three solely have two channels inverted as an alternative of all three. They’re diversified in colour now (however nonetheless look inverted), and with the addition of an alpha worth at 70% (100% for ::search-text:present), in addition they mix into one another in order that we will see the place every spotlight begins and ends:
physique {
--background: #38003c;
background: var(--background);
mark,
::choice,
::target-text,
::search-text {
colour: var(--background);
}
mark {
/* Invert all channels */
background: rgb(from var(--background) calc(255 - r) calc(255 - g) calc(255 - b) / 70%);
}
::choice {
/* Invert all channels however R */
background: rgb(from var(--background) r calc(255 - g) calc(255 - b) / 70%);
}
::target-text {
/* Invert all channels however G */
background: rgb(from var(--background) calc(255 - r) g calc(255 - b) / 70%);
}
::search-text {
/* Invert all channels however B */
background: rgb(from var(--background) calc(255 - r) calc(255 - g) b / 70%);
&:present {
/* Invert all channels however B, however with out transparency */
background: rgb(from var(--background) calc(255 - r) calc(255 - g) b / 100%);
}
}
}
::spelling-error and ::grammar-error are excluded from all this as a result of they’ve their very own visible affordances (purple underlines and inexperienced underlines respectively, usually contrasted towards the impartial background of an editable factor equivalent to ).
However mark, ::choice, ::target-text, and new-to-Chrome ::search-text? Properly, they will seem wherever (even on high of one another), so I feel it’s vital that they’re visually distinctive from one another whereas being accessible always. Once more although, even fully-inverted colours might be inaccessible. Actually, the inverse of #808080 is #808080, so take a look at, take a look at, take a look at! Though, possibly contrast-color() may come to the rescue as soon as the CSS Colour Module Stage 5 model of it ships.
Within the meantime, please, no extra highlight-y components!
