惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
D
Docker
GbyAI
GbyAI
B
Blog RSS Feed
博客园 - 司徒正美
博客园 - Franky
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
aimingoo的专栏
aimingoo的专栏
C
Check Point Blog
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
AI
AI
O
OpenAI News
Attack and Defense Labs
Attack and Defense Labs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
S
Secure Thoughts
博客园 - 聂微东
L
LINUX DO - 最新话题
U
Unit 42
SecWiki News
SecWiki News
A
Arctic Wolf
Schneier on Security
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Visual Studio Blog
量子位
The Cloudflare Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
G
Google Developers Blog
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
B
Blog
博客园 - 【当耐特】
C
CERT Recently Published Vulnerability Notes
Scott Helme
Scott Helme
Last Week in AI
Last Week in AI
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
Latest news
Latest news

Ahmad Shadeed

Better fluid sizing with round() Use Cases for Field Sizing The Basics of Anchor Positioning Item Flow CSS Relative Colors Balancing Text In CSS Should masonry be part of CSS grid? CSS display contents CSS Grid Areas CSS Cap Unit An Interactive Guide to CSS Container Queries CSS :has() Interactive Guide CSS Nesting UX in DevTools CSS Nesting Future CSS: State Container Queries Rebuilding a comment component with modern CSS Conditional CSS with :has and :nth-last-child CSS Text balancing with text-wrap:balance CSS Masking Do we need CSS flex-wrap detection? My CSS Wishlist Conditional CSS CSS Style Queries Inside the mind of a frontend developer: Article layout Inside the mind of a frontend developer: Hero section CSS container queries are finally here The CSS behind Figma First Look At The CSS object-view-box Property Learn CSS Subgrid CSS :has Parent Selector Aligning Content In Different Wrappers Flexbox Dynamic Line Separator Hello, CSS Cascade Layers Building UI Components With SVG and CSS A Deep CSS Dive Into Radial And Conic Gradients Defensive CSS Building Real-life Components: Facebook Messenger Conditional Border Radius In CSS CSS Container Query Units Aligning a Button Label Vertically Comparing Design Mockups To Code Result Using HSL Colors In CSS Custom Scrollbars In CSS Let CSS Container Queries For Designers The State of CSS Cross-Browser Development Overflow Issues In CSS Inspect Element As A Way To Increase Your Curiosity Handling Text Over Images in CSS Digging Into CSS Logical Properties Clipping Scrollable Areas On The inline-start Side Understanding Clip Path in CSS The Art of Building Real-life Components Handling Short And Long Content In CSS CSS Scroll Snap A Deep Dive Into CSS Grid minmax() CSS Variables 101 Finding The Root Cause of a CSS Bug Learn CSS centering How to detect browser support for Flexbox Gap CSS Mistakes While On Autopilot Digging Into the Flex Property Understanding CSS Multiple Backgrounds Aligning Logo Images in CSS Grid for layout, Flexbox for components Colors in CSS Thinking About The In-between Design Cases min(), max(), and clamp() CSS Functions Image Techniques On The Web Everything About Auto in CSS Learn Box Alignment Let Learn CSS Positioning Intrinsic Sizing In CSS CSS Grid Template Areas In Action Hiding Elements On The Web Creating a Variable Color Font From Scratch Building a Football Ticket With CSS and SVG Blending Modes in CSS CSS Variables With Inline Styles Implementing Dark Mode For My Website Rebuilding Apple Music Header in HTML & CSS Accessible Checkbox Layout Flickering On Browser Resize Enhancing The Clickable Area Size Custom Underlines with SVG Part 3: The Process of Implementing A UI Design From Scratch Part 2: The Process of Implementing A UI Design From Scratch Building An Old Nav Design CSS Flexbox: 5 Real World Use Cases I Used CSS Inline Flex For The First Time The Process of Implementing A UI Design From Scratch Common CSS Issues For Front-End Projects Handling Long and Unexpected Content in CSS How to Build Web Form Layouts With CSS Grid Grid Layout Ah-ha Moment Enhancing Our Components with CSS :empty Building Resizeable Components with Relative CSS Units CSS Writing Mode The Journey of Learning Front End Web Development on a Daily Basis
Selection in CSS
Ahmad Shadeed · 2020-04-27 · via Ahmad Shadeed

