焦點指標 (通常以「焦點環」表示) 會指出網頁上目前聚焦的元素。對於無法使用滑鼠的使用者而言,這個指標「非常重要」,因為它可取代滑鼠游標。
如果瀏覽器的預設焦點指標與您的設計衝突,您可以使用 CSS 重新設定樣式。只要記得要考量鍵盤使用者的需求即可!
使用 :focus
一律顯示焦點指標
無論使用哪種輸入裝置 (滑鼠、鍵盤、觸控筆等) 或方法聚焦元素,只要元素聚焦,就會套用 :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
/ OPTION
或 CONTROL
鍵,則 :focus-visible
會符合條件。
下方範例中的按鈕會選擇性顯示焦點指標。如果您使用滑鼠點選它,結果會與先使用鍵盤按 Tab 鍵前往時不同。
button:focus-visible {
outline: 4px dashed orange;
}
使用 :focus-within
為焦點元素的上層項目套用樣式
當元素本身收到焦點,或該元素內的另一個元素收到焦點時,系統會將 :focus-within
擬類別套用至該元素。
可用於醒目顯示網頁的某個區域,以便吸引使用者注意。舉例來說,當您選取表單本身或任何單選按鈕時,下方表單會收到焦點。
form:focus-within {
background: #ffecb3;
}
顯示焦點指標的時機
一個簡單的訣竅是,請問自己:「如果您在使用行動裝置時按下這個控制項,會希望系統顯示鍵盤嗎?」
如果答案為「是」,則無論使用哪種輸入裝置,控制項都應「一律」顯示焦點指標。<input type="text">
元素就是一個很好的例子。無論輸入元素最初如何接收焦點,使用者都必須透過鍵盤將輸入內容傳送至元素,因此建議您一律顯示焦點指標。
如果答案為「否」,控制項可能會選擇選擇性顯示焦點指標。<button>
元素就是一個很好的例子。如果使用者以滑鼠或觸控螢幕點選,動作就會完成,因此可能不需要焦點指標。不過,如果使用者使用鍵盤瀏覽,顯示焦點指標就很有用,這樣使用者就能決定是否要使用 ENTER
或 SPACE
鍵按一下控制項。
建議不要使用 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 {
…
}