模板列表選了「作品集」,卡片數量確實變少,鍵盤焦點卻仍停在篩選按鈕上。畫面沒有其他文字提示時,使用者可能不知道篩選是否成功,還是資料仍在載入。除了改變卡片,提供簡短的結果數量,可以讓人確認目前看的是哪一組內容。
這篇處理的是篩選完成後的狀態回報:成功找到幾個、零個,以及清除條件後恢復幾個。結果文字放在一個持續存在的status節點裡,更新時不用把焦點搬到提示,也不用強迫每次跳到列表開頭。
先把結果文字放在固定位置
在列表上方保留一個status區域,讓看得到畫面的人也能直接讀到數量。初始文字可以顯示目前總數;之後篩選完成,再更新同一個節點。role=status提供禮貌的動態區域語意,適合不需要立即打斷操作的結果提示。
<button type="button" data-filter="portfolio">
作品集
</button>
<button type="button" data-filter="all">
清除條件
</button>
<p id="result-status" role="status">
顯示2個模板
</p>
<section id="results" aria-label="模板結果">
<article data-kind="business">商務模板</article>
<article data-kind="portfolio">作品集模板</article>
</section>
status不是會自動計算數量的功能。JavaScript仍要在篩選完成後設定文字,確保提示和實際顯示的卡片一致。不要先更新「找到10個」,列表卻仍留下上一組結果;也不要讓計數只代表資料庫全部記錄,而畫面只顯示當頁其中一部分。
更新結果後,再更新同一個status節點
下面用本頁已存在的兩張卡片示範,不發送網路請求。選取作品集時只顯示一張,清除條件後顯示兩張;若傳入目前沒有的分類,則顯示零張。
const cards = [...document.querySelectorAll(
'#results article'
)];
const status = document.querySelector('#result-status');
function applyFilter(kind) {
let count = 0;
for (const card of cards) {
const show = kind === 'all' ||
card.dataset.kind === kind;
card.hidden = !show;
if (show) count += 1;
}
status.textContent = `顯示${count}個模板`;
}
for (const button of document.querySelectorAll(
'[data-filter]'
)) {
button.addEventListener('click', () => {
applyFilter(button.dataset.filter);
});
}
程式沒有呼叫focus,也沒有把status換成新的DOM節點。使用者可以繼續調整條件,或按Tab往列表走。保留既有節點再修改內容,可以讓動態區域的更新有穩定的載體;不要等結果回來才建立帶有role的提示,然後假設每個輔助技術都會用相同方式處理。
role=status有隱含的aria-live=polite與aria-atomic=true語意。一般結果回報不用再把它升級成alert。若每一次篩選都用assertive或alert打斷目前資訊,可能讓操作變得吵雜,尤其篩選器連續改動時更明顯。
零結果也要回報,但不必把空頁文案塞進狀態
數量為零時,status可以簡短說「顯示0個模板」。列表區域則另外顯示清除條件或調整篩選的操作。這兩者作用不同:狀態文字讓人知道篩選已完成,列表裡的提示幫人決定接下來做什麼。不要把整段長說明都放進每次自動更新的狀態。
若有分類名稱,提示可以寫成「作品集:顯示1個模板」。內容要和目前選取條件對得上;若清除後還保留「作品集」字樣,數量雖然正確,仍會誤導。多個條件時可以用短摘要,詳細條件留在可見的選取標記中,不必每次朗讀所有選項。
這個範例沒有對外部資料做搜尋。正式網站若有分頁,需分清「共找到30個」與「本頁顯示12個」。不要把當頁DOM節點數當成全部結果;計數應來自實際資料或API約定,並在文字裡說清楚是哪一種數量。
非同步篩選要確認回報的是最新那一組
如果篩選會發出API請求,先處理資料載入、錯誤與較舊回應,再設定最終數量。使用者剛選作品集又立即改商務,較晚回來的作品集請求不能蓋掉商務結果。status只負責呈現狀態,不會替你處理請求先後;結果與提示應一起採用同一個被確認為最新的回應。
載入中的文字可以清楚說「正在更新結果」,完成後換成數量。請求失敗時不要把結果數設成零,因為「找到零個」與「資料沒有成功取得」不同。保留已顯示內容、提供重新嘗試,或依產品流程處理錯誤,都要避免讓使用者以為查詢已正常完成。
即時輸入篩選也不應每打一個字就反覆宣布完整結果。可以先按照產品需求等待一小段穩定輸入,或在提交條件後才回報。這屬於互動節奏設計,需要和實際查詢速度一起測;不能只把aria-live設上就認為提示一定不會打擾。
驗證三種狀態,並看焦點留在哪裡
可以把檢查拆成兩個部分。先看資料:顯示的卡片是否符合條件、計數是否相同、清除後是否恢復。再看操作:按鈕焦點是否保留、下一次Tab能否走到合理位置、提示是否仍在可見區域。不要只對文字做比對,因為「顯示1個」可能是對的,卻有另一張應隱藏的卡片仍留在畫面。
若框架每次重新渲染都替換節點,應確認status與篩選按鈕的識別方式穩定。資料更新不一定需要重建整個容器;保留控制項與提示位置,更容易維持焦點。使用元件key時,也要避免只因計數改變就換一個新的key,否則你原本想保留的動態區域會在每次更新時消失再出現。
本機Chromium案例使用同一個status節點,實際點選作品集得到1個、沒有資料的分類得到0個、清除條件恢復2個。每次操作後,焦點仍在剛按的篩選按鈕,卡片顯示數與文字吻合。瀏覽器無障礙資訊也保留status及其動態語意;實際螢幕閱讀器的提示時機與體驗,還需搭配工具與操作流程驗證。
自己的頁面可先從開發者工具檢查status角色,再用鍵盤完成選取、清除與前往結果。確認更新時沒有強制focus,沒有重建整個篩選面板把焦點丟掉,也沒有把目前操作的控制項藏起來。如果產品要移到新頁面或開啟對話框,則按那種互動模式處理焦點,不要把所有操作都套成同一條規則。
進一步使用實際輔助技術驗證時,注意提示是否在適當時機被感知、是否重複,以及內容是否足夠區分不同條件。瀏覽器DOM與無障礙樹可以先確認標記,真正的提示體驗仍受工具、模式與操作流程影響。將結果文字保持簡短、穩定又可見,也能幫助不使用螢幕閱讀器的人。
維護時把卡片資料、選取條件與狀態文字放在同一段完成流程,避免各自更新。新增分類、改分頁或切換語言後,重新測一次成功、零結果和清除三種狀態。這個小回報應讓人確認結果,而不是成為另一個和列表不同步的計數器。

評論0