Make text unselectable and uncopyable (webkit, while surrounded by copyable text)
Asked Answered
D

5

14

The following snippet shows how to make text unselectable. Sadly, if you select text on either side in Chrome, when you copy and paste the unselected text also gets pasted.

Is there any way to have a lot of writing, with unselectable content throughout, that you can copy and paste and none of the unselectable content is pasted?

.hide {
  color: orange;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<div>Hello this text is selectable <span class="hide">but I'm not</span> You can select me all day!</div>

http://codepen.io/regan-ryan/pen/XdodGx

edit: This question does seem like a possible duplicate, seeing there are something like 12 questions already on this topic. However, I couldn't find my particular problem after extensive searching, so I thought it merits it's own question with a more particular question title.

Demott answered 4/5, 2016 at 12:17 Comment(1)
Possible duplicate of Unselectable and uncopyable text HTMLOram
C
26

More a workaround: you can exploit fact, that CSS generated content is invisible for clipboard (*), so with empty span with text moved to some attribute you have visually similar result with requested clibpoard behaviour:

[data-text] {
  color: orange;
}
[data-text]::after {
  content: attr(data-text);
}
<div>Hello this text is selectable <span data-text="but I'm not"></span> You can select me all day!</div>

http://codepen.io/myf/pen/jqXrNZ

If accessibility / SEO is not a concern, this could be the solution. In other case, it could be real text in HTML but moved to attribute with script 'on demand'.

(*) Update: as noted in comment ( How to disable text selection highlighting using CSS? ) Internet explorer actually involves CSS generated content in clipboard. Argh.

Chidester answered 4/5, 2016 at 12:28 Comment(3)
This works great! My content was being generated dynamically, so I ended up have a regex parse 3 groups, before-(no copy)-after. I then ran this JS line line = line.replace(spacerTextRegex, "$1<span class='spacer-text' data-uncopyable-text='$2'></span>$3");Demott
Putting text using CSS is a bad accessibility practice. Screen readers can't read this text.Mohler
@SylvainDNS Accessibility is a good point, but as far as I know, at least more recent screen readers parse and read CSS generated content quite well, considering it can be used as aid (see for example: adrianroselli.com/2017/12/tweaking-text-level-styles.html).Chidester
S
2

css can disable selection highlight but if you want use not to copy the text use this small piece of jquery code

$('.hide').on('copy paste cut drag drop', function (e) {
   e.preventDefault();
});

$('.hide').on('copy paste cut drag drop', function (e) {
       e.preventDefault();
    });
.hide {
  color: orange;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Hello this text is selectable <span class="hide">but I'm not</span> You can select me all day!</div>
Sissie answered 4/5, 2016 at 12:24 Comment(1)
This works well in Firefox but does not seem to be working in Chrome.Chidester
R
2

You can try to read the highlighted text with window.getSelection. Please try the following code example and look into the console. With this, you can remove the unwanted text from the string and copy it to the clipboard. But this isn't very simple, maybe not even possible. This is just an idea.

function getSelectedText() {
  console.log(window.getSelection());
}

document.onmouseup = getSelectedText;
document.onkeyup = getSelectedText;
.hide {
  color: orange;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
<!-- begin snippet: js hide: false -->
<div>Hello this text is selectable <span class="hide" unselectable="on">but I'm not</span> You can select me all day!</div>
Rosenblast answered 4/5, 2016 at 12:46 Comment(1)
looks unselectable, but I can still copy paste it with ChromeDemott
N
0

Use user-select: none; in style attribute or use in a css file.

Noggin answered 1/2, 2022 at 9:46 Comment(0)
G
0

The previous answer is good, but I wish to elaborate on a possible solution for a more stringent definition of uncopyable.

If we define 'uncopyable' to mean it can't be copied through:

  1. Text selection by mouse
  2. Opening the developer console and copying from HTML
  3. Copying it from a script file that has it embedded
  4. Copying it straight from a network request (e.g. the network request analyzer)
  5. Copying it through a fake screen reader

For example: you present the user with several secure token which you want to protect against being logged, living in a clipboard longer than intended, being read by an extension, etc.

Then the requirements are not met by a pure CSS approach, because you ultimately need to write data to a place which is accessible through the code or queried using javascript on the page.

If we exclude 'copying' to mean e.g. parsing the visuals of the page with something like OCR, querying pixels on the page or in elements, or actively manipulating the page (writing to it), then something like this works:

  1. A javascript function which does not keep state (globalThis can be read by extensions with certain permissions, etc)
  2. An ephemeral or function-call-life public-private keypair for the client generated client-side within the function, which you send the public key of to the server to get back a private key-wrapped secret, which you decrypt
  3. A HTML5 Canvas the function itself creates, uses a fillText call to write the pixels to the canvas, then adds the canvas to the DOM.

The canvas will then simply look like text in the DOM, but not be text-copyable or interceptable without breaking the encryption.

In the scenario where you are also worried about malicious interference that may be able to write to the document - you can write an extension that can take the private-key-wrapped payload and decrypt + display it within the extension, or pass pure pixels back and have a script on the page which can commit it to the DOM.

It's worth noting, of course, that any pixels written to the DOM can be read by other things on the page, which is why displaying it in an extension is the 'most secure' solution from our research - but doesn't do it inline like the question requested.

Gardia answered 7/12, 2023 at 10:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.