カラーピッカーColor picker
丸い色見本を並べて1つ選ばせ、その下にカラーコードの欄と自由に色を選ぶボタンを置いた入力。テーマ色やラベルの色のように、色そのものを決めてもらうときに使う。
表示例
アイコン: Font Awesome 7 Free(fa-solid / fa-regular)
別名・英語表記
- 色選択
- カラーセレクター
- 色見本
- カラースウォッチ
- 色を選ぶ欄
- Color picker
実装例
<fieldset class="x-color-picker">
<legend class="x-color-picker__lg">テーマの色</legend>
<div class="x-color-picker__sw">
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#1d4ed8" checked>
<span class="x-color-picker__c x-color-picker__c--blue"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">青 #1d4ed8</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#15803d">
<span class="x-color-picker__c x-color-picker__c--green"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">緑 #15803d</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#b91c1c">
<span class="x-color-picker__c x-color-picker__c--red"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">赤 #b91c1c</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#ea580c">
<span class="x-color-picker__c x-color-picker__c--orange"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">橙 #ea580c</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#7e22ce">
<span class="x-color-picker__c x-color-picker__c--purple"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">紫 #7e22ce</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#facc15">
<span class="x-color-picker__c x-color-picker__c--yellow"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">黄 #facc15</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#475569">
<span class="x-color-picker__c x-color-picker__c--gray"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">灰 #475569</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#ffffff">
<span class="x-color-picker__c x-color-picker__c--white"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">白 #ffffff</span>
</label>
</div>
<div class="x-color-picker__row">
<label class="x-color-picker__l" for="x-color-picker-n">ほかの色</label>
<input class="x-color-picker__n" id="x-color-picker-n" type="color" value="#1d4ed8">
<label class="x-color-picker__l" for="x-color-picker-hex">カラーコード</label>
<input class="x-color-picker__hex" id="x-color-picker-hex" type="text" value="#1d4ed8"
maxlength="7" pattern="#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})" spellcheck="false" autocomplete="off">
</div>
<!-- 3つの入力のどれを変えても、残り2つとこの行を同じ値に揃える -->
<p class="x-color-picker__v" role="status">選択中: 青(#1d4ed8)</p>
</fieldset>
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-color-picker,
.x-color-picker *:not([class*="fa-"]),
.x-color-picker *:not([class*="fa-"])::before,
.x-color-picker *:not([class*="fa-"])::after {
box-sizing: border-box;
/* 貼った先の既定の書体に引きずられないようにする。書体が変わると
文字の幅と高さが変わり、枠のサイズまでずれる */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}
.x-color-picker {
width: 300px;
margin: 0;
padding: 0;
border: 0;
color: #1b2028;
}
.x-color-picker__lg {
margin-bottom: 8px;
padding: 0;
font-size: 12px;
font-weight: 700;
}
.x-color-picker__sw {
display: flex;
gap: 8px;
}
.x-color-picker__o {
position: relative;
display: block;
width: 28px;
height: 28px;
cursor: pointer;
}
/* 本物のラジオボタンを色見本の上に透明で重ねる。キーボードの矢印キーと読み上げはそのまま効く */
.x-color-picker__r {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
margin: 0;
opacity: 0;
cursor: pointer;
}
.x-color-picker__c {
display: grid;
place-items: center;
width: 100%;
height: 100%;
border: 1px solid #5b6472;
border-radius: 50%;
color: #fff;
font-size: 13px;
}
.x-color-picker__c .fa-check {
visibility: hidden;
}
.x-color-picker__c--blue { background: #1d4ed8; }
.x-color-picker__c--green { background: #15803d; }
.x-color-picker__c--red { background: #b91c1c; }
.x-color-picker__c--orange { background: #ea580c; color: #1b2028; }
.x-color-picker__c--purple { background: #7e22ce; }
.x-color-picker__c--yellow { background: #facc15; color: #1b2028; }
.x-color-picker__c--gray { background: #475569; }
.x-color-picker__c--white { background: #fff; color: #1b2028; }
/* 選んだ色は、色の違いではなく印(チェック)と外側の輪で示す */
.x-color-picker__r:checked + .x-color-picker__c {
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #1b2028;
}
.x-color-picker__r:checked + .x-color-picker__c .fa-check {
visibility: visible;
}
.x-color-picker__r:focus-visible + .x-color-picker__c {
outline: 2px solid #1d4ed8;
outline-offset: 5px;
}
.x-color-picker__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
white-space: nowrap;
clip-path: inset(50%);
}
.x-color-picker__row {
display: flex;
align-items: center;
gap: 8px;
margin-top: 14px;
}
.x-color-picker__l {
font-size: 12px;
font-weight: 700;
}
.x-color-picker__n {
width: 40px;
height: 40px;
padding: 3px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
cursor: pointer;
}
.x-color-picker__hex {
width: 92px;
height: 40px;
padding: 0 10px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
color: #1b2028;
font-size: 14px;
font-variant-numeric: tabular-nums;
}
.x-color-picker__n:focus-visible,
.x-color-picker__hex:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 1px;
}
.x-color-picker__v {
margin: 8px 0 0;
color: #5b6472;
font-size: 12px;
}
AIへの指示文
「カラーピッカー(Color picker)」を実装してください。
## これは何か
丸い色見本を並べて1つ選ばせ、その下にカラーコードの欄と自由に色を選ぶボタンを置いた入力。テーマ色やラベルの色のように、色そのものを決めてもらうときに使う。
## 使いどころ
- テーマ色・カレンダーの予定の色・ラベルの色など、決まった候補から色を選んでもらうとき
- デザインツールや設定画面で、候補にない色もカラーコードで指定させたいとき
## 実装の要件
- fieldset > legend + label > input[type=radio] + 見本の span + 名前の文字 / input[type=color] / input[type=text](カラーコード)/ 選択中の値の文字
- input[type=color] の値は既定で #rrggbb の小文字16進。alpha 属性は付けない。付けると値が color(srgb 0 1 0 / 0.5) の形に変わり、対応も Safari 18.4 以降だけ(Chrome・Edge は未対応、Firefox は Nightly のみ)
- 透明度が要るなら「不透明度」の label を付けた input[type=range] を別に置く
- 見本の色はクラスか CSS 変数で持ち、選んだ値は16進のカラーコードで保存する
- 色見本だけで選ばせない。選んだ色の名前とカラーコードを文字でも出す。色の見分けがつきにくい人は、見本の違いだけでは何を選んだか分からない
- 白や薄い黄色の見本は背景に溶ける。見本にも枠線を引き、背景との差を 3:1 以上にする
- 選んだ見本は、色の違いではなくチェックの印や外側の輪で示す
- 見本・カラーコード・自由選択の3つを別々に持たない。どれを変えても残りが同じ値に揃うようにする
- カラーコードの欄は「#」の有無や大文字小文字、3桁の短縮形(#fff)を受け止めて正規化する
## アクセシビリティの要件
- 色見本は input[type=radio] を同じ name でまとめ、fieldset と legend で「テーマの色」と見出しを付ける。矢印キーで選べるのは標準の挙動
- 各見本に「青 #1d4ed8」のような名前を文字で持たせる(見えない文字でよい)。色の塗りだけでは読み上げで何色か分からない
- 見本の当たり判定は 24px 以上にする(WCAG 2.2 の 2.5.8)
- input[type=color] にも label を付ける。開く色選びの画面はブラウザと OS のもので、見た目も操作も揃えられない
## 参考にする実装
この形を出発点にして、プロジェクトの命名規則・色・余白に合わせて調整してください。
```html
<fieldset class="x-color-picker">
<legend class="x-color-picker__lg">テーマの色</legend>
<div class="x-color-picker__sw">
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#1d4ed8" checked>
<span class="x-color-picker__c x-color-picker__c--blue"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">青 #1d4ed8</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#15803d">
<span class="x-color-picker__c x-color-picker__c--green"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">緑 #15803d</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#b91c1c">
<span class="x-color-picker__c x-color-picker__c--red"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">赤 #b91c1c</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#ea580c">
<span class="x-color-picker__c x-color-picker__c--orange"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">橙 #ea580c</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#7e22ce">
<span class="x-color-picker__c x-color-picker__c--purple"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">紫 #7e22ce</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#facc15">
<span class="x-color-picker__c x-color-picker__c--yellow"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">黄 #facc15</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#475569">
<span class="x-color-picker__c x-color-picker__c--gray"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">灰 #475569</span>
</label>
<label class="x-color-picker__o">
<input class="x-color-picker__r" type="radio" name="theme-color" value="#ffffff">
<span class="x-color-picker__c x-color-picker__c--white"><i class="fa-solid fa-check" aria-hidden="true"></i></span>
<span class="x-color-picker__sr">白 #ffffff</span>
</label>
</div>
<div class="x-color-picker__row">
<label class="x-color-picker__l" for="x-color-picker-n">ほかの色</label>
<input class="x-color-picker__n" id="x-color-picker-n" type="color" value="#1d4ed8">
<label class="x-color-picker__l" for="x-color-picker-hex">カラーコード</label>
<input class="x-color-picker__hex" id="x-color-picker-hex" type="text" value="#1d4ed8"
maxlength="7" pattern="#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})" spellcheck="false" autocomplete="off">
</div>
<!-- 3つの入力のどれを変えても、残り2つとこの行を同じ値に揃える -->
<p class="x-color-picker__v" role="status">選択中: 青(#1d4ed8)</p>
</fieldset>
```
```css
/* 貼った先のリセットに頼らないよう、この部品の中だけ border-box にする */
.x-color-picker,
.x-color-picker *:not([class*="fa-"]),
.x-color-picker *:not([class*="fa-"])::before,
.x-color-picker *:not([class*="fa-"])::after {
box-sizing: border-box;
/* 貼った先の既定の書体に引きずられないようにする。書体が変わると
文字の幅と高さが変わり、枠のサイズまでずれる */
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Noto Sans JP", "Yu Gothic UI", Meiryo, sans-serif;
}
.x-color-picker {
width: 300px;
margin: 0;
padding: 0;
border: 0;
color: #1b2028;
}
.x-color-picker__lg {
margin-bottom: 8px;
padding: 0;
font-size: 12px;
font-weight: 700;
}
.x-color-picker__sw {
display: flex;
gap: 8px;
}
.x-color-picker__o {
position: relative;
display: block;
width: 28px;
height: 28px;
cursor: pointer;
}
/* 本物のラジオボタンを色見本の上に透明で重ねる。キーボードの矢印キーと読み上げはそのまま効く */
.x-color-picker__r {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
margin: 0;
opacity: 0;
cursor: pointer;
}
.x-color-picker__c {
display: grid;
place-items: center;
width: 100%;
height: 100%;
border: 1px solid #5b6472;
border-radius: 50%;
color: #fff;
font-size: 13px;
}
.x-color-picker__c .fa-check {
visibility: hidden;
}
.x-color-picker__c--blue { background: #1d4ed8; }
.x-color-picker__c--green { background: #15803d; }
.x-color-picker__c--red { background: #b91c1c; }
.x-color-picker__c--orange { background: #ea580c; color: #1b2028; }
.x-color-picker__c--purple { background: #7e22ce; }
.x-color-picker__c--yellow { background: #facc15; color: #1b2028; }
.x-color-picker__c--gray { background: #475569; }
.x-color-picker__c--white { background: #fff; color: #1b2028; }
/* 選んだ色は、色の違いではなく印(チェック)と外側の輪で示す */
.x-color-picker__r:checked + .x-color-picker__c {
box-shadow: 0 0 0 2px #fff, 0 0 0 4px #1b2028;
}
.x-color-picker__r:checked + .x-color-picker__c .fa-check {
visibility: visible;
}
.x-color-picker__r:focus-visible + .x-color-picker__c {
outline: 2px solid #1d4ed8;
outline-offset: 5px;
}
.x-color-picker__sr {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
white-space: nowrap;
clip-path: inset(50%);
}
.x-color-picker__row {
display: flex;
align-items: center;
gap: 8px;
margin-top: 14px;
}
.x-color-picker__l {
font-size: 12px;
font-weight: 700;
}
.x-color-picker__n {
width: 40px;
height: 40px;
padding: 3px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
cursor: pointer;
}
.x-color-picker__hex {
width: 92px;
height: 40px;
padding: 0 10px;
border: 1px solid #7f8a99;
border-radius: 8px;
background: #fff;
color: #1b2028;
font-size: 14px;
font-variant-numeric: tabular-nums;
}
.x-color-picker__n:focus-visible,
.x-color-picker__hex:focus-visible {
outline: 2px solid #1d4ed8;
outline-offset: 1px;
}
.x-color-picker__v {
margin: 8px 0 0;
color: #5b6472;
font-size: 12px;
}
```
## 出力の約束
- HTML と CSS を分けて出す。JavaScript が要るときは素の JavaScript で書き、UIフレームワークは使わない。
- 参考実装がアイコンに Font Awesome のクラスを使っている場合は、プロジェクトで使っているアイコンかインライン SVG に置き換えてよい。
- 上のアクセシビリティ要件を満たす。満たせない箇所があるときは、理由を添えて先に知らせる。
- 色・角丸・余白は既存のデザイントークンがあればそれを使う。無ければ CSS 変数として切り出す。
使いどころ
- テーマ色・カレンダーの予定の色・ラベルの色など、決まった候補から色を選んでもらうとき
- デザインツールや設定画面で、候補にない色もカラーコードで指定させたいとき
注意点
- 色見本だけで選ばせない。選んだ色の名前とカラーコードを文字でも出す。色の見分けがつきにくい人は、見本の違いだけでは何を選んだか分からない
- 白や薄い黄色の見本は背景に溶ける。見本にも枠線を引き、背景との差を 3:1 以上にする
- 選んだ見本は、色の違いではなくチェックの印や外側の輪で示す
- 見本・カラーコード・自由選択の3つを別々に持たない。どれを変えても残りが同じ値に揃うようにする
- カラーコードの欄は「#」の有無や大文字小文字、3桁の短縮形(#fff)を受け止めて正規化する
アクセシビリティの要点
- 色見本は input[type=radio] を同じ name でまとめ、fieldset と legend で「テーマの色」と見出しを付ける。矢印キーで選べるのは標準の挙動
- 各見本に「青 #1d4ed8」のような名前を文字で持たせる(見えない文字でよい)。色の塗りだけでは読み上げで何色か分からない
- 見本の当たり判定は 24px 以上にする(WCAG 2.2 の 2.5.8)
- input[type=color] にも label を付ける。開く色選びの画面はブラウザと OS のもので、見た目も操作も揃えられない