The skill of highlighting text and other objects was formed among computer users many years ago. We highlight the content of web pages for various reasons. Perhaps you need to copy the text and quote it somewhere, perhaps - it is simply easier for someone to read the text, highlighting its fragments. On mobile devices, however, highlighting something more difficult. For example, it annoys me. I don’t like highlighting the contents of web pages on the phone. This operation seems to be somehow "wrong." In this article I’ll talk about everything you need to know about styling selections with CSS. In particular, we will talk about the pseudo-element and the property
::selection
user-select
. This article aims to show everyone who wants CSS to work with selections, and how to use different methods to work with selections.The basics
On MDN, you can learn that a pseudo-element ::selection
allows you to apply styles to parts of a document that has been selected by the user (for example, using the mouse).To use it is ::selection
enough to use the following construction:p::selection {
color: #fff;
background-color: #000;
}
Selected text.Here is an example with which you can experiment.Properties Supported :: selection
It is worth noting that the pseudo-element ::selection
only supports properties color
, background
and text-shadow
.Customize your own selection effects
What if we need to make the selection look special? For example, so that the selection would have a certain height or some interesting background? Take a look at the following figure.An example of a special selection of selectionThis is possible, although it will require some effort. Here's how the selection shown above is made:- A pseudo-element is added, with the same text that we select. Then the pseudo-element is set to a property
height: 50%
and a white background color. - The pseudo-element is located above the source text.
If you now select the text, then the pseudo-element will overlap 50% of the text vertically. This allows us to simulate the effect we need.p {
position: relative;
color: #fff;
}
p:after {
content: attr(data-content);
position: absolute;
color: #000;
top: 0;
left: 0;
width: 100%;
height: 50%;
background-color: #fff;
}
p::selection {
background: rgba(76, 125, 225, 0.18);
}
I learned about this technique here .Another option for this selection is presented below. Here, instead of a solid selection, I implemented the selection as a CSS gradient. The point here is to use a white gradient with a height of 50% and to fill the element once with the background image by using the value no-repeat
when setting the property background
.h1:after {
content: attr(data-content);
position: absolute;
color: #000;
top: 0;
left: 0;
width: 100%;
background: linear-gradient(#fff, #fff) top/100% 50% no-repeat;
}
The following figure illustrates this technique.Implementing Gradient HighlightingHopefully I was able to clearly explain this idea. Here is a working example.Animating Selection
Working on the previous example, I asked the following question: "Is it realistic to animate the selection?". For example, in the process of selecting text, the height of the selection is 50%. And when the mouse pointer is moved to the side, the height of the selection increases to 80%. How to do it? But like this:p {
transition: background 0.3s ease-out;
}
p:hover:after {
background-size: 100% 80%;
}
Text in the selection processText after selection is completeHere is a video that demonstrates animated selection.Multiline text
The above selection adjustment technique, unfortunately, is not suitable for multi-line text. In order to, nevertheless, implement something similar for such text, you need to resort to the capabilities of JavaScript and put each word in an inline (lowercase) element, for example, in <span>
. After each word appears in its own element <span>
, a pseudo-element must be added to each of these elements. And after that, the effect described above can be applied to multiline text.Here is a script to put each word in a <span>
container:let paragraph = document.querySelector(".text");
const words = paragraph.textContent.split(" ");
paragraph.innerHTML = "";
words.forEach(function (word) {
let wordItem = document.createElement("span");
wordItem.setAttribute("data-word", word);
wordItem.innerHTML = word + " ";
paragraph.appendChild(wordItem);
});
After that, the elements <span>
must be stylized. Then to each of them you need to add a pseudo-element:span {
position: relative;
font-size: 1.25rem;
line-height: 1.4;
}
span::after {
content: attr(data-word);
position: absolute;
left: 0;
right: 0;
top: -0.28em;
height: 75%;
padding-top: 0.14em;
background: #fff;
pointer-events: none;
}
span::selection {
background: rgba(#4C7DE1, 0.18);
}
If you look at this design in practice, it turns out that it works, but not quite as you might expect. An example of multi-line text highlighting is shown below. You may notice that the selection looks patchy.Inhomogeneous selectionI would say that such a multi-line selection is not very good, and that it should not be used on a global scale. Perhaps it should be used only, say, to organize the selection of a particular paragraph.Here, with such a selection, you can experiment.Creative use :: selection and text-shadow
Since one of the properties that the pseudo-element supports ::selection
is text-shadow
that we can try to achieve some interesting effects using several shadows of the text. We are exploring the possibilities that this idea opens before us.▍ Highlight with long shadows
Selected text casts long shadows.Here's how to implement this effect:p::selection {
color: #444444;
background: #ffffff;
text-shadow: 1px 0px 1px #cccccc, 0px 1px 1px #eeeeee, 2px 1px 1px #cccccc, 1px 2px 1px #eeeeee, 3px 2px 1px #cccccc, 2px 3px 1px #eeeeee, 4px 3px 1px #cccccc, 3px 4px 1px #eeeeee, 5px 4px 1px #cccccc, 4px 5px 1px #eeeeee, 6px 5px 1px #cccccc, 5px 6px 1px #eeeeee, 7px 6px 1px #cccccc;
}
▍ Outline text effect
Selected text becomes contourThis idea I found in this article. We are talking about the fact that using the propertytext-shadow
you can simulate the effect of the outline text.p::selection {
color: #fff;
text-shadow:
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
}
▍ Blur effect
Selected text looks blurry.Another interesting effect that can be applied to selected text is to blur the text. The bottom line is to use the property when setting the color of the textcolor: transparent
. The shadows set with the helptext-shadow
will not disappear anywhere, which will give the desired effect.p::selection {
color: transparent;
text-shadow: 0 0 3px #fff;
}
I’m sure that you yourself will be able to come up with many more examples of text-shadow
styling selections. This property gives us unlimited possibilities.▍Shadow texts and performance
It is not recommended to use too complex styles when customizing text-shadow
. The fact is that excessive enthusiasm for this property leads to performance problems. Here's a video showing one example of such issues.Using very sophisticated styles to customize text selectionThe neon effect presented here is very complex. Please note that when this text is selected, there is a noticeable delay between the moment the text is selected and the moment the stylization is applied. In addition, pay attention to the fact that what should not appear on top and left. Therefore, I ask you to use ittext-shadow
carefully.Do form elements stand out?
A short answer to the question in the title of this section will sound “yes.” It seems to me that this is wrong: you select the page, but it turns out that the content inside the input fields is also highlighted. Here is how it looks.The content inside the input fields is highlighted.Here, the text inside the button can also be selected. In the section devoted touser-select
, we will talk about whether or not to allow users to highlight the forms of elements.Here is an example.Investigating the user-select property
The property user-select
allows us to set the ability to select specific text by the user. This property may be useful for disabling the ability to select text, which may be useful to limit the user's ability to select materials located next to each other. Here is a standard that describes user-select
.This property can take the following values: none, auto, text, contain, all
.User-select use cases
▍Text and icon
If the element has text and an icon - in the form of a symbol or icon taken from some font, then this icon will be highlighted when the text is selected. Consider the example shown in the following figure.Button with text and iconHere is the code for this button:<button>Our Services<span aria-hidden="true">▼</span></button>
When you select this item, it looks like the one shown below.Dedicated buttonThis is completely unnecessary. Please note that the markup uses an attributearia-hidden
that hides the icon from screen readers. In order to solve the problem of highlighting what you do not need to highlight, we can use the following style:button span[aria-hidden="true"] {
user-select: none;
}
This allows you to prohibit the selection of the icon. And, at the same time, we bind the selection ban to the attribute aria-hidden
. As a result, everything that should not stand out, most likely, should not be visible to screen readers.▍ Flags
This behavior of the flags annoys me when, by setting or unchecking a flag, I accidentally select the text of its description. Here is how it looks.The text of the flag description is selected randomly. You cansolve this problem by styling the element<label>
as follows:label {
user-select: none;
}
▍ Highlight all text
The value all
that a property can take user-select
allows you to achieve an interesting effect. If the parent element has this property with such a value, then all the text contained in such an element can be selected with one click. This can be useful for working with text content, which should be highlighted in its entirety. For example, to highlight code fragments available on a page:.embed-code {
user-select: all;
}
A fragment of text designed in such a style can be selected with one click on it.Web applications
The web application should be perceived by the user as a real application. Is it possible to select button text in regular applications? No you can not. It is important that web applications reflect the familiar features of regular applications, even if they are designed using HTML and CSS.Consider a few examples from life.▍Slack
In Slack, you can highlight labels and input fields. However, button texts are not highlighted.Button captions are not highlighted.Here is another example.The signature in the title bar of the modal window is highlighted. The date of the chat cannot be highlighted.The date cannot be allocatedIn general - it seems strange to me that in the application you can select some texts that, it would seem, should not support the selection. There are places in the Slack interface where it is useduser-select: none
, but there are fewer such places than you might expect. For example, to me, as a user, there is no benefit from highlighting the title of a modal window.▍Notion
The approach to the selection of elements implemented in Notion, I like more. This web application is more like a real application, rather than a website, any part of which can be highlighted.What should not stand out does not stand out.Not a single fragment of text is highlighted from this picture. This is exactly what you can expect from an application.Do not use global selection disable
It is not recommended to disable selection globally. When you use disabling selection, try to disable it only for elements for which it does not make sense. To do this, you can create a helper class. For example - this:.disable-selection {
-webkit-user-select:text;
-moz-user-select:text;
-ms-user-select:text;
user-select:text;
}
Bad pattern
There is one UX pattern that I really dislike. It consists in showing a warning when trying to highlight text. This annoys and makes the user feel as if they are trying to control his interaction with the site. An example of this pattern is shown below.Disable highlighting with notification displayPlease do not do this.Highlight on mobile devices
There is a property -webkit-touch-callout
for iOS Safari that should turn off the display of the standard tooltip displayed when text is selected. I tried to use this property, but it does not work.p {
-webkit-touch-callout: none;
}
Styles ::selection
don't work either.And the property user-select: none
works as expected.I tried to find a real example illustrating this problem. I copied a piece of text from Wikipedia. At the same time, the text that was completely unnecessary to me was copied (listen)
. This is annoying.Together with the useful text, it is copied and (listen)Instead of allowing the user to copy this “listen”, it would be better to add a style to this elementuser-select: none
. As a result, when copying text containing this element, it will not be copied.Summary
Here we looked at methods for customizing the highlighting of web page elements using CSS. You may be interested in looking at this material.Dear readers! How do you set up text selection in your projects?