互動式多媒體選擇器 (可自訂選取)

網頁功能: 可自訂的 <select>

原生 <select> 元素過去很難設定樣式,且只能包含純文字選項。appearance: base-select 屬性提供宣告式、僅限 CSS 的方式,可為 <select> 元素啟用可自訂狀態。這樣一來,開發人員就能在 <option> 元素中加入豐富的 HTML 內容 (例如圖片、SVG 和複雜版面配置),同時保留原生鍵盤無障礙功能和表單整合。使用這個模式,將繁重的自訂選取元件替換為標準的原生元素。

導入方式

如要使用 Customizable Select API 導入互動式多媒體選擇器,請按照下列步驟操作:

  1. 選擇加入基本樣式:使用 ::picker(select) 虛擬元素,將 appearance: base-select 同時套用至 <select> 元素及其內部挑選器。這會變更瀏覽器的 HTML 剖析器,用於剖析 <select> 內的內容。
  2. 定義按鈕內容:在 <select> 中使用標準 <button> 和 <selectedcontent> 元素,定義挑選器關閉時顯示的內容。<selectedcontent> 元素會自動反映所選選項的內容。如要在按鈕中顯示目前選取的多媒體內容,就必須提供這項資訊。
  3. 在選項中使用多媒體內容:現在可以在 <option> 標記中加入圖片、SVG 和其他 HTML 代碼。在這個 API 推出前,瀏覽器會從 <option> 標記中移除標記,只顯示純文字。
  4. 設定彈出式視窗樣式:指定 ::picker(select) 虛擬元素,設定下拉式選項清單的樣式。它會在頂層算繪,因此您不必與 z-index 競爭。選項會使用 Anchor Positioning API 原生定位。

程式碼範例:Rich Role Picker

<label for="role-picker">Select your role</label>
<select class="custom-select" name="role" id="role-picker">
  <button>
    <selectedcontent></selectedcontent> <!-- Mirrors the selected option's content automatically so you do not need JS to update the button -->
  </button>

  <!-- Define concise aria-label values on options whose mirrored rich content would otherwise read awkwardly as a concatenated string -->
  <option value="frontend" aria-label="Frontend Developer">
    <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
      <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
    </svg>
    <div class="option-text">
      <span class="option-title">Frontend Developer</span>
      <span class="option-desc">React, Vue, CSS</span>
    </div>
  </option>

  <option value="backend" aria-label="Backend Developer">
    <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
      <rect x="2" y="12" width="20" height="14" rx="2" ry="2"></rect>
    </svg>
    <div class="option-text">
      <span class="option-title">Backend Developer</span>
      <span class="option-desc">Node.js, Python</span>
    </div>
  </option>
</select>
select.custom-select,
select.custom-select::picker(select) {
  appearance: base-select; /* MUST opt-in both the select and its picker to enable the customizable state, otherwise browser standard rendering applies */
}

select.custom-select {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 12px;
  background-color: #1e293b;
  border: 1px solid #334155;
  border-radius: 8px;
  color: #f1f5f9;
  cursor: pointer;
}

select.custom-select::picker(select) {
  background-color: #0f172a;
  border: 1px solid #334155;
  border-radius: 8px;
  padding: 8px;
  box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5);
  width: anchor-size(width); /* Uses Anchor Positioning API to keep the dropdown precisely aligned to the button trigger width */
}

select.custom-select option {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  border-radius: 4px;
  cursor: pointer;
}

select.custom-select option:hover {
  background-color: #1e293b;
}

/* Remove standard OS checkmark for base-select */
select.custom-select option::before {
  display: none;
}

/* MANDATORY: Provide multiple visual indicators (e.g., prominent background color and bold title font) to communicate the checked state cleanly */
select.custom-select option:checked {
  background-color: #3b82f6;
  color: #ffffff;
}
select.custom-select option:checked .option-title {
  font-weight: 700;
}

策略執行與最佳做法

  • 建議:如需複雜的選項版面配置 (圖示、說明、圖片),請使用 appearance: base-select。這類版面配置先前只能透過繁重的 JavaScript UI 架構達成。
  • 如果發現效能延遲,請勿使用臨時元素;瀏覽器會以原生方式處理原生鍵盤焦點。
  • 務必考量頂層轉譯。挑選器會在頂層顯示,也就是說,它會覆寫網頁內容的相對 z-index。
  • 建議:如果次要詳細資料 (例如說明) 占用太多空間,請設定 .custom-select selectedcontent .option-desc { display: none; } 樣式,在按鈕狀態中隱藏這些資料。
  • 測試版面配置行為。設定 appearance: base-select 會移除預設的瀏覽器行為,也就是根據最長的選項寬度調整選取範圍大小。您可能需要設定固定寬度,或使用彈性/格線限制,避免版面配置位移。
  • 確認 <select> 具有 name 屬性和相關聯的 <label>。這樣一來,即使使用自訂 UI,螢幕閱讀器仍可存取元件,且元件能與標準表單提交作業搭配運作。
  • 在選項中使用標準 value 屬性,確保表單提交功能與先前完全相同。

備用策略

可自訂 <select> 的備用方案和瀏覽器支援

如果瀏覽器尚未支援 appearance: base-select,<select> 元素會正常降級為標準作業系統下拉式選單。

  • 忽略非文字內容:舊版瀏覽器會移除 <option> 標記內的 HTML 代碼 (例如 <svg> 或 <div>),只轉譯文字節點。確保 <option> 的文字內容本身清晰可讀且有意義。
  • HTML 結構處理:標準剖析器可能會忽略 <select> 內的 <button> 和 <selectedcontent> 標記,或將其視為無效。如果將標準文字視為可讀取的備用文字,則不需要使用繁重的 JavaScript 填充碼來進行漸進式增強。
document.addEventListener("DOMContentLoaded", () => {
  // Check if browser supports base-select value
  if (!CSS.supports("appearance", "base-select")) {
    // Custom select overrides are not supported natively.
  }
});