聚焦樣式

焦點指標 (通常以「焦點環」表示) 會指出網頁上目前聚焦的元素。對於無法使用滑鼠的使用者而言,這個指標「非常重要」,因為它可取代滑鼠游標。

如果瀏覽器的預設焦點指標與您的設計衝突,您可以使用 CSS 重新設定樣式。只要記得要考量鍵盤使用者的需求即可!

無論使用哪種輸入裝置 (滑鼠、鍵盤、觸控筆等) 或方法聚焦元素,只要元素聚焦,就會套用 :focus 擬群組別。舉例來說,下方的 <div>tabindex,可讓其聚焦。它也具有 :focus 狀態的自訂樣式:

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

無論您是使用滑鼠點選,還是使用鍵盤的 Tab 鍵前往,<div> 都會一律顯示相同的內容。

很抱歉,瀏覽器在套用焦點的方式可能不一致。元素是否會接收焦點,可能會視瀏覽器和作業系統而定。

舉例來說,下方的 <button> 也為其 :focus 狀態提供自訂樣式。

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

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

由於焦點的行為不一致,因此您可能需要在不同裝置上進行一些測試,確保焦點樣式符合使用者需求。

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

每當元素獲得焦點,且瀏覽器透過啟發式搜尋判斷顯示焦點指標對使用者有益時,系統就會套用新的 :focus-visible 擬似類別。具體來說,如果最近的使用者互動是透過鍵盤進行,且按鍵時並未包含中繼資料、ALT / OPTIONCONTROL 鍵,則 :focus-visible 會相符。

下方範例中的按鈕會選擇性顯示焦點指標。如果您使用滑鼠點選它,結果會與先使用鍵盤切換至該按鈕時不同。

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 will hide the focus indicator if the element receives focus via the
  mouse, but it will still show 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 {
 

}