聚焦樣式

焦點指標 (通常以「焦點環」表示) 會指出網頁上處於焦點的元素。對於無法或不想使用滑鼠的使用者來說,這個指標非常重要,因為它會取代滑鼠指標。

如果瀏覽器的預設焦點指標與設計衝突,可以使用 CSS 重新設定樣式。請務必考量使用者需求。

使用 :focus 一律顯示焦點指標

無論使用哪種輸入方法或裝置 (例如滑鼠、鍵盤或觸控筆),:focus 虛擬類別都會套用至焦點元素。

舉例來說,下列 <div> 具有 tabindex,可讓它成為可聚焦的項目,並為 :focus 狀態設定自訂樣式:

div[tabindex="0"]:focus {
  outline: 4px dashed orange;
}

無論使用哪種裝置,<div>在焦點中看起來都一樣。

遺憾的是,瀏覽器套用焦點的方式可能不一致。元素是否會收到焦點,可能取決於瀏覽器和作業系統。

舉例來說,下列 <button>:focus 狀態具有自訂 CSS。

button:focus {
  outline: 4px dashed orange;
}

如果您在 macOS 上的 Chrome 中使用滑鼠點選 <button>,應該會看到自訂焦點樣式。不過,如果您在 macOS 上的 Safari 中點選 <button>,就不會看到自訂焦點樣式。這是因為在 Safari 中,點選元素時,元素不會取得焦點。

焦點行為不一致。在不同裝置上使用不同輸入內容測試網頁,確保焦點樣式符合使用者需求。

使用 :focus-visible 選擇性顯示焦點指標

當元素收到焦點,且瀏覽器 (透過啟發式方法) 判斷顯示焦點指標對使用者有益時,系統就會套用 :focus-visible 虛擬類別。具體來說,如果使用者最近一次是透過鍵盤互動,且按下的按鍵不包含 Meta、ALTOPTIONCONTROL 鍵,則 :focus-visible 會相符。

在下列範例中,按鈕會選擇性顯示焦點指標。如果使用滑鼠點選,結果會與先使用鍵盤 Tab 鍵切換至該項目不同。

button:focus-visible {
  outline: 4px dashed orange;
}

使用 :focus-within 為焦點元素的父項設定樣式

當元素本身或子項元素收到焦點時,系統會將 :focus-within 虛擬類別套用至元素。可用於醒目顯示網頁區域,吸引使用者注意。

舉例來說,表單本身和任何圓形按鈕都可接收焦點。

form:focus-within {
  background: #ffecb3;
}

何時顯示焦點指標

您可以問自己:「如果使用行動裝置時點選這個控制項,您會預期顯示鍵盤嗎?」

  • 如果是:控制項一律應顯示焦點指標,無論輸入裝置為何。舉例來說,<input type="text"> 元素幾乎一律是這種情況。無論輸入元素如何成為焦點,使用者都必須透過鍵盤將輸入內容傳送至該元素。
  • 如果為否:控制項可能會選擇性地顯示焦點指標。舉例來說,當使用者以滑鼠點選 <button> 或在觸控螢幕上輕觸時,就會完成動作。焦點指標可能不必要。不過,如果使用者是透過鍵盤操作,顯示焦點指標就很有用,可讓使用者決定是否要使用 ENTERSPACE 鍵啟動控制項。

建議不要使用 outline: none

坦白說,瀏覽器決定何時繪製焦點指標的方式非常令人困惑。使用 CSS 變更 <button> 元素的外觀,或為元素提供 tabindex,都會觸發瀏覽器的預設焦點環行為。

有時開發人員會使用 CSS 移除焦點指標:

/* Don't do this!!! */
:focus {
  outline: none;
}

如要解決這個問題,建議您結合 :focus:focus-visible polyfill。第一個程式碼區塊示範了 Polyfill 的運作方式,下方的範例應用程式則示範如何使用 Polyfill 變更按鈕的焦點指標。

/*
  This hides the focus indicator if the element receives focus with a
  mouse, but it still shows up on keyboard focus.
*/
.js-focus-visible :focus:not(.focus-visible) {
  outline: none;
}

/*
  Optionally: Define a strong focus indicator for keyboard focus.
  If you choose to skip this step, then the browser's default focus
  indicator will be displayed instead.
*/
.js-focus-visible .focus-visible {
  ...
}