使用 CSS 閱讀流程,實現邏輯的連續焦點導覽

發布日期:2025 年 5 月 1 日

CSS reading-flowreading-order 屬性可在 Chrome 137 版中使用。本文將說明這些屬性設計背後的原因,並提供一些簡短的詳細資訊,協助您開始使用這些屬性。

格線和 Flex 等版面配置方法已改變前端開發作業,但它們的彈性可能會對部分使用者造成問題。很容易出現視覺順序與 DOM 樹狀結構中的來源順序不符的情況。使用鍵盤瀏覽網站時,瀏覽器會依照這個來源順序進行瀏覽,因此部分使用者在瀏覽網頁時,可能會遇到意外的跳轉情形。

reading-flowreading-order 屬性已設計並新增至 CSS 顯示規格,以便解決這個長期存在的問題。

reading-flow

reading-flow CSS 屬性可控制 Flex、格線或區塊版面配置中元素向無障礙工具公開的順序,以及使用線性順序導覽方法將焦點放在這些元素的方式。

這個屬性會採用一個關鍵字值,預設為 normal,可保留元素的 DOM 排序行為。如要在 Flex 容器中使用,請將其值設為 flex-visualflex-flow。如要在格狀容器中使用,請將其值設為 grid-rowsgrid-columnsgrid-order

reading-order

reading-order CSS 屬性可讓您手動覆寫閱讀流程容器內的項目順序。如要在格狀、Flexbox 或區塊容器中使用此屬性,請將容器的 reading-flow 值設為 source-order,並將個別項目的 reading-order 設為整數值。

Flexbox 範例

舉例來說,您可能有一個 Flex 版面配置容器,其中包含三個元素,並以相反的列順序排列,同時也想使用順序資源重新排列該順序。

<div class="box">
 <a href="#">One</a>
 <a href="#">Two</a>
 <a href="#">Three</a>
</div>
.box {
  display: flex;
  flex-direction: row-reverse;
}

.box :nth-child(1) {
  order: 2;
}

您可以嘗試使用 TAB 鍵瀏覽這些元素,找出下一個可聚焦的元素,並使用 TAB + SHIFT 鍵找出上一個可聚焦的元素。這會按照來源項目的順序:One、Two、Three。

從使用者的角度來看,這麼做毫無意義,而且可能會造成混淆。如果我們使用無障礙空間導覽工具瀏覽網頁,也會發生同樣的情況。

如要修正這個問題,請設定 reading-flow 屬性:

.box {
  reading-flow: flex-visual;
}

焦點順序現在為:一、三、二。這與從左到右閱讀英文時的視覺順序相同。

相反地,如果您想保留焦點順序,並以相反的順序顯示,可以設定:

.box {
  reading-flow: flex-flow;
}

焦點順序現在是反向的 Flex 順序:Two、Three、One。在兩種情況下,CSS order 屬性都會計算在內。

格狀版面配置範例

如要瞭解這項功能在格狀布局中的運作方式,請假設您正在使用 CSS 格狀布局自動放置項目,且有十二個可聚焦的區域。

<div class="wrapper">
 <a href="#">One</a>
 <a href="#">Two</a>
 <a href="#">Three</a>
 <a href="#">Four</a>
 <a href="#">Five</a>
 <a href="#">Six</a>
 <a href="#">Seven</a>
 <a href="#">Eight</a>
 <a href="#">Nine</a>
 <a href="#">Ten</a>
 <a href="#">Eleven</a>
 <a href="#">Twelve</a>
</div>

您希望第五個子項佔據最上方的最大空間,其次是第二個子項,位於格線的中間。所有其他子項都可以依照欄範本自動放置在格線中。

.wrapper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 100px;
}
.wrapper a:nth-child(2) {
  grid-column: 3;
  grid-row: 2 / 4;
}
.wrapper a:nth-child(5) {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}

請嘗試使用 TAB 鍵瀏覽這些元素,找出下一個可聚焦的元素,然後使用 TAB + SHIFT 鍵找出上一個可聚焦的元素。這會按照來源順序排列項目:一到十二。

