HOWTO · CSS
CSS 中的樣式選擇下拉選單
本教程介紹瞭如何在 CSS 中設定下拉選單的樣式。
本頁內容
您可以調整原生 HTML select 下拉選單的外觀,並以 CSS 繪製的箭頭取代預設箭頭。這仍是真正的 select 控制項,因此使用者保有內建的選取行為與鍵盤操作功能。常見做法有兩種:直接移除原生外觀,或用包裝元素裁切掉原生箭頭。
設定原生 select 下拉選單的樣式,同時保留其行為
select 包含 option 元素,而瀏覽器會依照平台與自身慣例來呈現控制項。CSS 可以修改可見的控制項外框,但彈出選項清單及部分細節仍會因瀏覽器和作業系統而異。若要保留內建的表單與鍵盤操作功能,請使用原生元素,不要用通用元素重新製作下拉選單。
範例使用相同的四個選項。CSS 在控制項右側預留箭頭空間,並為鍵盤使用者提供清楚可見的焦點外框。您可以調整顏色與尺寸,讓它符合介面設計。
使用 appearance: none 隱藏原生箭頭並新增自訂箭頭
在 select 上設定 appearance: none,即可在支援此設定的環境中移除瀏覽器的原生箭頭,接著用兩個 CSS 漸層繪製 V 形箭頭。background 圖層會將兩道線條放在靠近右側的位置;右側內距則讓選項文字不會貼近線條。-webkit-appearance 和 -moz-appearance 是供使用這些前綴的引擎採用的廠商前綴形式,並不代表各自對應不同的 WebKit/Blink 瀏覽器家族。標準屬性是主要宣告;只有在瀏覽器支援需求需要時,才保留前綴版本。
這是一個完整的靜態瀏覽器範例。將它儲存為 HTML 檔案並在瀏覽器中開啟,即可查看控制項;封包沒有提供瀏覽器實際呈現結果的證據,因此本文不宣稱已確認其視覺效果。
本節中的程式碼以及顯示的標籤或輸出仍為英文。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Styled select</title>
<style>
.vehicle-select {
box-sizing: border-box;
width: 220px;
height: 40px;
padding: 0 32px 0 10px;
border: 1px solid #777;
border-radius: 4px;
color: #222;
background-color: #fff;
background-image:
linear-gradient(45deg, transparent 50%, #333 50%),
linear-gradient(135deg, #333 50%, transparent 50%);
background-position:
calc(100% - 14px) 50%,
calc(100% - 9px) 50%;
background-size: 5px 5px, 5px 5px;
background-repeat: no-repeat;
appearance: none;
}
.vehicle-select:focus-visible {
outline: 3px solid #1769aa;
outline-offset: 2px;
}
</style>
</head>
<body>
<label for="vehicle">Choose a vehicle</label>
<select class="vehicle-select" id="vehicle" name="vehicle">
<option>RE Himalayan</option>
<option selected>CRF Rally</option>
<option>GS 310</option>
<option>KTM ADV</option>
</select>
</body>
</html>
使用裁切包裝元素隱藏原生箭頭
包裝元素也能用來隱藏原生箭頭。將 select 的寬度設為略大於包裝元素,並把包裝元素的 overflow 設為 hidden;原生箭頭便會落在包裝元素的可見範圍之外。接著用偽元素在包裝元素上繪製替代箭頭。由於 select 仍位於包裝元素內,選項與原生互動功能都會保留。
包裝元素的寬度要足以容納控制項文字,而 select 只需比它稍寬。如果兩者寬度差距太大,控制項右側邊框或其他內容也可能被裁切。偽元素使用 pointer-events: none,因此不會攔截對 select 的點擊。
在包裝元素範例中,select 比包裝元素多出 20 像素。以下簡短的 JavaScript 檢查會明確確認這個尺寸關係:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
const wrapperWidth = 200;
const selectWidth = 220;
if (selectWidth <= wrapperWidth) {
process.exitCode = 1;
}
當 select 比包裝元素寬時,這項檢查會順利完成;否則便會設定失敗的結束代碼。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Select with clipped arrow</title>
<style>
.select-wrap {
position: relative;
box-sizing: border-box;
width: 200px;
height: 42px;
overflow: hidden;
border: 1px solid #777;
border-radius: 4px;
background: #fff;
}
.select-wrap select {
box-sizing: border-box;
width: 220px;
height: 40px;
padding: 0 10px;
border: 0;
color: #222;
background: transparent;
font: inherit;
}
.select-wrap::after {
position: absolute;
top: 18px;
right: 12px;
width: 7px;
height: 7px;
border-right: 2px solid #333;
border-bottom: 2px solid #333;
content: "";
pointer-events: none;
transform: rotate(45deg);
}
.select-wrap:focus-within {
outline: 3px solid #1769aa;
outline-offset: 2px;
}
</style>
</head>
<body>
<label for="vehicle">Choose a vehicle</label>
<div class="select-wrap">
<select id="vehicle" name="vehicle">
<option>RE Himalayan</option>
<option selected>CRF Rally</option>
<option>GS 310</option>
<option>KTM ADV</option>
</select>
</div>
</body>
</html>
選擇合適的做法並確認限制
如果希望由 select 本身決定寬度與邊框,而且目標瀏覽器支援所需樣式,可以使用 appearance: none。如果需要在包裝元素上放置箭頭,或不適合直接設定外觀,則可使用裁切包裝元素的做法。無論選擇哪一種,都請在支援的瀏覽器與裝置上測試頁面:原生 select 的呈現方式與彈出選單並不完全一致。
請確認選取值完整可見、自訂箭頭位置正確,而且鍵盤焦點清楚易辨。若使用包裝元素的做法,當邊框或文字看起來遭到裁切時,請比對包裝元素與 select 的寬度。不要只為了讓控制項看起來更簡潔就移除焦點指示;若要自訂樣式,請改用同樣清晰的指示方式。這些技巧會改變外觀呈現,但仍由原生 select 負責選取與表單行為。