iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0
Modern Web

前端不寫 Python,照樣 ship 一把網頁無障礙 CLI系列 第 2

Day 02:我們的工具說「全綠」,人工審查回來 9 條

  • 分享至 

  • xImage
  •  

Day 02 · W1 · 無障礙線 · 難度 ★★☆☆☆

本系列由 AI 協作撰寫。 內容、技術判斷、程式碼由 light-design 數位顧問團隊與 Claude 共同產出,最終由作者驗證後 publish。完整協作模式與把關方式見 Day 01

2026 年 4 月 30 日,我們把自家網站送去申請 MODA 無障礙 AAA 標章。

送件之前,我們用自己寫的檢測工具掃過一遍。0 個 fail。

12 天後,審查結果回來了:9 條。

主軸

今天要講的不是「審查很嚴」。是一件對所有做自動化檢測的人都成立的事:

工具「有這條規則」,跟工具「抓得到這個問題」,是兩件不同的事。

那 9 條裡面,只有 2 條是我們根本沒寫規則。另外 7 條,規則檔就躺在專案裡,跑過,然後給了綠燈。

12 天才知道自己錯在哪

先講這個迴圈,因為它決定了所有事。

送審回饋迴圈時間軸:4 月 30 日送件,等待 12 天後於 5 月 12 日收到第一輪 9 條意見,接著花 8 天修正,5 月 20 日回函。等待期間開發者無法得知問題所在

第一輪的迴圈。深色是你在動的時間,淺色是你在等的時間。等的那 12 天,你連要改什麼都不知道。

送出去到知道結果,12 天

這 12 天你什麼都不能做,因為你不知道要改什麼。

對接案的人來說,這個數字很痛。標案合約寫「需通過無障礙標章」
你排時程時得把這段等待算進去,而且不只一輪。改完再送,又要等。

真正的問題不是等待本身,是你沒辦法在送出去之前先知道答案
官方檢測工具是桌面 GUI 程式,你沒辦法把它接進 CI,讓每次 commit 都跑一遍。你只能寫完、送出、等、收到、改、再送。

這就是我們當初決定自己蓋一把 CLI 的原因。跑得起來的東西才能進 pipeline,進得了 pipeline 才能在寫的當下就知道。

9 條裡,只有 2 條是「沒寫規則」

收到報告那天,我本來以為會看到一堆沒實作的檢核項目。實際比對之後才發現不是。

當時的版本是 v0.3.4。九條意見對應的檢核碼,我一條一條回去翻專案:

情況 條數
規則檔不存在,根本沒檢 2
規則檔存在,跑過,回報通過 7

7:2。問題的大宗不是「還沒做」,是「做了但沒抓到」。

這比缺規則麻煩得多。缺規則你知道自己缺,補上就好。規則存在卻給綠燈,你會相信那個綠燈。

九個審查意見依「工具為什麼漏抓」分成五類:焦點行為未模擬 3 條、深色模式未掃描 1 條、規則邏輯方向寫反 1 條、白名單認不出自製元件 1 條、規則理解錯誤 1 條、規則根本不存在 2 條

九條意見的根因分佈。灰色那兩格是「沒寫規則」,其餘七格都是「寫了規則但漏抓」,而且漏抓的理由各不相同。

盲區一:工具只走「頁面剛打開」那一個狀態

三條意見指向同一個結構性問題。

審查意見裡有這樣的描述:展開右上角漢堡選單之後,下一個焦點要直接進入選單內容;在選單收合之前,焦點不能跑出去。另一條講聯絡頁的彈出視窗,同樣的要求。

我們的鍵盤檢測是這樣寫的:載入頁面,從頭 Tab 到尾,記錄每一站的焦點位置與樣式。

看起來合理。問題是它只走了一種狀態 —— 頁面剛打開、什麼都沒點的那個狀態。

漢堡選單展開後的焦點順序、彈出視窗開啟後的焦點是否被限制在視窗內,這些都要先做一個互動動作才會出現。工具從來沒點過任何東西,自然永遠看不到。

這不是我們特別粗心。焦點限制(focus trap)是自動化無障礙工具普遍的弱項,主流工具多數也不直接驗證這件事。原因很單純:要驗它,工具就得會操作網頁,而不只是讀網頁。

差別有多大?「讀網頁」是拿到 HTML 之後分析結構,快、便宜、可以一次跑幾百頁。「操作網頁」是開一個真的瀏覽器、找到那顆漢堡按鈕、點下去、等動畫跑完、再開始 Tab,然後判斷焦點有沒有跑出選單外。後者慢一個數量級,而且每一種元件的開啟方式都不一樣。

我們後來補的做法是:讓工具先去找頁面上「看起來會展開東西」的按鈕,逐一點開,在每個展開狀態下重跑一次焦點檢查。

