Customizable <select>

Baseline 未達(対応: Chrome・Safari)select の閉じた表示と開いたときの一覧を、CSS で自由に作るMDN ↗

STEP 1

これまでは中身を変えられない

select は、枠や文字色は変えられても、開いたときの一覧はブラウザ任せでした。選択肢に書けるのも文字だけです。

下の select を開いてみてください。

STEP 2

appearance: base-select で自由に作る

select と ::picker(select) に appearance: base-select を指定すると、一覧も含めて CSS で見た目を変えられます。選択肢には画像や説明文などの要素も書けます。

未対応のブラウザでは

button や selectedcontent は無視され、STEP 1 と同じ従来の select になります。選択肢は文字だけが表示されます。

使っている機能

appearance: base-select
select と ::picker(select) の両方に指定すると、CSS で見た目を自由に変えられるようになる
<button> と <selectedcontent>
select の最初の子に button を置くと、閉じているときの表示を置き換える。selectedcontent には選んだ option の中身が複製される
::picker(select)
開いたときの一覧。ポップオーバーとして最前面に表示される
::checkmark / ::picker-icon
選択中の option に付く印と、閉じているときの矢印
:open
一覧が開いている間だけ一致する疑似クラス

CSS

/* select と一覧の両方で、カスタマイズできる見た目に切り替える */
.select-custom,
.select-custom::picker(select) {
	appearance: base-select;
}

.select-custom {
	min-width: 220px;
	background: white;
}

/* 一覧(ポップオーバー) */
.select-custom::picker(select) {
	margin-top: 4px;
	padding: 4px;
	border: 1px solid var(--color-border);
	border-radius: 8px;
	box-shadow: 0 8px 24px rgb(0 0 0 / 0.12);
}

.select-custom option {
	gap: 12px;
	padding: 8px 12px;
	border-radius: 6px;
}

.select-custom option:checked {
	background: var(--color-accent-soft);
}

/* 選択中の印を右端へ */
.select-custom option::checkmark {
	order: 1;
	margin-left: auto;
	color: var(--color-accent);
}

/* 閉じているときは説明文を隠す */
.select-custom selectedcontent small {
	display: none;
}

/* 開いている間は矢印を上向きに */
.select-custom::picker-icon {
	transition: rotate 0.2s;
}

.select-custom:open::picker-icon {
	rotate: 180deg;
}

HTML

<select name="custom-pet" class="select-custom">
	<button>
		<selectedcontent></selectedcontent>
	</button>
	<option value="cat">
		<span class="select-icon" aria-hidden="true">🐱</span>
		<span class="select-label">ねこ<small>気ままに暮らす</small></span>
	</option>
	<option value="dog">
		<span class="select-icon" aria-hidden="true">🐶</span>
		<span class="select-label">いぬ<small>散歩が好き</small></span>
	</option>
	<option value="rabbit">
		<span class="select-icon" aria-hidden="true">🐰</span>
		<span class="select-label">うさぎ<small>静かに過ごす</small></span>
	</option>
</select>