「テーマ色をユーザーに選ばせたい」「お絵かきツールのようにパレットから色を選びたい」——そんなときに使えるのが <input type="color"> です。クリックするとOSやブラウザ標準のカラーピッカーが開き、選んだ色を #rrggbb 形式の値として受け取れます。この記事では、基本的な書き方から、JavaScript での値の取得、input と change の使い分け、datalist によるプリセット色、そして見た目のカスタマイズの限界まで、初心者の方にも分かるように解説します。
目次
type=”color” でカラーピッカーを表示する
カラーピッカーは、input 要素の type に color を指定するだけで作れます。表示されるのは小さな色見本(スウォッチ)で、クリックするとブラウザやOSが用意した色選択ダイアログが開きます。自前でカラーパレットを実装しなくても、これ一行でネイティブのピッカーが手に入るのが大きな利点です。何のための入力欄かを伝えるため、label と結び付けておきましょう。
<label for="picker">色を選ぶ</label>
<input type="color" id="picker" name="picker">
ここで押さえておきたいのが、この入力欄が扱える値の形式は #rrggbb の16進カラー(7文字)に限られるという点です。赤・緑・青をそれぞれ2桁で表す形で、たとえば青なら #0000ff になります。透明度(アルファ値)には対応しておらず、#rgba のような8桁指定や rgb() ・色名(red など)は使えません。値を明示しなかったときの既定値は黒、つまり #000000 です。
value で初期色を指定する
最初に表示しておく色は value 属性で指定します。ここに書けるのも #rrggbb 形式だけです。次のように書くと、ピッカーは最初から青色を選んだ状態で表示されます。
<!-- 初期色を青にする -->
<input type="color" value="#3b82f6">
注意したいのは、value に #RRGGBB のような大文字や #fff のような3桁の短縮形を書いた場合の扱いです。仕様上は7桁の小文字が正となるため、大文字で書いてもブラウザ側で小文字に正規化され、後述する .value は必ず小文字で返ってきます。3桁の短縮形や不正な文字列を書くと、その指定は無視されて既定の #000000 に戻る点にも気をつけてください。
JavaScript で選ばれた色を取得する
ユーザーが選んだ色は、value プロパティで読み取れます。返ってくるのは常に #rrggbb 形式の小文字の文字列です。type="number" のように数値へ変換する必要はなく、そのままCSSの色として使えるのが扱いやすいところです。
const picker = document.getElementById("picker");
// 選択されている色を取り出す
console.log(picker.value); // "#3b82f6"(常に小文字の #rrggbb)
// そのまま CSS の色として使える
document.body.style.color = picker.value;
もし赤・緑・青の各成分を数値として使いたい場合は、文字列を切り出して16進から10進へ変換します。たとえば parseInt(picker.value.slice(1, 3), 16) で赤成分(0〜255)が得られます。
選んだ色をボックスに反映するデモ
実際にカラーピッカーを動かしてみましょう。下のデモは、ピッカーで選んだ色をボックスの背景に反映しつつ、現在の16進値を画面に表示します。スライダーを動かしている最中にも色が変わり続けることに注目してください。これを実現しているのが、次の節で説明する input イベントです。
<label for="picker">色を選ぶ:</label>
<input type="color" id="picker" value="#3b82f6">
<div id="box">この文字とボックスに色が反映されます</div>
<p>選択中の値: <output id="hex">#3b82f6</output></p>body {
font-family: sans-serif;
font-size: 15px;
}
label {
margin-right: 8px;
}
#box {
margin-top: 12px;
padding: 24px;
border-radius: 8px;
color: #fff;
font-weight: bold;
background: #3b82f6;
}
#hex {
font-family: monospace;
font-weight: bold;
}const picker = document.getElementById("picker");
const box = document.getElementById("box");
const hex = document.getElementById("hex");
// input はドラッグ中も連続で発火するので、リアルタイムに反映できる
picker.addEventListener("input", () => {
const color = picker.value; // 常に "#rrggbb" 形式の小文字
box.style.background = color;
hex.textContent = color;
});input と change の違いを理解する
カラーピッカーで値の変化を捉えるとき、input と change という2つのイベントが使えます。この2つは発火するタイミングが違い、用途に応じて選び分けます。
| イベント | 発火するタイミング |
|---|---|
input | ピッカー上で色を動かしている最中、値が変わるたびに連続して発火する |
change | 色が確定したとき(ダイアログを閉じるなど)に発火する |
プレビューをリアルタイムに更新して「今どの色か」を見せたいなら input が向いています。先ほどのデモも input を使っており、ドラッグ中でも背景色が追従します。一方、色が最終的に決まったときだけ処理したい——たとえばサーバーへ保存したり、重い再描画を走らせたりする場合は change が適しています。input は短時間に何度も発火するため、そこで重い処理を書くと動作が重くなる点に注意しましょう。
const picker = document.getElementById("picker");
// ドラッグ中も連続で発火:プレビューの更新に向く
picker.addEventListener("input", () => {
preview.style.background = picker.value;
});
// 色が確定したときだけ発火:保存などの確定処理に向く
picker.addEventListener("change", () => {
saveColor(picker.value);
});
なお、input と change のどちらが「連続」でどちらが「確定」かは、テキスト入力欄とは感覚が異なるので混同しがちです。カラーピッカーでは「リアルタイム=input、確定=change」と覚えておくとよいでしょう。
datalist でプリセットの色を用意する
ブランドカラーやよく使う色をあらかじめ候補として出したいときは、list 属性と datalist 要素を組み合わせます。input の list に datalist の id を指定し、候補の色を option の value に #rrggbb で並べます。対応しているブラウザでは、ピッカー内にこれらの色がスウォッチとして表示され、ワンクリックで選べるようになります。
<input type="color" value="#e11d48" list="presets">
<datalist id="presets">
<option value="#e11d48"></option>
<option value="#3b82f6"></option>
<option value="#22c55e"></option>
</datalist>
ここで表示されるのはあくまで「候補(サジェスト)」で、ユーザーはこの候補以外の色も自由に選べます。特定の色だけに限定する仕組みではない点に注意してください。また、datalist の表示のされ方はブラウザによって差があり、候補が出ない環境もあります。あくまで便利な補助と考えるのがよいでしょう。
選んだ色をCSS変数に反映する
取得した色は文字列としてそのままCSSに渡せるので、CSSカスタムプロパティ(CSS変数)に流し込むと、ページ全体のテーマ色を一括で切り替えられます。element.style.setProperty("--変数名", 値) で変数を書き換えると、その変数を var() で参照しているすべての箇所に反映されます。下のデモでピッカーの色を変えて、カードの枠線・見出し・ボタンがまとめて変わる様子を確かめてみてください。
<label for="theme">テーマ色:</label>
<input type="color" id="theme" value="#e11d48"
list="presets">
<datalist id="presets">
<option value="#e11d48"></option>
<option value="#3b82f6"></option>
<option value="#22c55e"></option>
<option value="#f59e0b"></option>
</datalist>
<div class="card">
<h3>プレビュー</h3>
<p>CSS 変数に色を流し込んでいます。</p>
<button>ボタン</button>
</div>body {
/* ここに選んだ色が入る */
--theme: #e11d48;
font-family: sans-serif;
font-size: 15px;
}
.card {
margin-top: 12px;
padding: 16px;
border: 2px solid var(--theme);
border-radius: 8px;
}
.card h3 {
margin: 0 0 8px;
color: var(--theme);
}
.card button {
padding: 6px 16px;
border: none;
border-radius: 4px;
color: #fff;
background: var(--theme);
cursor: pointer;
}const theme = document.getElementById("theme");
// 選んだ色を CSS 変数 --theme に反映する
theme.addEventListener("input", () => {
document.body.style.setProperty("--theme", theme.value);
});このように「1つのピッカーで色を選ぶ → CSS変数を更新 → 複数の要素へ反映」という流れにしておくと、色に関するコードが一か所にまとまり、テーマ切り替えの実装がぐっと楽になります。
見た目を思うようにスタイリングできないとき
type="color" は便利ですが、入力欄そのものの見た目はブラウザやOSに強く依存します。ボタンの形や色見本の表示のされ方はブラウザごとに異なり、CSSで細部まで統一するのは難しいのが実情です。ここでつまずいたときの考え方を整理します。
スウォッチ部分の余白や角を調整する
色見本を表示している内側の部分は、WebKit系ブラウザ(Chrome や Safari)では擬似要素で指定できます。色そのものが表示される領域が ::-webkit-color-swatch、その外側の枠が ::-webkit-color-swatch-wrapper です。枠線や角丸を消して、余白を詰めるといった調整に使えます。
input[type="color"] {
width: 48px;
height: 48px;
border: none;
padding: 0;
cursor: pointer;
}
/* 色が表示される内側の領域(WebKit系) */
input[type="color"]::-webkit-color-swatch {
border: none;
border-radius: 50%; /* 丸いスウォッチにする */
}
/* その外側の余白部分(WebKit系) */
input[type="color"]::-webkit-color-swatch-wrapper {
padding: 0;
}
これらは接頭辞から分かるとおりWebKit系ブラウザ向けの擬似要素で、すべてのブラウザで同じように効くわけではありません。Firefox では ::-moz-color-swatch という別の擬似要素になるなど、対応状況はブラウザによって異なります。
見た目を完全に統一したいとき
どうしてもデザインを揃えたい場合は、type="color" の入力欄自体を opacity: 0 などで見えなくして重ね、その上に自分でデザインしたボタンや色見本を置く、という手法がよく使われます。クリックは下に隠したネイティブのピッカーが受け取るため、標準のカラーピッカーの使い勝手を保ちつつ、見た目だけを自由に作れます。ただし実装は複雑になるので、まずは擬似要素での調整で足りないかを検討するとよいでしょう。
まとめ
<input type="color"> は、ネイティブのカラーピッカーを一行で用意できる便利な入力部品です。要点を整理します。
- 扱える値は
#rrggbb形式の小文字16進のみ。アルファ値は非対応で、既定値は#000000。 - 初期色は
valueで指定し、.valueは常に小文字の#rrggbbを返す。 - リアルタイム反映は連続発火する
input、確定処理はchangeを使う。 list属性+datalistでプリセット色を候補として出せる(あくまで候補で限定はしない)。- 見た目はブラウザ依存。
::-webkit-color-swatchなどで一部調整できるが、完全な統一は難しい。
まずは value で初期色を決め、input イベントで .value を取り出してプレビューやCSS変数へ反映するところから試すと、カラーピッカーの扱いがつかめます。