As an experienced full-stack developer, I often need to make certain text unselectable on websites for security, privacy, or design reasons.
Whether it‘s sensitive personal data, credit card numbers, code snippets, or simply visually-focused text elements that shouldn‘t be highlighted, disabling text selection is a common requirement.
Fortunately, CSS provides simple and flexible ways to make text unselectable with broad browser support. In this comprehensive guide, I’ll share professional techniques and best practices for preventing text selection.
Technical Primer on How Text Selection Works
Before looking at the code, it helps to understand what’s happening technically when users select text on a web page.
When text is highlighted, the browser renders a transparent overlay dividing the selected portion from the rest. This overlay fills with the highlight color (typically pale blue), allowing the selected text to stand out visually.
Several CSS properties control this selection overlay and color:
::selection {
color: #fff;
background: #3399ff;
}
So to make text unselectable, the core idea is removing that visual highlight when users select it. This can be achieved by:
- Styling the selection overlay differently
- Disabling the ability to select text altogether
The user-select property and ::selection pseudo-element give us these capabilities.
Now let’s walk through them in detail, including advanced usage.
1. Using the user-select Property
The user-select CSS property determines if text can be selected or not.
For example, to disable text selection:
p {
user-select: none;
}
User highlighting is now blocked on all <p> elements.
user-select accepts a few different values:
.auto {
user-select: auto; /* Default browser behavior */
}
.text {
user-select: text; /* Text can be selected */
}
.none {
user-select: none; /* Text cannot be selected */
}
.all {
user-select: all; /* Text and sub-elements can be selected */
}
This gives you precise control over text selection behavior.
Browser Support
The user-select property has excellent cross-browser support:
| Browser | Version |
|---|---|
| Chrome | 1+ |
| Edge | 12+ |
| Firefox | 3.5+ |
| Safari | 3.1+ |
| Opera | 9+ |
| iOS Safari | 3.2+ |
| Android Browser | 2.1+ |
| IE | 10+ |
So you can use it quite safely without worrying about legacy browser issues nowadays.
Use Cases for Disabling Text Selection
There are many reasons why you may want to disable text selection, for example:
- Masking credit card or personal identity information like SSNs
- Preventing users from copying code snippets easily
- Creating text-heavy designs where highlighting would be visually disruptive
- Highlighting key text elements like headings by preventing selection
Here are some real-world examples:
| Site | Unselectable Text Elements |
|---|---|
| Banking & Finance | Account numbers, credit cards, SSN, passwords |
| News & Media | Article titles, captions, citations |
| Software Docs | Code blocks, credentials |
| Legal | Sensitive clauses, citations |
Of course, you’ll want normal body text to remain selectable so users can copy it. Use good judgment when applying user-select: none;.
Allow Selection on Child Elements
A neat trick with user-select is allowing text selection on child elements even when it’s disabled on the parent:
.parent {
user-select: none;
}
.parent .child {
user-select: text;
}
So the text remains selectable on .child elements inside .parent.
For example:
<div class="parent">
<p>Non-selectable parent text</p>
<div class="child">
<p>But child text is selectable</p>
</div>
</div>
This granular control over selection behavior is quite useful in some cases.
2. Using the ::selection Pseudo-Element
An alternative approach is styling the selection itself using the ::selection pseudo-element.
For example, this removes the highlight color when text is selected:
::selection {
background: transparent;
}
While users can still technically select the text, there will be no visual highlight effect.
Compatibility Notes
::selection has excellent browser support:
| Browser | Version |
|---|---|
| Chrome | 1+ |
| Edge | 12+ |
| Firefox | 2+ |
| Safari | 3.1+ |
| Opera | 9+ |
| IE | 9+ |
It’s also supported on all major mobile and tablet devices. So you don’t need to worry much about cross-browser issues.
Do note that Firefox doesn’t allow styling across element boundaries:
❌ This won’t work:
p::selection {
color: #fff
}
⚠️ But this is okay:
::selection {
color: #fff
}
So with Firefox, apply ::selection styles globally rather than on specific elements.
Styling Capabilities
These properties can be used with ::selection:
colorbackground-colorcursoroutline
That’s more limited than normal CSS, but playing with color and transparency gives you good control over selected text appearance.
Some examples:
/* Make selected text transparent */
::selection {
background: transparent;
}
/* Remove selection outline */
::selection {
outline: none;
}
/* Change text and background colors */
::selection {
color: black;
background: lightgrey;
}
Get creative with different styles and effects!
Security Considerations
One downside of ::selection compared to user-select is that text remains selectable and copyable even if the visual highlight is removed.
So for security use cases, combine ::selection styles with user-select: none to also disable selection, along with JavaScript validation for maximal protection.
Unselectable Text Security Best Practices
When dealing with sensitive text that shouldn’t be copied, some additional precautions are recommended:
Use JavaScript Validation
While CSS handles presentation, JavaScript actively prevents unauthorized actions like highlighting protected text or disabling right-clicks.
For example:
function disableSelect(targetElement) {
targetElement.onselectstart = function() {
return false;
};
targetElement.style.MozUserSelect = "none";
targetElement.style.webkitUserSelect = "none";
}
This offers an extra layer of protection that CSS alone may not provide.
Monitor Clipboard Access
Watch for copy/cut events to prevent unauthorized copying attempts:
document.addEventListener(‘copy‘, function(event) {
event.preventDefault();
});
Use Session Storage
Rather than displaying protected info directly in the DOM, use sessionStorage to keep it in-memory client-side and then render securely with JS.
Limit Internal Access
Restrict which users and roles can view protected text in the first place through authentication and authorization.
Transport via HTTPS
Always transfer sensitive data over secure HTTPS connections to prevent man-in-the-middle attacks.
So in high-risk scenarios, utilize a blend of methods for defense-in-depth.
Additional Tips and Tricks
Here are some more tips from my many years disabling text selection professionally:
Change Cursor Style
Subtly indicate unselectable text using the cursor property:
.unselectable {
cursor: not-allowed;
user-select: none;
}
Combine user-select + ::selection
Using both techniques together gives you optimal cross-browser support and more styling options:
p {
user-select: none; /* Disable selection */
}
p::selection {
background: transparent; /* Hide highlight */
}
Prevent Form Interactions
Make unselectable text non-focusable and non-submittable for forms:
.unselectable {
user-select: none;
pointer-events: none;
}
This disables mouse events.
Use Background Clip
Here’s another clever trick – hide text in the selection overlay while keeping it visible otherwise:
::selection {
background: white;
-webkit-background-clip: text;
background-clip: text;
color: rgba(0,0,0,0);
}
The text vanishes when highlighted!
Let me know if you have any other clever CSS selection techniques.
Unselectability Myths & Misconceptions
Having disabled text selection across hundreds of sites and apps, there are a few common myths worth dispelling:
Myth: It creates huge accessibility issues
Reality: By only applying to small portions of text, most pages remain keyboard/screenreader friendly.
Myth: Mobile devices won’t respect the rules
Reality: iOS, Android, etc fully support both user-select and ::selection.
Myth: There are major browser compatibility problems
Reality: All modern browsers have excellent support, with fallbacks available.
Myth: It completely blocks copying
Reality: Text can still be accessed by disabling CSS, though extra measures like JS help.
Myth: It’s annoying for users
Reality: When applied judiciously to small sections, most users won’t care or even notice.
Hopefully this reassures anyone hesitant about unselectable text thinking it has major downsides. With mindful usage, it’s quite safe and low-impact.
Now let’s round up everything we’ve covered…
Key Takeaways
Here are the core highlights:
- The
user-select: noneproperty disables text selection - The
::selectionpseudo-element styles the highlight effect - Browser support is excellent overall
- Balance security without harming DX excessively
- Combine CSS with JS validation for high-risk scenarios
- Carefully apply to small sections of text only
Making text unselectable is quite straightforward with native CSS capabilities.
While no approach is 100% bulletproof, user-select and ::selection give you powerful options to disable – or visually hide – selectable text when needed.
So don’t be afraid to leverage them on your sites and apps!
I hope this guide has demystified the process and given you ideas for your own projects. Let me know if you have any other questions!


