前端互動 QA 不只看畫面:focus-visible、hover 與 touch target 怎麼一起驗收

前端頁面交付時,最容易被忽略的不是「正常狀態」好不好看,而是使用者開始操作之後,元件狀態是否還能清楚、穩定、可預期。按鈕 hover 有回饋,鍵盤 tab 到連結時有焦點圈,手機上按得到,表單錯誤不會被鍵盤遮住,這些細節平常很安靜,但它們決定網站是否真的能被使用。
我會把這種檢查稱為「互動狀態 QA」。它不是只跑 Lighthouse,也不是只問設計稿有沒有標 hover,而是用實際輸入方式檢查 UI:鍵盤、滑鼠、觸控、螢幕寬度、瀏覽器錯誤、表單回饋與可復現的紀錄。對 UCAMC 這類內容站來說,文章卡片、CTA、分類標籤、搜尋入口、表單與導覽都需要被這樣檢查,因為讀者不一定只用桌機滑鼠閱讀。
先列出真正會被操作的元件
互動 QA 第一件事不是打開 DevTools,而是盤點頁面上哪些元件需要被操作。常見清單包含:
- Header 導覽連結與 Logo 回首頁。
- Hero CTA、文章卡片 CTA、分類與標籤連結。
- Blog 列表的文章標題、閱讀按鈕、分類入口。
- 表單欄位、送出按鈕、錯誤訊息與成功訊息。
- 手機版選單、展開/收合區塊、carousel 或 tabs。
- 文章內的外部連結、程式碼區塊與可水平捲動內容。
這一步的重點是避免只測最顯眼的主按鈕。很多破壞體驗的問題藏在次要入口,例如分類 pill 在手機上太小、卡片整塊可點但焦點只出現在文字、或 hover 狀態在觸控裝置上沒有任何替代線索。
鍵盤檢查:focus-visible 要能看見,而且順序合理
鍵盤檢查可以從最基本的流程開始:重新整理頁面後按 Tab,觀察焦點順序是否跟畫面閱讀順序一致。每一個可操作元素都應該有清楚的 :focus-visible 樣式,而且不能只靠瀏覽器預設外框在複雜背景中勉強可見。
我會記錄三件事:
[observe] keyboard focus path
page: /
viewport: 390 x 1200 and desktop
checks:
- first Tab reaches skip/header or first meaningful link
- CTA focus ring is visible against background
- card links and category pills show focus-visible state
judgement:
keyboard users can identify current position without guessing.
如果焦點圈被 overflow: hidden 裁掉,或按鈕 hover 有設計但 focus 沒有,就應該修 CSS,而不是在 QA 紀錄裡寫「鍵盤可操作」。可操作不等於可理解;使用者必須知道自己現在停在哪裡。
滑鼠與觸控要分開看,不要把 hover 當成唯一回饋
桌機滑鼠常靠 hover 提供預告:按鈕背景變深、卡片陰影浮起、連結底線出現。但手機沒有穩定的 hover,觸控回饋通常只能靠按下瞬間、版面間距與明確標籤。若設計只在 hover 狀態才顯示「可點」,行動版讀者可能完全不知道那是一個入口。
我會用兩個層級檢查:
- 桌機:hover 是否清楚但不誇張,active 是否有短暫回饋,游標是否符合可點區域。
- 手機:不依賴 hover 也能辨識入口,文字、邊框、箭頭或按鈕形狀足以提示可操作性。
例如文章卡片可以有 hover 陰影,但標題連結與「閱讀文章」CTA 仍要在靜止狀態下看得出來。分類 pill 如果是連結,也應該保留足夠對比與可點面積,而不是只像裝飾標籤。
Touch target:不要只看寬度,要看手指能不能穩定點到
手機 QA 常見誤判是只看「元素有沒有出現在畫面裡」,卻沒有檢查是否容易點擊。WCAG 常用的參考值是至少約 44 x 44px 的可操作區域;實務上也要看元素之間的間距,避免兩個連結貼太近。
DevTools 的行動裝置模式可以協助檢查,但不要只相信截圖。可以在 Elements 面板選取 CTA 或連結,看 computed box size、padding 與實際可點範圍。如果文字很短,例如「SEO」或「AI」,就更需要靠 padding 補足可點面積。
一份好的 touch target 紀錄應該像這樣:
[verify] mobile touch target
viewport: 390 x 1200
selector: .category-pill
observed:
min-height: 36px
horizontal padding: 12px
nearby links have visible gap
judgement:
acceptable for lightweight taxonomy navigation;
primary CTA still uses larger target area.
不是每個輔助連結都必須長得像主按鈕,但越重要的動作,就越不能用過小的點擊區域交付。
表單錯誤狀態要一起測,因為它也是互動的一部分
很多網站的表單正常送出看起來沒問題,但錯誤狀態一出現就破版:錯誤訊息換行推擠 layout、紅色文字對比不足、focus 沒有移到第一個錯誤欄位,或手機鍵盤打開後遮住按鈕。這些都不是單純的「表單文案」問題,而是互動狀態 QA。
檢查時可以故意送出空白表單,或填入錯誤格式,觀察:
- 錯誤訊息是否靠近對應欄位。
- 欄位是否有
aria-invalid或可被輔助工具理解的關聯。 - 焦點是否回到第一個需要修正的欄位。
- 手機版鍵盤打開後,錯誤訊息和送出按鈕是否仍可操作。
- 錯誤顏色是否不只靠顏色傳達,最好搭配文字或圖示。
如果網站目前沒有公開表單,仍可把這段流程保留給後台搜尋、訂閱表單、留言功能或未來活動頁。互動 QA 的價值在於建立共用檢查習慣,而不是每次從零開始。
用 DevTools 補證據:computed styles、scrollWidth 與 console
視覺檢查很重要,但光說「看起來可以」不夠。前端 QA 最好補一點可重複證據:
[verify] page overflow
viewport: 390 x 1200
html.clientWidth: 390
html.scrollWidth: 390
result: no page-level horizontal overflow
[verify] CTA focus style
selector: .legacy-button:focus-visible
outline: 3px solid / visible blue ring
outline-offset: 3px
result: focus ring is not clipped
如果有程式碼區塊或長 URL,還要分開檢查 pre.scrollWidth 與頁面 documentElement.scrollWidth。程式碼區塊可以自己水平捲動,但不能讓整個頁面跟著溢出。Console 也要掃一次,因為互動元件有時候視覺正常,實際點擊卻丟 JavaScript error。
把 QA 紀錄寫成「觀察、變更、驗證」三段
前端互動問題常常是小修,但小修最容易被忘記原因。建議每次紀錄時都拆成三段:
[observe]
Mobile Blog cards show clear article titles, but secondary links
have weak focus-visible contrast.
[change]
Increase focus-visible outline contrast and add outline-offset.
No route or content slug change.
[verify]
npm run lint: passed
npm run build: passed
390px DOM probe: no horizontal overflow;
focused CTA outline visible and not clipped.
這種紀錄可以讓之後的維護者知道:這次改的是互動狀態,不是整體品牌重設;驗證的是鍵盤、手機與 build,不是只截一張漂亮圖。
UCAMC 內容站的最低互動驗收線
若時間有限,我會把 UCAMC 的日常互動 QA 壓成一條最低驗收線:
/、/blog、代表性文章頁在 390px 沒有 page-level horizontal overflow。- Header、Hero CTA、文章卡片標題與「閱讀文章」都能用鍵盤 Tab 到。
- 主要 CTA 有清楚
focus-visible,不被 border radius 或 overflow 裁切。 - 文章頁圖片、程式碼區塊與表格不會讓整頁溢出。
- 手機版可點元素不過度密集,重要 CTA 有足夠點擊面積。
- Console 沒有互動時才出現的錯誤。
這些檢查不會讓網站變得花俏,但會讓網站更像一個長期維護的品牌內容站:每一個入口都可讀、可點、可驗證,也能留下下一次維護能接手的證據。