CSS
この記事では、要素内の文字や画像を選択できるかどうかを制御するCSSのuser-selectを説明します。
Controls whether users can select text or images inside an element.
user-select
user-select は、UI部品や本文などで「テキストを範囲選択できる/できない」を切り替えるためのCSSです。
- Table Of Contents
このページでできるようになること
- タブ・ボタン風UIで、ダブルクリックやドラッグ時に文字が選択されるのを防げる
- 注文番号・クーポンなど、コピーしてほしい文字列を一発で全選択にできる
autoが「継承しないのに親の影響を受ける」理由を説明できる- クリック可否(
pointer-events)と選択可否(user-select)を混同せずに使い分けられる - 効かないときに DevTools の Computed を使って原因を追える
- 試験で出やすい“ひっかけ”を、選択問題の形で判断できる
まずは直感:user-select って何?
user-select は、要素の中身(主にテキストや画像)をユーザーが範囲選択できるかどうかを切り替える設定です。
よくある用途は「UI部品では選択させない」「コピーしてほしい文字列は選択しやすくする」の2つです。
見た目やレイアウト(幅・高さ・配置)は変わりません。クリックやタップの可否も変わりません。
最小デモ:まず動かす
まずは none(選択不可)と all(一発全選択)を体感します。
このテキストは普通に選択できます。
このテキストは選択できない設定になっています。
一度のクリックで、このテキスト全体を選択できます。
HTML
<p>このテキストは普通に選択できます。</p>
<p class="unselectable">このテキストは選択できない設定になっています。</p>
<p class="all">一度のクリックで、このテキスト全体を選択できます。</p>
CSS
.unselectable {
user-select: none;
}
.all {
user-select: all;
}
基本の書き方(最短の型)
実務では外部CSS(共通CSSやページCSS)に書くのが基本で、インラインやJavaScriptでの指定は例外として扱います。
CSS
/* UIの誤選択を防ぐ */
.button-like {
user-select: none;
}
/* コピーさせたい文字列を一発で全選択 */
.copy-token {
user-select: all;
}
正確な定義(仕様に沿った説明)
user-select は、ユーザー操作(ドラッグ、ダブルクリック、長押しなど)による「選択」のしやすさを制御します。
対象はすべての要素です。レイアウトや描画(表示/非表示)を変えるプロパティではありません。
user-select: none は“操作を抑制する”だけで、DevToolsやJavaScript、画面キャプチャなどによる取得まで防ぐものではありません。情報保護の仕組みではありません。
- 初期値
auto- 適用対象
- すべての要素
- 継承
- なし
※継承はしないが、autoの計算値は親要素の値に影響される。 - 計算値
- 指定値
- アニメーションの種類
- 離散(discrete)
指定できる値(まず覚える4つ)
none- 対象要素とその子孫要素のテキストは範囲選択できません。
text- ユーザーはテキストを範囲選択できます。選択範囲は要素境界をまたいで拡張できます。
all- 要素の内容が不可分に選択されます。部分的に選ぶと、その要素全体が選択されるイメージです。
auto- 状況に応じて自動決定されます(次の章で“なぜそうなるか”を押さえます)。
contain は仕様上は存在しますが、主要ブラウザでほとんど実装されていないため実務で使える場面はほぼありません(試験では“存在する値”として知識整理だけしておくと安全です)。
仕様として押さえるポイント(ここで事故を防ぐ)
継承しない、でも auto は親の影響を受ける
user-select は継承しません。ただし auto の使用値は親の計算値を参照して決まるため、結果として“継承しているように見える”ことがあります。
HTML
<div class="parent">
<p>親は選択不可(none)</p>
<p class="child">子は指定なし(auto)でも、親の影響で選択不可になります</p>
<p class="child text-select">この子だけ text に戻すと選択できます</p>
</div>
CSS
.parent {
user-select: none;
}
.child {
/* 指定なし(auto) */
}
.text-select {
user-select: text;
}
親は選択不可(none)
子は指定なし(auto)でも、親の影響で選択不可になります
この子だけ text に戻すと選択できます
auto の使用値(ざっくり結論 → ルール)
結論としては「だいたい text だが、親が none/all なら引っ張られる」と覚えると実務で迷いにくいです。
::beforeと::afterの疑似要素では、計算値はnoneになります。- 編集可能な要素(
input/textarea/contenteditable="true")では、ユーザーが編集・選択できる状態になります。 - 上記以外で、親要素の計算値が
allの場合、対象要素もallになります。 - 上記以外で、親要素の計算値が
noneの場合、対象要素もnoneになります。 - それ以外は
textになります。
離散アニメーション(パッと切り替わる)
user-select は途中の中間値がないため、値を変えると“段階的に”ではなく“切り替え”になります。
よくある勘違い・混同ポイント
user-select- テキストや画像を範囲選択できるかを制御します。クリック可否は変わりません。
pointer-events- クリックやタップなどポインター操作の当たり判定を制御します。テキスト選択の可否とは別です。
display/visibility- 表示状態を制御します。
user-selectは表示を変えません。 -webkit-touch-callout- iOS Safari系で長押し時に出るメニュー(コールアウト)表示に関係します。
user-selectと併用されることがあります。 cursor- 見た目のカーソルを変えるだけで、選択可否・クリック可否を保証しません。
実務でよくある使用例(制作会社の現場)
ボタン風UIでテキスト選択を防ぐ
CSS
.button-like {
user-select: none;
}
タブ切り替えやカードUIなどで、ダブルクリックやドラッグ時に文字が選択状態になるのを防げます。
コピーしやすくする(注文番号・クーポン・コード)
ABCD-1234-EFGH
CSS
.all {
user-select: all;
}
適用範囲を絞る(フォームは生かす)
CSS
.ui-area {
user-select: none;
}
/* 入力欄や編集可能要素は選択できる状態に戻す */
.ui-area input,
.ui-area textarea,
.ui-area [contenteditable="true"] {
user-select: text;
}
UI領域をまとめて none にしつつ、入力や編集は巻き込まないのが安全です。
一部のテキストだけ選択できるようにする
親(または文章全体)を none にしてから、選択したい部分だけ text で上書きします。
このテキストは「一部」だけ、範囲選択ができます。
HTML
<p class="unselectable">このテキストは「<span class="text-select">一部</span>」だけ、範囲選択ができます。</p>
CSS
.unselectable {
user-select: none;
}
.text-select {
user-select: text;
}
実務で起きがちな事故と回避策(効かないを最短で潰す)
まず DevTools の Computed で最終値を見る
- Elements → 対象要素を選択 → Styles で
user-selectの宣言元(どのCSSが効いているか)を見る - Computed →
user-selectの最終値(勝った値)を確認する - 親要素の
user-selectがnone/allになっていないかも合わせて見る(autoの影響)
よくある症状と原因候補
- 指定したのに選択できてしまう
- 別のCSSが後から上書きしている/詳細度が高いルールに負けている/JavaScriptでインライン指定されている可能性があります。Computedで最終値を確認します。
- 入力欄まで選択できなくなった
input/textarea/[contenteditable]まで巻き込んでいる可能性があります。適用範囲を絞るか、対象だけtextに戻します。- 一部だけ選択したいのにうまくいかない
- 親に
noneを当てた上で、選択したい要素にtextを明示して上書きします。 - クリックも止めたい
user-selectではなくpointer-eventsを検討します(ただしキーボード操作やアクセシビリティにも影響が出やすいので用途限定)。
詳細度で負けるパターン(最小の注意)
同じ要素に複数の user-select が当たる場合、基本は「詳細度 → 後勝ち」の順で勝ち負けが決まります。UI全体に .ui-area * のような広域指定をすると、意図せずフォームまで巻き込みやすいので注意します。
モバイルでの挙動(長押し・メニュー)
スマートフォンでは長押しによる選択やコンテキストメニューの表示に影響します。特にiOS Safari系では -webkit-touch-callout と併用されることがあります。
CSS
.sample {
user-select: none;
-webkit-touch-callout: none;
}
アクセシビリティ/UX観点での注意
- 本文や規約など「読んでコピーする可能性がある文章」に安易に
user-select: noneを付けない(UXを下げやすい) - 問い合わせ番号・クーポンなどコピーが前提の情報は
user-select: allの方がUXが上がる user-selectはテキスト選択の話であり、スクリーンリーダーの読み上げ可否とは別です(“選択できない=読めない”ではない)
関連プロパティ・関連セレクタとの組み合わせ
pointer-events- クリック/タップの当たり判定を制御します。テキスト選択を止めたいだけならまず
user-selectを検討します。 -webkit-touch-callout- iOS Safari系で長押しメニュー表示に関係します。
[contenteditable="true"]- 編集可能要素。
autoの挙動にも関係します。 ::before/::afterautoの計算でnoneになる例外を持ちます。
試験(Webクリエイター能力認定試験)で得点できる整理
用語ミニ辞典(短く)
- 継承(inheritance)
- 親の値が子に自動で引き継がれる仕組み。
user-select自体は継承しません。 - 初期値(initial value)
- 指定しなかった場合の出発点。
user-selectの初期値はautoです。 - 計算値(computed value)
- 継承や単位換算などを反映した値。
- 使用値(used value)
- 実際の挙動に使われる最終値。
autoは条件で使用値が変わります。 - 詳細度(specificity)
- どのCSSが勝つかの強さ。基本は「詳細度 → 後勝ち」。
ひっかけポイント(短く)
user-select: noneでクリックも無効になる → ×(クリックは別。必要ならpointer-events)user-selectは継承する → ×(継承しない。ただしautoは親の影響を受ける)autoは常にtextと同じ → ×(親がnone/allなら引っ張られる など条件あり)
ミニ確認(判断する形)
- Q1.
.ui-area { user-select: none; }の中にあるinputまで選択できなくなった。最短の修正は? - A.
.ui-area input { user-select: text; }のように、入力系だけtextで上書きします。 - Q2. 子要素に指定していないのに選択できない。親に
user-select: noneがある。子のuser-selectは継承している? - A. 継承ではありません。子が
autoのままだと、使用値決定のルールで親の影響を受けます。 - Q3. コピー禁止にしたいので
user-select: noneを付けた。これで情報保護になる? - A. なりません。通常操作での選択を抑制するだけで、DevToolsやJavaScript、キャプチャなどは別です。
よくある質問(FAQ)
user-selectが効かないのはなぜ?- DevTools の Computed で
user-selectの最終値を確認し、上書き(詳細度/後勝ち)や親のnone/allを疑います。 - 一部だけ選択できるようにしたい
- 親(または文章全体)を
user-select: noneにして、選択したい要素だけuser-select: textで上書きします。 - スマホで長押しメニューを出したくない
user-selectに加えて、iOS Safari系では-webkit-touch-calloutの影響を受けることがあります。- コピーを完全に防げますか?
- 通常の選択操作は抑制できますが、情報保護の機能ではありません。コピー禁止を前提に設計しないのが安全です。
- クリックも無効にしたい
user-selectではなくpointer-eventsを検討します。ただし操作性やアクセシビリティへの影響が大きいので用途限定です。
よくあるエラー/症状 早見表
- 症状:選択できない
- 原因候補:親が
none/JSでインライン指定/広域セレクタで巻き込み。確認:Computedの最終値。解決:必要箇所だけtextへ上書き。 - 症状:選択できてしまう
- 原因候補:別ルールに負けている。確認:Stylesで宣言元。解決:詳細度を上げるか後勝ちにする。
- 症状:フォームが使いづらい
- 原因候補:
input/textareaを巻き込んだ。確認:対象要素のComputed。解決:フォームだけtextに戻す。 - 症状:スマホで長押しメニューが出る/出ない
- 原因候補:
-webkit-touch-callout。確認:iOS Safariで再現。解決:必要なら併用。
まとめ:迷ったときの判断軸
- UI部品(タブ/ボタン風/ドラッグがある領域)→
user-select: none - コピーしてほしい番号・コード →
user-select: all - 入力/編集(
input/textarea/[contenteditable])→ 巻き込まない、必要ならtextに戻す - 効かないとき → DevTools の Computed で最終値 → 親の影響(
auto)と上書きを確認