The Layout Maestro

I spent years teaching CSS layout on this blog. I put everything I know into The Layout Maestro course: 70+ lessons and 150+ interactive examples that teach you how to think CSS layouts, not just memorize syntax.

Get the course

Selection is a habit formed by computer users many years ago. On the web, we select content for different reasons. Maybe we want to copy a text and quote it somewhere, or maybe coping is just a habit that some users do to make reading easier. For mobile, selecting content is harder and for me, it’s annoying. I don’t like to select content on mobile. It just doesn’t feel right!

In this article, I will go through everything about selection in CSS, which includes the pseudo-element ::selection, and user-select. The goal of the article is to get you aligned with all those techniques and to let you know when and where to use them.

According to Mozilla Developer Network (MDN):

The ::selection CSS pseudo-element applies styles to the part of a document that has been highlighted by the user (such as clicking and dragging the mouse across text).

To use the ::selection pseudo-element, all you need to do is the following:

p::selection {
  color: #fff;
  background-color: #000;
}

Demo

Supported Properties For ::selection

It’s worth noting that only color, background, and text-shadow properties are supported with ::selection.

Custom Selection

What if we want a custom selection effect? For example, controlling the height of selection, and having a custom background? See the below figure:

It’s possible, but a bit tricky. Here is an explanation of how it’s done:

  1. We add a pseudo-element with the same text content. Then, we give it a 50% height with a white background color.
  2. The pseudo-element is positioned above the original text.

Now, when the text is selected, the pseudo-element will cover 50% of the text vertically. This mimics the effect we needed.

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);
}

Credits goes to this question on StackOverflow.

As another option, I tweaked the above and used CSS gradients instead. The point here is using a white gradient that has a 50% height and doesn’t repeat the 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;
}

See the below figure for a visual explanation.

I hope it’s more clear now! See the demo on CodePen.

Animating Selection

While working on the previous demo, I asked myself a question: is it possible to animate the selection? For example, while the text is selected and the mouse is not hovering, the height is 50% and When the mouse is hovering, the height can be increased to 80%.

p {
  transition: background 0.3s ease-out;
}

p:hover:after {
  background-size: 100% 80%;
}

Multi Line Text

Unfortunately, the solution above won’t work with multi-line text. To make it work, we should use JavaScript to wrap each word in an inline element, a <span>, for example. Once each word is in a <span> element, a pseudo-element should be added to each one, and the same technique can be used.

See the below script for wrapping each word in a <span> element.

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

Now, you need to style each <span> element, and then add a pseudo-element for each one.

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);
}

This solution works, but not with all text. For example, the text below has a comma, number, full capital words. Notice that the selection is not consistent in all words.

I would say that having a multi-line selection style is hacky, and shouldn’t be used globally on a website. Maybe it’s totally fine if it’s were used for one paragraph only.

Demo

Getting Creative With ::selection and text-shadow

Since text-shadow is one of the supported properties for a custom selection, we can get creative with some interesting effects by using multiple text shadows. Let’s explore some:

Long Shadow Selection

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 Selection

As per this article on CSS tricks, we can simulate a text outline by using text-shadow.

p::selection {
  color: #fff;
  text-shadow:
    -1px -1px 0 #000,
    1px -1px 0 #000,
    -1px 1px 0 #000,
    1px 1px 0 #000;
}

Blur Selection

Another interesting effect is to blur the text on selection. By making the color transparent, the text-shadow will still be there and mimics a blur effect.

p::selection {
  color: transparent;
  text-shadow: 0 0 3px #fff;
}

And I’m sure you can come up with more and more examples. The possibilities are endless with text-shadow.

