Q. HTML のコピー禁止をするにはどうすればいいですか?

古典的な回答:

<body oncopy="return false;"
  oncontextmenu="return false;">

要するにコピーイベントおよびポップアップメニューを無効(return false)にしてしまう。 なお、div要素など個別に指定もできるので、 下記のように指定区域のみコピー禁止的なこともできる。

ここはコピーできない!?
  • div要素など一部分に指定した場合、それよりも外側を選択したらコピーできる。(イベントリスナが捕捉できないため。)
  • Firefox だと Shift+右クリック でポップアップメニューを開けるのでコピー可能。
  • unix/linux などの X window system だと選択した時点で領域選択が完了するので、マウスの中ボタンクリックでそのままペーストできてしまう。
  • JavaScript を無効にするとコピー可能。

というわけで、選択さえさせないということにしないというソリューションに発展していくこととなる。 HTML 5 標準には含まれていないが、最近は user-select なる CSS プロパティがある。 user-select に対して none と指定すれば、そのまま選択不能となる。

なお、下記の通り vender prefix が必要だ。

Browser Property Name
Webkit (Safari/Chrome) -webkit-user-select
KHTML (Konqueror/Safari/Chrome) -khtml-user-select
Gecko (Firefox) -moz-user-select
Trident (Internet Explorer) -ms-user-select

なお、IE は IE10以降である。

さらに IE9 以前には selectstart イベントが捕捉できるので、これをキャンセルすればよい。

<body style="-webkit-user-select: none; -khtml-user-select: none; -ms-user-select: none; -moz-user-select: none; user-select: none;"
      onselectstart="return false;">

なお、onselectstart の動作に目をつぶれば、 下記のように指定区域のみ禁止的なこともできる。

ここはコピーできない!?

Q. `user-select: none` 指定されたテキストをコピーするにはどうすればいいですか?

たとえば、Firefox だったら Web Console なり Scratch Pad なりに 以下を入力して実行。

Array.forEach(window.document.getElementsByTagName("*"), function(v){v.style.MozUserSelect="";}));

なにはともあれいかなる努力を持ってしても、 ソースコードなりDOM 構文木にアクセスできる術があるので、 コピーを本当の意味で無効にするのは無理である。 (面倒にさせることはできる。) テキストに限ってコピペされたくないのなら、 コピー禁止PDFにでもすればよいだろうし。

どちらかというと、user-select: none は 全体コピー禁止選択禁止とかではなく、 小技的にコピペをより便利にするような目的で使うようになって欲しいものである。