CSS How do you prevent a button with user-select: none from selecting outer text on mobile?

Viewed 563

Take a look at this (overly simplified) snippet:

HTML

<div class="container">
    <button class="no-select">Button</button>
    Container Text
</div>

CSS

.no-select {
    user-select: none; /* For comprehension sake, pretend this works for every browsers */
}

When clicking, dragging or double-clicking the button on desktop, it works as expected: the text inside the button is not highlighted.

Long-pressing the button on mobile still doesn't select the text inside the button, but instead starts selecting the parent's text. More precisely, it selects the next "selectable" thing it can. In this case, it would be the container text (Container Text). I've only tested on iOS, someone could confirm for other devices?

You can also see this behavior on Material-UI's buttons. Long-press one of the buttons on iOS and you will see the bug.

How do you prevent this behavior from happening?

1 Answers

Nodes in an HTML document bubble most events to its parent (and subsequent parents) that are not captured by the child. This is what you are seeing.

If you want to avoid the parent's other text from being selected when the child is (long) pressed, try wrapping the other text in a separate element.

<div class="container">
  <button class="no-select">Button</button>
  <span class="container-text">Container Text</span>
</div>

Generally, it's good practice to not leave bare text next to other HTML elements as it can break semantic reasoning. However, in some instances it can be acceptable, such as anchor tags or inline text buttons.

Related