Filter 順序由使用者掃描成本決定
核心原則
選項清單按使用者掃描順序排序、不按資料來源預設。 短清單先看完、長清單花更多時間 — 把短清單放前面讓使用者先排除一個維度、再面對長清單。字母排序對「找已知名稱」有效;多選 facet 場景下使用者通常不知道確切選項名、需要 scan,這時候掃描成本主導。
為什麼掃描成本優先於字母排序
商業邏輯
當清單有多個選項供使用者挑選,選項數量影響掃描時間。使用者在 facet UI 的行為不是「找已知 tag」、是「看到有什麼可選、選有興趣的」 — 這是探索式行為、不是查找式行為。
| 行為類型 | 適合的排序 |
|---|---|
| 查找式(知道要什麼) | 字母排序 — 二分查找 |
| 探索式(看有什麼) | 掃描成本排序 — 短清單先 |
字母排序是資料庫思維(穩定、可預測),掃描成本排序是 UX 思維(縮短決策時間)。Facet 場景幾乎都是後者。
兩條維度收斂的順序
當有多個 facet 維度可選、使用者通常逐維度收斂:先用一個維度砍掉一半結果、再用第二個維度精選。短清單放前面讓「第一刀」決策快速。
這次任務的應用
觀察
Pagefind filter 預設按 filter key 字母排序:tag < type,所以 Tag 先顯示。
實際內容:
| Filter | 選項數量 |
|---|---|
| Type | ~5 個(post / card / glossary 等 section) |
| Tag | ~80 個(站上所有 tags) |
判讀
Type 短、Tag 長 — 預期使用者行為是「先按 type 收斂(這是 post 還是 glossary?)、再進 tag 找主題」。Tag 在前等於要使用者先面對 80 個選項,認知成本高。
把順序倒過來:Type 先顯示讓使用者先用 section 收斂、再進 Tag 找。
執行
1function reorderFilters() {
2 var blocks = filter.querySelectorAll('.pagefind-ui__filter-block');
3 var desiredOrder = ['type', 'tag'];
4 var byKey = {};
5 blocks.forEach(b => {
6 var key = b.querySelector('.pagefind-ui__filter-name').textContent.trim().toLowerCase();
7 byKey[key] = b;
8 });
9 desiredOrder.forEach(k => byKey[k] && filter.appendChild(byKey[k]));
10}內在屬性比較:四種排序策略
| 策略 | 適合場景 | 失敗模式 |
|---|---|---|
| 字母排序 | 使用者知道確切選項名 | 探索式場景下掃描慢 |
| 掃描成本排序(短先長後) | 探索式 facet | 「短」「長」邊界模糊時不穩 |
| 使用頻率排序 | 有 analytics 資料 | 冷啟動時無資料、需要默認 |
| 語意分組排序 | 選項有明顯子類別 | 子類別劃分本身需要設計 |
選擇順序:有 analytics → 頻率排序;沒有 → 掃描成本排序;都不適用 → 字母排序。
排序原則的延伸應用
同類 facet 內的選項排序
Tag 內部的 80 個 tag 怎麼排?
| 內部排序方式 | 適用 |
|---|---|
| 字母排序 | 使用者知道想找哪個 tag |
| 計數排序(最多文章的 tag 在前) | 探索式、引導使用者進熱門主題 |
| 編輯精選 | 站方有特定主題策略 |
當前接受 pagefind 的字母排序(成本最低、且 80 個 tag 做計數排序需要額外索引處理)。
選項數量門檻
短清單跟長清單的邊界沒有絕對值,常用啟發:
- ≤ 7 個選項:可一眼掃完、放前面
- 8-20 個:中等、需要結構(縮排、分組)
- 20+ 個:長清單、放後面或加搜尋框
Type 5 個落在「短」、Tag 80 個落在「長」 — 順序明顯。
設計取捨:選項清單的排序策略
四種做法、各自機會成本不同。預設依使用者行為性質選 — 探索式 → A、查找式 → B、有 analytics → C、有子類別 → D。
A:掃描成本排序(短先長後)(探索式 facet 的預設)
- 機制:選項數量少的維度放前面(type 5 個 → 先;tag 80 個 → 後)
- 選 A 的理由:使用者先用短清單收斂一刀、再面對長清單;認知成本低
- 適合:探索式 facet(使用者不知道確切選項名)
- 代價:需要主動覆寫資料來源預設(不能直接用 DB 順序)
B:字母排序
- 機制:按 alphabetical 排
- 跟 A 的取捨:B 對「找已知名稱」高效(二分查找)、A 對「探索式選擇」高效;但 facet 場景幾乎都是探索式
- B 比 A 好的情境:使用者通常知道確切選項名(國家清單、語言清單)
C:使用頻率排序(最常用在前)
- 機制:按 analytics 統計、最高頻選項在前
- 跟 A/B 的取捨:C 比 A 更精準(用真實資料)、但需要 analytics + 冷啟動時無資料
- C 比 A 好的情境:有足夠 analytics、且使用者偏好集中(80/20 分布明顯)
D:語意分組排序
- 機制:把選項分子類別、組內再排
- 跟 A 的取捨:D 對「選項有明顯子類別」更直觀(產品類別 / 功能類別)、A 對純扁平清單夠用
- D 比 A 好的情境:選項有清楚的層級結構(電商 facet:類別 > 子類別 > 選項)
判讀徵兆
| 訊號 | 排序問題 | 修正動作 |
|---|---|---|
| 使用者抱怨「選項太多找不到」 | 長清單在前、掃描負擔大 | 把短清單前移、或加搜尋框 |
| 同類選項使用者卡在第一步 | 第一個維度選項過多 | 換成更少選項的維度當第一步 |
| 預設排序看起來「隨機」 | 資料來源排序與 UX 不符 | 主動 reorder、不接受預設 |
| 新增選項後順序錯亂 | reorder 邏輯依賴 hardcoded list | 改用屬性分類(例如選項數量自動排) |
核心原則:UI 排序是設計決策、不是技術選擇。預設順序通常反映資料來源結構、不反映使用者行為 — 主動覆寫是常態、不是例外。
跟 #55-#66 Filter × Source 系列 的關係:本卡是「filter UI 的排序」、Filter × Source 系列是「filter 行為的層級」 — 兩個維度互補。設計 filter UI 時兩者都要顧:本卡決定「哪個選項放前面」、#58 決定「篩選的定義域是哪一層」、#59 決定「filter 跟 source 怎麼合成」。