CSSだけでselectタグをスタイル!でもNext.js(Turbopack)には落とし穴も…?
2025年3月ついにchrome134とedge134でCSSだけでselectタグのカスタマイズができるようになりました。(safari、firefoxではまだ対応していないの早く対応してもらいたいですね)
今までselectタグはブラウザネイティブUIに強く依存しており、他のフォームと見た目の統一を取るのが難しかったり、JavaScriptを使用しないとカスタマイズできなかったのでCSSだけで完結するのは開発体験の向上になってすごくありがたいです👏
今回はNext.jsでselectタグのカスタマイズをやってみようと思います。
検証
globals.css
に入れてみます。
/** @supportsでappearance: base-selectが利用できるブラウザのみこのCSSが適用されます(::pickerの判定はできないのでappearanceで判定しています) */
@supports (appearance: base-select) {
select,
::picker(select) {
appearance: base-select;
}
}
src/app/page.tsx
はcreate-next-app
で作られた大部分を消してselect, optionだけ追加しています。
export default function Home() {
return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
<main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
<select>
<option value="en">English</option>
<option value="es">Spanish</option>
<option value="fr">French</option>
<option value="de">German</option>
<option value="it">Italian</option>
</select>
</main>
</div>
);
}
これで準備は整ったのであとはChromeかEdgeでnpm run dev
します。
'picker' is not recognized as a valid pseudo-element. Did you mean ':picker' (pseudo-class) or is this a typo? at [project]/src/app/globals.css:454:18
'picker' は有効な疑似要素として認識されません。!?
いやいや、ちゃんとありますよ。https://developer.mozilla.org/en-US/docs/Web/CSS/::picker
エラーの原因を調べると、
こちらのissueを見つけました。
原因はNext.js v15から安定版として提供されたJavaScriptのビルドツールであるTurbopackが安定していないCSSの擬似要素をサポートしていないからだそうです。
正確にはTurbopackはCSSパーサーにLightning CSSを使っていますがこれが構文チェックが厳しく、仕様に載ってない、未対応の疑似要素は読み込み時点でエラーになります。
対処法
時間が経てばいずれTurbopackの方で正式にサポートはしてくれると思いますが、とりあえず検証してみたかったのでこの方法で対処しました。
Turbopackをやめてwebpackを使うようにする
Turbopackを使わないとなると、ビルドやホットリロードのスピードが下がったりと開発体験が落ちるかもしれませんがpackage.json
からの”dev”のところにある—turbopack
フラグを外せばエラーは解決します。
// before
{
"name": "select-test",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
...
},
...
}
// after
{
"name": "select-test",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
...
},
...
}
これでselectタグの表示が変わりCSSだけでカスタマイズすることが可能になりました。
まとめ
確かにこれでエラーは解決はするんですけど正直Turbopackが使えなくなってしまうのはあんまり良いやり方でない気がします。動作検証のために使うくらいで本番環境で使うにはまだ早いかもって思いました。
Lightning CSS側で ::picker 対応などselectタグのカスタマイズについてのPRは出ているみたいなので、こちらの動きをチェックしていきます。
何にせよselectタグのカスタマイズがCSSだけでできるようになったのは、フォームUIの進化としてかなり嬉しいですね。これからの対応ブラウザ拡大や、Turbopack側の改善にも期待していきたいところです。
Discussion