連結 (<a>) 與表單元素獲得焦點時,瀏覽器預設繪製的虛線外框 (focus outline) 雖具無障礙功能,但常與視覺設計衝突。本文系統整理 CSS、原生 JavaScript、jQuery 三大技術路線的解決方案,深度分析瀏覽器相容性、無障礙影響與最佳實踐策略。
/* 標準語法:移除 outline */
a:focus,
input:focus,
button:focus,
select:focus,
textarea:focus {
outline: none;
}
/* Firefox 舊版支援 -moz-outline (現代版已標準化) */
a:focus {
outline: none;
-moz-outline-style: none; /* Firefox 1.5-3.0 */
}
/* 僅在鍵盤導航時顯示焦點,滑鼠點擊不顯示 */
a:focus:not(:focus-visible) {
outline: none;
}
a:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
/* 表單元素同理 */
input:focus:not(:focus-visible),
button:focus:not(:focus-visible) {
outline: none;
}
優勢:完美平衡視覺設計與鍵盤無障礙需求。支援:Chrome 86+、Firefox 85+、Edge 86+、Safari 15.4+。
| 瀏覽器 | outline:none | :focus-visible | -moz-outline |
|---|---|---|---|
| Chrome | ✓ 1+ | ✓ 86+ | ✗ |
| Firefox | ✓ 1.5+ | ✓ 85+ | ✓ 1.5-3.0 (已廢棄) |
| Safari | ✓ 1.2+ | ✓ 15.4+ | ✗ |
| Edge | ✓ 12+ | ✓ 86+ | ✗ |
| IE | ✓ 8+ | ✗ | ✗ |
<a href="#" onfocus="this.blur()">連結</a>
缺點:HTML 與行為耦合、破壞鍵盤導航 (Tab 鍵無法停留)、違反 CSP 原則。
// 頁面載入後執行
document.addEventListener('DOMContentLoaded', function() {
// 針對所有連結與按鈕
document.addEventListener('focus', function(e) {
if (e.target.matches('a, button, input, select, textarea')) {
// 方案 A:立即模糊 (破壞無障礙)
// e.target.blur();
// 方案 B:僅移除視覺 outline (需配合 CSS)
e.target.style.outline = 'none';
}
}, true); // 捕獲階段
});
/* css/focus.htc */
<public:attach event="onfocus" onevent="element.blur()" />
/* CSS 引用 */
a, input, button {
behavior: url(/css/focus.htc);
}
已淘汰:IE 11 移除 HTC 支援,現代專案勿用。
$(document).ready(function() {
// 排除文字類輸入框 (保留編輯焦點視覺)
$('a, button, input:not([type="text"], [type="password"], [type="email"], [type="search"], [type="url"])')
.on('focus', function() {
this.blur(); // 立即失焦
});
});
// 載入 focus-visible polyfill 後
$(function() {
// 為不支援 :focus-visible 的瀏覽器提供 fallback
if (!('focusVisible' in document.documentElement.dataset)) {
$('a, button').on('mousedown', function() {
$(this).addClass('mouse-focus');
}).on('blur', function() {
$(this).removeClass('mouse-focus');
});
}
});
/* CSS 配合 */
a.mouse-focus,
button.mouse-focus {
outline: none;
}
| 做法 | 鍵盤用戶影響 | WCAG 合規 | 建議 |
|---|---|---|---|
outline: none 無替代 | 完全看不見焦點位置 | 違反 2.4.7 Focus Visible | ❌ 禁止 |
this.blur() | 無法透過 Tab 停留操作 | 違反 2.1.1 Keyboard | ❌ 禁止 |
:focus-visible | 鍵盤可見、滑鼠不干擾 | 完美符合 | ✅ 強烈推薦 |
| 自訂焦點樣式 | 可見且符合品牌設計 | 符合 (需對比度 ≥ 3:1) | ✅ 推薦 |
/* 符合品牌設計的焦點指示器 */
:focus-visible {
outline: none; /* 重置預設 */
box-shadow: 0 0 0 3px #fff, 0 0 0 5px #0066cc; /* 雙層陰影適配深淺背景 */
border-radius: 2px;
}
/* 按鈕專屬 */
button:focus-visible,
input[type="button"]:focus-visible,
input[type="submit"]:focus-visible {
box-shadow: 0 0 0 3px #fff, 0 0 0 5px #0066cc, 0 2px 8px rgba(0,0,0,0.15);
}
專案需求分析
├─ 現代瀏覽器為主 (不支援 IE)
│ └─ → 直接使用 :focus-visible + 自訂焦點樣式 ✅
│
├─ 需支援 IE 11
│ ├─ 可接受 Polyfill 體積
│ │ └─ → 引入 focus-visible polyfill + :focus-visible 寫法 ✅
│ └─ 無法使用 Polyfill
│ └─ → outline: none + :focus { outline: auto } (IE 忽略 :focus-visible) ⚠️
│
├─ 必須移除所有焦點樣式 (極少數情況)
│ └─ → outline: none + 確保替代導航機制 (如鍵盤快捷鍵、語音控制) ⚠️
│
└─ 歷史專案快速修復
└─ → a:focus { outline: none } + 記錄技術債、排期重構 📝
:focus-visible 是解決「視覺乾淨」與「鍵盤可見」衝突的標準答案blur():破壞鍵盤導航,違反 WCAG 2.1.1outline: none:違反 WCAG 2.4.7採用 :focus-visible 為核心、自訂焦點樣式為表現層、Polyfill 為相容層的三層架構,是目前最專業、最符合無障礙法規、最易維護的解決方案。