CSSselect::pickersibling-index前端開發UI 設計

CSS 創意應用:可自訂 Select 的酷炫效果

深入探索 CSS 新的 ::picker() 偽元素、::checkmark 偽元素與 sibling-index() 函數,帶你解鎖 `<select>` 元素的外觀限制,實現完全自訂的下拉選單效果。

· 6 分鐘閱讀

還記得被 <select> 元素支配的恐懼嗎?那個怎麼改 color 都沒反應的下拉選單,那個在各瀏覽器看起來都不一樣的原生元件。別擔心,CSS 現在給了我們一把解鎖原生選單的鑰匙——appearance: base-select、::picker() 偽元素,以及強大的 sibling-index() 函數。準備好讓你的下拉選單煥然一新了嗎?


傳統 Select 的困境

在過去十年裡,前端工程師面對 <select> 元素時,內心都會浮現一個共同的疑問:「為什麼這麼難樣式化?」

無論你嘗試什麼:

select {
  color: red;
  background: blue;
  border-radius: 8px;
}

結果往往是——什麼都沒變。那個熟悉的下拉箭頭依然固執地待在那個位置,背景色依然是我行我素的白色。這是因為 <select> 是一個「替換元素」(replaced element),它的渲染由作業系統和瀏覽器原生控制,傳統 CSS 幾乎無法干預。

但時代變了。CSS 規範帶來了一系列新武器,讓我們終於可以對原生選單下手了。


解鎖樣式的第一把鑰匙:appearance: base-select

什麼是 appearance?

appearance 是一個 CSS 屬性,用於控制元素是否使用作業系統的原生物件外觀。傳統上,你可能看過 appearance: none——這會完全移除原生樣式,讓元素變得像一個普通的 div

none 太激進了,它把所有東西都拿走,連基本的行為都沒有。

base-select 的誕生

這時候 base-select 就派上用場了。它是 appearance 屬性的一個新值,專門針對 <select> 元素設計。讓我們看看它的效果:

.custom-select {
  appearance: base-select;
}

加上這一行之後,奇蹟發生了——

  • 原本不可修改的 colorbackground-color 現在可以改變了
  • 邊框、圓角終於聽話了
  • 文字樣式(字體、大小、字重)也可以自由設定

但這只是第一步。base-select 讓元素變得「可樣式化」,但要真正自訂下拉選單的各個部分,我們還需要認識更多偽元素。


深入選單內部:::picker() 偽元素

認識 ::picker()

::picker() 是 CSS 新的偽元素,它代表 <select> 元素的下拉面板——也就是你點擊時彈出來的那個選項列表。

這是我們第一次可以對下拉選單的「內部」進行樣式控制!

/* 改變下拉面板的背景 */
select::picker(select) {
  background-color: #1a1a2e;
  border-radius: 12px;
  padding: 8px;
}

::picker() 的強大應用

讓我們看一個完整的例子:

.theme-dark select::picker(select) {
  background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
  border: 1px solid #0f3460;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
}

.theme-dark select::picker(select) li {
  padding: 12px 16px;
  color: #e8e8e8;
  border-radius: 6px;
  margin: 2px 0;
}

.theme-dark select::picker(select) li:hover,
.theme-dark select::picker(select) li:highlighted {
  background: #0f3460;
  color: #00d9ff;
}

你可以看到,我們現在可以:

  • 設定下拉面板的背景(支援漸層和陰影!)
  • 調整每個選項的內邊距和間距
  • 自訂 hover 和选中状态的样式

這在以前是根本不可能做到的事。


鉤選標記:::checkmark 偽元素

::checkmark 的作用

除了下拉面板,選項旁邊的「勾選標記」也是可以自訂的。當一個選項被選中時,旁邊會出現一個勾勾,這就是 ::checkmark 偽元素代表的內容。

/* 自訂勾選標記 */
select::checkmark {
  color: #00d9ff;
  font-size: 14px;
}

完整範例:時尚的下拉選單

讓我們把這些技術整合在一起,創建一個現代感十足的下拉選單:

/* 基礎樣式 */
.fancy-select {
  appearance: base-select;
  padding: 14px 40px 14px 16px;
  font-size: 16px;
  border: 2px solid #e0e0e0;
  border-radius: 12px;
  background-color: #ffffff;
  color: #333;
  cursor: pointer;
  transition: all 0.3s ease;
}

.fancy-select:hover {
  border-color: #00d9ff;
  box-shadow: 0 4px 12px rgba(0, 217, 255, 0.15);
}

.fancy-select:focus {
  outline: none;
  border-color: #00d9ff;
  box-shadow: 0 0 0 4px rgba(0, 217, 255, 0.1);
}

