CSSで、文字を選択したときの色を変える方法

​​CSS​HTML,Playwright,アクセシビリティ

文字をマウスでなぞって選択したときの色は、::selection という擬似要素に、文字の色(color)と背景色(background-color)を書いて変えます。ページ全体の色を :root::selection に書いておくと、注意書きなど一部分だけ別の色にしたいときに、その部分の指定がそのまま効きます。

補足

検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。HTML と CSS のページを Playwright で開き、JavaScript で文字を選択した状態にしてから、スクリーンショットの画素の色と、getComputedStyle() で読んだ ::selection の値を記録しました。マウスでドラッグして選択する操作、Firefox と Safari、スマートフォンの実機は試していません。各ブラウザの対応バージョンは、互換性データ(@mdn/browser-compat-data 8.1.8)の値です。

上下2つの画面。上の「何も指定しない」では、選択した2行の文字が、青い背景に白い文字で表示されている。下の「:root::selection と .note::selection で色を変えた」では、1行目が濃い水色の背景に白い文字、左に縦線のある注意書きの行が、太字の部分も含めて、薄いピンクの背景に濃い灰色の文字で表示されている
本文と注意書きを選択した状態。上はブラウザの標準の選択色、下はこの記事の CSS で色を変えたもの

ページ全体の選択色を変える

ページ全体の選択色は、次のように書きます。

css
:root::selection {
  color: #fff;
  background-color: #067a98;
}

検証環境で本文を選択すると、何も指定しないときは青い背景(rgb(51, 103, 209))に白い文字でした。この CSS を読み込むと、濃い水色の背景(rgb(6, 122, 152))に白い文字に変わりました。

::selection は古くから使える擬似要素で、互換性データでは Chrome 1、Edge 12、Firefox 62、Safari 1.1 から使えます。Firefox は 61 以前でも、::-moz-selection という接頭辞付きの名前で使えます。一方、互換性データでは、iOS の Safari は未対応(false)になっています。

:root は、HTML では <html> 要素のことです。:root::selection と書くと、<html> の選択色が決まり、その中の要素はこの色を受け継ぎます。単に ::selection と書いても、ページ全体の色は変わります。ただし、一部分だけ別の色にしたいときに困ることがあります(次の節で説明します)。

文字の色と背景色は、両方書く

文字の色と背景色は、片方だけ書くと、思った見た目になりません。検証環境で ■■■■ を選択して確かめました。

color だけを書いて赤にすると、文字は赤になりましたが、選択した範囲の背景は塗られず、白いままでした。選択していることが、文字の色でしか分かりません。反対に、background-color だけを書いて緑にすると、背景は緑になり、文字の色は選択する前の濃い灰色のままでした。

CSS の仕様(CSS Pseudo-Elements Level 4)では、ブラウザの標準の選択色は、文字の色と背景色を1組として扱うと決められています。作り手が color と background-color のどちらか片方でも指定すると、標準の組は両方とも使われません。片方だけ書くと、書いていないほうは標準の色に戻らず、背景なら塗られないままになります。

一部分だけ色を変えるときは、:root::selection に書く

注意書きの中だけ、選択色を薄いピンクにしたいとします。HTML は次のとおりで、注意書きの中に太字の <strong> があります。

html
<p>猫の手でも借りたい日は、まず深呼吸。</p>
<p class="note">注意:<strong>保存する前に</strong>閉じないでください。</p>

ページ全体の色を、:root を付けずに ::selection だけで書くと、太字の部分だけが、注意書きの色になりません。

css
/* ページ全体の選択色 */
::selection {
  color: #fff;
  background-color: #067a98;
}

/* 注意書きの中だけ、選択色を薄いピンクにする */
.note::selection {
  color: #1f2a30;
  background-color: #f7c6d2;
}
上下2つの画面。上の「::selection と .note::selection」では、注意書きの行のうち「保存する前に」の太字だけが、濃い水色の背景に白い文字になり、ほかの部分は薄いピンクの背景になっている。下の「:root::selection と .note::selection」では、注意書きの行が太字も含めてすべて薄いピンクの背景になっている
注意書きを選択した状態。上はページ全体の色を ::selection に書いたもの、下は :root::selection に書いたもの

