Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I prevent a certain element's text being copied to the clipboard?

Before someone suggests it: no, user-select isn't the correct answer.

Daniel O'Connor's pure CSS method is close but I can't use it for my use case because of those "Accessibility concerns".

I need a better way of doing the same thing. I can't think of how it'd be done; I don't think there's a reliable cross-browser compatible way of copying something to the clipboard with JavaScript. So I think it has to be a HTML & CSS solution.

Edit

I say "I don't think there's a reliable cross-browser compatible way of copying something to the clipboard with JavaScript" because one solution could've been to catch when the copy event (if that's even supported everywhere). I just realised though even if "there's a reliable cross-browser compatible way of copying something to the clipboard with JavaScript", this probably wouldn't work when a user copies the text on a mobile device. Correct me if I'm wrong.

Edit 2

I'm not trying to block people from copying the text in any way. I'm not trying to block access to the text. That's impossible and discouraged anyway. I'm just trying to make it nicer for users who are copying N number of elements' text from my app who end up with unimportant stuff in the clipboard (like timestamp elements' text, etc.)

like image 897
Adam Lynch Avatar asked Mar 17 '23 11:03

Adam Lynch


2 Answers

New Answer

You want to automatically omit certain parts of the text when users select and copy it.

I know two solutions for this:

  1. Put the text in different parent elements
  2. Hide the unwanted elements when the user starts selecting

Solution #1 is usually used for source code with line numbers. By clever applying CSS, two DIV's are aligned vertically so that each line number appears to be on the left of the correct line of source code (which is actually in a different DIV).

That way, you can drag your selection in the source code without getting any of the line numbers. This works well for information that can be displayed in boxes that are vertically/horizontally aligned or, to use a different picture, if you could put things into different table cells.

Solution #2 responds to the first mouse click and applies display: none to elements with a certain class like omit-during-copy.

The advantage of this approach is that the user can see what they are copying (i.e. the unwanted information is vanishing).

The disadvantage is how/when to revert the state.

A variant of this is to use absolute positioning to make elements appear in a certain place. This becomes tedious very quickly if your have to apply the technique to things like aHIDEb - you will have to put enough empty space between a and b to display HIDE between them, then place HIDE pixel perfect in the gap. Not impossible but I'd try to rearrange the information first.

Old Answer

There are two ways to prevent a user from copying text from your HTML page:

  1. Don't display it
  2. Use a password field

Let me explain: There is a small amount of things that you can try with JavaScript in the page itself. If you swallow Ctrl+C, then people will use the mouse. If you swallow the mouse button in the page, they will use the menu bar. If you disable the menu bar of the browser, people will deactivate the option "Allow JavaScript to hide the menu bar".

If you use a password field, people will use the JavaScript console or the "Show Source" or they'll use tools like Tampermonkey to get rid of your pesky intrusion into their lives.

You can try to display an image with the text instead. People will then use OCR. So even if you used a Flash-based HTML viewer to replace the whole page, people could still copy the text. But it would make them pretty mad.

Personal note: I tend to visit pages which try things like that once and briefly at that. I tend to remember such sites for a long time and with very negative emotions. So if I were you, I try this only to drive people away from my site.

like image 92
Aaron Digulla Avatar answered Apr 01 '23 13:04

Aaron Digulla


In case someone is still looking for a way to prevent copying unimportant elements (such as line numbers), the answer is to use pseudo elements:

.code {
  white-space: pre;
  font-family: monospace;
  padding-left: 40px;
}
.line-number {
  position: absolute;
  left: 0;
  width: 38px;
  color: #888;
  text-align: right;
}
.line-number::before {
  content: attr(data-line-number);
}
<div class="code">
<span class="line-number" data-line-number="1"></span>const greet = () => {
<span class="line-number" data-line-number="2"></span>  console.log("Hello World!");
<span class="line-number" data-line-number="3"></span>};
</div>
like image 30
riv Avatar answered Apr 01 '23 12:04

riv