Text Shadow and Performance

It’s recommended not to use a heavy text-shadow style as they will cause performance issues. I tried to cause a performance issue for you :D See below:

That neon effect is very heavy. Notice that while selecting the text, there is a lag between the time I select and the time that the selected style appears. Also, notice those glitches at the top and left sides. Please use text-shadow carefully.

Do Form Elements Got Selected?

The short answer is yes. For me, I found it weird to selected a page and found that the content inside an input is selected. See the figure below:

For example, the button text can be selected. We will come to discuss whether or not to allow selecting form elements in the user-select section.

Demo

However, things don’t stop there. Selection is more than just selecting text. In the next section, I will explain the user-select CSS property and how we can get the benefit of it.

Digging user-select Property

The user-select property gives us the ability to wether the user can select a specific text or not. It can be useful to disable text selection in some use-cases, which will be useful for the user to avoid selecting any unwanted neighboring content. (I borrowed the word neighboring from the CSS spec).

The possible values for the property are:

none, auto, text, contain, all

Use Cases

Text and Icon

If an element has an icon as a symbol or a font icon, then it will be selected within the text. This is not practical and not useful at all. Consider the following:

<button>Our Services<span aria-hidden="true"></span></button>

When selected, it looks like this.

That’s not necessary at all. Notice that it has the aria-hidden attribute to avoid exposing it to screen readers. We can use this:

button span[aria-hidden="true"] {
  user-select: none;
}

That way, we prevented the icon from being selected, and at the same time, this ties it to the aria-hidden attribute. So anything that shouldn’t be selected, is most likely shouldn’t be exposed to screen readers.

Checkbox Input

A common thing that I consider annoying is accidentally selecting the checkbox’s label while clicking on it. See the below figure:

This can be solved by adding the following to the <label> element:

label {
  user-select: none;
}

Select All Text

An interesting value for user-select is all. If applied to a parent element, all text contained within it will be selected with one click only. This could be useful for content that is related and should be selected all together. For example, selecting a code snippet.

.embed-code {
  user-select: all;
}

See the Pen Selection in CSS - Multiline by Ahmad Shadeed (@shadeed) on CodePen.

Web Apps

A web application should feel like a real application. Can you select the button’s text for a computer application? No, you can’t. On the web, it’s important to reflect that something feels like a real app, even if it’s made via HTML and CSS.

Let’s take some examples from the wild.

Slack

Slack allows selecting labels and inputs. However, the button’s content is not selectable.

And here is me selecting a modal title.

The interesting thing is that the chat date is not selectable.

It feels weird to select text in an app. Slack does have places where user-select: none is used, but it’s less than expected. As a user, I find no benefit at all from copying a modal title.

Notion

I like Notion better. It feels more like a real app, not a website that I can select its text.

For the figure above, none of the text is selectable, which is expected.

Don’t Disable Selection Globally

It’s a bad practise to disable text selection globally. When used, make sure to apply it to certain elements where selection is not useful. You can make a utility class for it, like the one below:

.disable-selection {
  -webkit-user-select: text;
  -moz-user-select: text;
  -ms-user-select: text;
  user-select: text;
}

A Common Dark Pattern

There is a UX pattern that annoys me which shows a warning when a user tries to select content from an article. This is annoying, and makes the user feel that he is controlled. It looks like the figure below:

Please, don’t do this..

Selection For Mobile

  • There is a property “ for iOS Safari that disables a callout which appears when the user select a text. I tried it, but it didn’t do anything.
p {
  -webkit-touch-callout: none;
}
  • ::selection styles doesn’t work.
  • The user-select: none works as expected.

I tried to include a real example which shows an issue from Wikipedia. I copied text, and the icon (listen) was copied with it. This is annoying. See the figure below:

Instead of coping “listen”, it’s better to add user-select: none to it so when selected, it won’t be copied with the text.

The End

That’s a wrap. Do you have a comment or a suggestion? Please feel free to ping me on @shadeed9.