検証環境では、上の CSS で注意書きを選択すると、「注意:」と「閉じないでください。」は薄いピンクの背景でしたが、「保存する前に」だけは濃い水色の背景に白い文字でした。

::selection は、*::selection を短く書いたものです。* はすべての要素に当てはまるので、<strong> の選択色にも、この規則が直接当たります。仕様の、選択色がどう受け継がれるかを定めた部分では、親の選択色を受け継ぐのは、その要素に当たる規則で、そのプロパティの値が決まらないときだけです。<strong> には ::selection の規則が当たり、color と background-color が決まっているので、親の .note の薄いピンクは受け継がれません。仕様にも同じ例があり、ページ全体の色は :root::selection に書くよう勧めています。

:root::selection に書き換えると、<strong> に当たる規則がなくなり、親の .note の色を受け継ぎます。検証環境でも、「保存する前に」が薄いピンクの背景になりました。

css
/* ページ全体の選択色は :root::selection に書く */
:root::selection {
  color: #fff;
  background-color: #067a98;
}

.note::selection {
  color: #1f2a30;
  background-color: #f7c6d2;
}

ページ全体の ::selection を書き換えられないときは、注意書きの中の子要素にも規則を当てます。.note ::selection(空白あり)は、.note の中にあるすべての要素の選択色を指定します。検証環境では、この規則を足すと、「保存する前に」も薄いピンクになりました。

css
.note::selection,
.note ::selection {
  color: #1f2a30;
  background-color: #f7c6d2;
}

使えるのは、色まわりのプロパティだけ

::selection に書いて効くプロパティは限られています。MDN の ::selection のページ(「利用できるプロパティ」の節)では、color、background-color、text-decoration と関連するプロパティ、text-shadow などが挙げられ、background-image は無視されると書かれています。仕様の、選択色に使えるプロパティを定めた部分によると、レイアウトに影響しないプロパティだけを使えるようにしているためです。

検証環境で、::selection に font-weight: 700 と padding: 20px を書いて選択しても、文字は太くならず、getComputedStyle() で読んだ値も font-weight が 400、padding が 0px のままでした。文字列の幅も、選択の前後で同じ 128px でした。

一方、text-shadow: 6px 0 0 rgb(255, 0, 0) を書くと、選択した文字に赤い影が出ました。text-decoration: underline 4px rgb(255, 0, 0) を書くと、選択した文字の下に赤い下線が引かれました。ただし、互換性データでは、::selection の中の text-decoration に対応しているのは Chrome と Edge の 105 以降で、Firefox と Safari は未対応です。どのブラウザでも同じ見た目にしたいなら、color と background-color だけで作るのが確実です。仕様にも、ブラウザの間でそろって動いてきたのは color と background-color だけだと書かれています。

入力欄の文字にも、選択色は効きます。検証環境で <input> と <textarea> に ::selection を書き、中身を select() で選択すると、どちらも指定した赤い背景に白い文字になりました。

読める組み合わせの色にする

選択した文字は、選択色の背景の上で読まれます。MDN の ::selection のページ(「アクセシビリティ」の節)では、選択色を見た目のためだけに変えないこと、変えるなら文字と背景のコントラスト比を十分に高くすることを勧めています。WCAG の基準では、通常の文字で 4.5:1 以上、大きな文字で 3:1 以上です。

この記事の組み合わせを、WCAG 2 の計算式で計算しました。

文字の色 背景色 コントラスト比
白 #fff 濃い水色 #067a98 4.95:1
濃い灰色 #1f2a30 薄いピンク #f7c6d2 9.75:1
白 #fff ピンク #d85878 3.76:1
白 #fff 水色 #00c8e8 2.01:1

白い文字に明るい水色やピンクの背景を組み合わせると、4.5:1 に届きませんでした。注意書きの選択色を、濃いピンクに白い文字ではなく、薄いピンクに濃い灰色の文字にしたのはこのためです。

​Posted by 86