Explain Codes LogoExplain Codes Logo

Prevent selection in HTML

html
responsive-design
best-practices
accessibility
Alex KataevbyAlex Kataev·Jan 13, 2025
TLDR

To prevent text selection in your web page, the crux is applying the CSS user-select: none; property on elements. Here's a brief one-liner to disable selection across the entire webpage:

* { user-select: none; /* Ah, the art of not selecting */ }

Legacy browser support

It's not a secret that some older versions of browsers can be pretty stubborn, specifically old IE and Opera versions. For these, we use the unselectable attribute. Let's see this antiquity at work:

<div unselectable="on" class="no-select"> Cannot touch this (get it, like the song...? Nevermind). </div>
var elems = document.querySelectorAll('.no-select'); Array.prototype.forEach.call(elems, function(el) { /* Who ya gonna call? */ el.setAttribute('unselectable', 'on'); });

Unselectability and dynamic content

Dynamic content too, like everything else on your page, has feelings and wishes to be "unselectable". Let's make that happen by utilizing recursion.

function makeUnselectable(node) { /* No node left behind */ if (node.nodeType == 1) { node.setAttribute("unselectable", "on"); } var child = node.firstChild; while (child) { makeUnselectable(child); child = child.nextSibling; } } // Usage: makeUnselectable(document.getElementById('content')); /* Operation: No Select */

Event-level mousedown prevention

Fun fact: sometimes CSS has its limits, and interactions like dragging laugh in its face. That's when we call JavaScript to the rescue:

document.addEventListener('mousedown', function(e) { e.preventDefault(); // Prevents text selection and drag events e.stopPropagation(); // Stops the event from bubbling up like hot lava }, false);

And jQuery can make managing this even simpler:

$(document).on('mousedown', function(e) { e.preventDefault(); /* Do not touch. Seriously. */ }).on('mouseup', function() { $(this).off('mousedown'); });

Vendor prefixes and pseudo-selection style

The beauty of modern browsers is their individuality - that's why vendor-specific prefixes for our CSS is an essential practice:

.no-select { -webkit-user-select: none; /* Safari */ -moz-user-select: none; /* Firefox */ -ms-user-select: none; /* IE 10+ and Edge */ user-select: none; /* "General" syntax */ }

Don't forget to adjust highlighting styles if you've customized using ::selection or ::-moz-selection:

.no-select::selection, .no-select::-moz-selection { background: none; }

Consider UX and accessibility

From an ethical standpoint, it's important to ponder on how disabling selection may affect interaction and accessibility. Any limiting feature should be considered for its potential limitations on the user experience.

Other interaction prevention methods

You may wish to stop users from dragging images on your pages. To do this without affecting text selection, we deal with this separately:

img { pointer-events: none; /* Images are not made for dragging */ }

For older browsers, here's a trick using a transparent overlay:

<img src="image.jpg" draggable="false"> <div class="overlay" style="position: absolute; width: imageWidth; height: imageHeight; top: imageTop; left: imageLeft;"></div>

Precision in selection behavior

Dynamic elements and refresh standards

In dynamic web environments, refreshing the user interface during interactions helps maintain smooth user experience:

document.addEventListener('mousemove', function(e) { // Your logic to refresh the UI here });

Image layering with z-index

For overlapping elements like overlays on images, manage their z-index for layering maintenance:

.overlay { z-index: 10; /* Overlay must sit higher than the image it protects */ }

Event listener clean-up

Managing events efficiently necessitate removing event listeners when not in use, especially for single-page applications and dynamic content:

$(window).on('mouseup', function() { $(document).off('mousemove'); /* Time for clean-up */ });