如要修正這個問題,請設定 reading-flow 屬性:

.wrapper {
  reading-flow: grid-rows;
}

焦點順序現在為:五、一、三、二、四、六、七、八、九、十、十一、十二。按照視覺順序逐列顯示。

如果您想讓閱讀流程依照資料欄的順序進行,可以改用 grid-columns 關鍵字值。焦點順序就會變成五、六、九、七、十、一、二、十一、三、四、八、十二。

.wrapper {
  reading-flow: grid-columns;
}

您也可以嘗試使用 grid-order。焦點順序仍為 1 到 12。這是因為任何項目都未設定 CSS 訂單。

使用 reading-order 的區塊容器

reading-order 屬性可讓您指定在閱讀流程中應造訪的項目,覆寫 reading-flow 屬性設定的順序。當 reading-flow 屬性不是 normal 時,這項屬性只會對有效的閱讀流程容器生效。

.wrapper {
  display: block;
  reading-flow: source-order;
}

.top {
  reading-order: -1;
  inset-inline-start: 50px;
  inset-block-start: 50px;
}

下列區塊容器包含五個項目。沒有任何版面配置規則會依來源順序重新排序元素,但有一個應優先造訪的流程外項目。

<div class="wrapper">
  <a href="#">Item 1</a>
  <a href="#">Item 2</a>
  <a href="#">Item 3</a>
  <a href="#">Item 4</a>
  <a class="top" href="#">Item 5</a>
</div>

將此項目的 reading-order 設為 -1 後,焦點順序會先拜訪該項目,然後再改為讀取流程項目的來源順序。

如需更多範例,請前往 chrome.dev 網站

與 tabindex 互動

以往開發人員會使用 HTML tabindex 全域屬性,讓 HTML 元素可供聚焦,並決定序列聚焦導覽的相對順序。不過,這項屬性有許多缺點和無障礙疑慮。主要問題是,使用正 tabindex 建立的 tabindex 排序焦點導覽,無法由無障礙樹狀結構辨識。如果使用方式不正確,可能會導致焦點順序不穩定,與螢幕閱讀器的體驗不符。如要修正這個問題,請使用 aria-owns HTML 屬性追蹤排序。

在先前的 Flex 範例中,如要取得與使用 reading-flow: flex-visual 相同的結果,您可以採取下列做法。

<div class="box" aria-owns="one three two">
  <a href="#" tabindex="1" id="one">One</a>
  <a href="#" tabindex="3" id="two">Two</a>
  <a href="#" tabindex="2" id="three">Three</a>
</div>

不過,如果容器外部的另一個元素也有 tabindex=1,會發生什麼情況?接著,系統會一起造訪所有含有 tabindex=1 的元素,然後再轉移至下一個遞增的 tabindex 值。這種跳躍式的連續導覽會導致使用者體驗不佳。因此,無障礙專家建議避免使用正 tabindex。我們在設計 reading-flow 時,曾嘗試修正這個問題。

設定 reading-flow 屬性的容器會成為焦點範圍擁有者。也就是說,它會將焦點導覽的範圍限制在容器內,以便在網路文件中移至下一個可聚焦的元素之前,先造訪容器內的每個元素。此外,其直接子項會使用 reading-flow 屬性排序,且系統會忽略正 tabindex,以便排序。不過,您還是可以在閱讀流程項目的子項上設定正 tabindex。

請注意,如果元素具有 display: contents,且從其版面配置父項繼承 reading-flow 屬性,則該元素也會是有效的閱讀流程容器。設計網站時請留意這一點。如要進一步瞭解這項功能,請參閱我們對 reading-flowdisplay: contents 的意見回饋要求

請告訴我們

請試試本文和 reading-flow 中的範例,並在網站上使用這些 CSS 屬性。如有任何意見回饋,請在 CSS 工作小組 GitHub 存放區中提出問題。如果您對 tabindex 和焦點範圍行為有具體意見,請將問題提交至 HTML WHATNOT GitHub 存放區。歡迎提供對這項功能的意見回饋。