聽起來理所當然。但這代表檢測工具從「靜態分析器」變成了「會操作介面的機器人」,那是完全不同量級的工程。

盲區二:深色模式是另一個網站

一條對比度意見,數字是 2.24

標準要求 4.5:1。2.24 差得不是一點點。但我們的對比度檢測明明跑過,而且是用 Playwright 真的開瀏覽器量算出來的顏色,不是讀原始碼裡寫的色碼。

問題在於:Playwright 預設用淺色模式開頁面。我們的網站支援深色模式,而那組文字顏色只在深色模式下才會套用。

工具量的是淺色模式的網站,審查員看的是深色模式的網站。兩邊都沒錯,看的不是同一個東西。

這件事在有設計系統的專案上特別容易發生。色票通常是一組語意變數,--text-secondary 在淺色模式解析成一個值、深色模式解析成另一個值,兩邊各自都「有經過設計」。但驗證通常只做一次,而且做在預設模式上;深色那組色票的實際對比,往往從來沒有人算過,因為它在設計稿裡看起來也還好。真正的落差要等到瀏覽器把兩層顏色疊起來、算出實際比值,才會現形。而檢測工具如果只開一種模式,它連現形的機會都不給你。

這一條之後,我們加了一個旗標讓兩種模式都跑一次再合併結果:

# 淺色與深色都掃,結果合併(需要實際渲染)
a11y-moda site https://example.com --level AAA --render --dark-mode

盲區三:規則寫了,但方向反了

這條最尷尬。

意見說:首頁有三個方案,三個「查看方案」連結文字一模一樣但指向不同頁面,需要各自加上 title 讓報讀軟體區分。

我們有一條規則在管連結的 title。它檢查的是:title 的連結,title 內容是不是跟連結文字重複多餘。

該檢查的是:文字重複、目的不同的連結,有沒有缺 title 來區分。

同一個屬性、同一條成功準則,兩個相反的方向。規則跑得好好的,一個 fail 都沒有,因為它根本在找別的東西。

這種錯 LLM 救不了。 模型再強,你叫它判斷的題目本身就問錯了,它只會很有信心地給你一個正確答案 —— 對於錯的問題。

盲區四:白名單認不出自製的元件

首頁有一個客戶評價的輪播。意見說輪播需要暫停鍵,而且暫停鍵要是進入該區塊的第一個焦點。

我們的規則怎麼找輪播?看 class 名稱裡有沒有 carouselsliderswiper 這些常見字串。

那個輪播是網站建置平台自己生成的,class 名稱完全不在名單裡。

啟發式白名單只認得你想得到的寫法。 你列了十種常見的,就漏掉第十一種。而真實世界的網站,第十一種永遠存在。

這不是審查太嚴,是工具鏈缺一塊

寫到這裡要講清楚立場。

這 9 條沒有一條是審查方吹毛求疵。 每一條都是真實存在、會影響真實使用者的問題 —— 鍵盤使用者打開選單後焦點跑掉、深色模式下文字看不清楚、報讀軟體唸出三個一模一樣的「查看方案」。這些如果沒被指出來,受影響的是實際在用網站的人。

審查員做的是機器目前做不到的事:開啟選單、按下 Tab、切換深色模式、用報讀軟體實際聽一遍。 那是行為與情境的判斷,不是靜態掃描。

所以問題不在制度,在工具鏈缺了「送審前自己抓」這一段

那 9 條後來全部修掉了,工具也跟著補了對應的檢測能力。整個過程收斂到 0,第 28 天會攤開完整紀錄。今天想留下的是這三句:

  • 綠燈可能只代表「這條規則沒發現問題」,不代表「這個問題不存在」
  • 工具的盲區有形狀,而且可以被列舉、被補
  • 每一次被打回,都是一次免費的工具測試

今天的重點

  • 「有規則」不等於「抓得到」。 9 條意見裡 7 條的規則檔早就存在,而且跑出綠燈。
  • 自動化工具的四種典型盲區:只走預設狀態、只掃單一顯示模式、規則方向寫反、白名單認不出沒見過的寫法。
  • 12 天的回饋迴圈是真正的成本。 不是等待本身痛,是送出去之前你沒辦法自己知道答案。
  • 機器補人,不取代人。 審查員抓到的是需要實際操作與聆聽才能發現的問題,那正是自動化目前最弱的一塊。

明天 Day 3,講我們怎麼把規範文件餵給 AI,讓它讀完自己生出檢測規則:讀規範、生程式、跑、失敗、修、再跑的迴圈長什麼樣。


上一篇
Day 01:前端不寫 Python,照樣 ship 一把網頁無障礙 CLI
系列文
前端不寫 Python,照樣 ship 一把網頁無障礙 CLI2
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言