/* 下拉面板 */
.fancy-select::picker(select) {
  background: #ffffff;
  border: 1px solid #e0e0e0;
  border-radius: 12px;
  padding: 8px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}

/* 選項樣式 */
.fancy-select::picker(select) li {
  padding: 12px 16px;
  border-radius: 8px;
  transition: background 0.2s;
}

.fancy-select::picker(select) li:hover,
.fancy-select::picker(select) li:highlighted {
  background: #f0f9ff;
  color: #0077cc;
}

/* 勾選標記 */
.fancy-select::checkmark {
  color: #00d9ff;
}

這段程式碼創造了一個有圓角邊框、 hover 效果、自訂背景的下拉選單——完全擺脫了原生外觀的束縛。


動態效果:sibling-index() 函數

什麼是 sibling-index()?

sibling-index() 是 CSS 的一個新函數,它可以返回當前元素在其所有兄弟元素中的索引位置。這個函數特別適合用在 <select> 的選項上,實現各種動態效果。

語法很簡單:

select li {
  /* 索引從 1 開始 */
  --index: sibling-index();
}

實際應用:編號效果

想象一個情境:你有一個選項列表,希望每個選項旁邊顯示它的編號。過去你可能需要用 JavaScript 動態添加,現在純 CSS 就可以做到:

/* 在選項前顯示編號 */
select::picker(select) li::before {
  content: counter(list-item) ". ";
  counter-increment: list-item;
  color: #888;
  margin-right: 8px;
}

不過更精確的做法是使用 sibling-index():

select::picker(select) li {
  /* 使用 --index 變數 */
  counter-set: option sibling-index();
}

select::picker(select) li::before {
  content: counter(option) ". ";
  color: #666;
  font-weight: 600;
  min-width: 24px;
  display: inline-block;
}

進階應用:漸層顏色效果

sibling-index() 更酷的應用是創建漸層或花哨的顏色效果:

select::picker(select) li {
  --hue: calc(sibling-index() * 30);
  background: hsl(var(--hue), 70%, 95%);
}

select::picker(select) li:nth-child(1) { --hue: 0; }   /* 紅色系 */
select::picker(select) li:nth-child(2) { --hue: 30; }  /* 橙色系 */
select::picker(select) li:nth-child(3) { --hue: 60; }  /* 黃色系 */
/* ...以此類推 */

或者用更動態的方式:

select::picker(select) li {
  /* 根據索引計算色相,實現彩虹漸變效果 */
  --hue: calc(sibling-index() * 40);
  background: hsl(var(--hue), 80%, 90%);
  color: hsl(var(--hue), 80%, 20%);
}

select::picker(select) li::before {
  content: "🎨 ";
}

間距動態效果

你還可以根據索引調整間距,創造層次感:

select::picker(select) li {
  --indent: calc(sibling-index() * 8px);
  padding-left: calc(16px + var(--indent));
}

/* 讓第一個選項更醒目 */
select::picker(select) li:first-child {
  font-weight: 700;
  font-size: 1.1em;
  border-bottom: 2px solid #00d9ff;
  margin-bottom: 4px;
}

瀏覽器支援與相容性

當前支援狀態

截至 2026 年,這些特性的瀏覽器支援如下:

特性ChromeFirefoxSafariEdge
appearance: base-select✅ 120+✅ 121+✅ 17.2+✅ 120+
::picker()✅ 120+✅ 121+✅ 17.2+✅ 120+
::checkmark✅ 120+✅ 121+✅ 17.2+✅ 120+
sibling-index()✅ 123+✅ 124+✅ 17.5+✅ 123+

優雅降級

為了確保在不完全支援的瀏覽器上也能正常運作,建議加上 fallback:

.custom-select {
  /* Fallback:傳統樣式 */
  background: #fff;
  border: 1px solid #ccc;
  
  /* 新式屬性 */
  appearance: base-select;
}

@supports (appearance: base-select) {
  .custom-select {
    /* 進階樣式,只在支援的瀏覽器生效 */
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: none;
  }
}

總結:CSS 的新時代

我們從「對 select 無能為力」的過去走到了「可以完全掌控」的今天。appearance: base-select 解開了原生元素的封印,::picker() 讓我們可以樣式化下拉面板,::checkmark 讓勾選標記不再單調,而 sibling-index() 則為動態效果開啟了大門。

這些技術的結合,讓我們終於可以告別那個醜醜的原生下拉選單,創造出與網站整體設計完美融合的自訂選單。

下一當你專案需要美化下拉選單時,記得這些新武器:先從 appearance: base-select 開始,然後用 ::picker() 打造獨特的下拉體驗,最後用 sibling-index() 添加一點創意魔法。

Happy styling! 🚀