Ngày phát hành: 1 tháng 5 năm 2025
Các thuộc tính CSS reading-flow
và reading-order
có trong Chrome 137.
Bài đăng này giải thích lý do đằng sau thiết kế của các thuộc tính này và một số thông tin chi tiết ngắn gọn để bạn bắt đầu sử dụng.
Các phương thức bố cục như lưới và flex đã thay đổi quá trình phát triển giao diện người dùng, tuy nhiên, tính linh hoạt của các phương thức này có thể gây ra vấn đề cho một số người dùng. Rất dễ tạo ra tình huống thứ tự hình ảnh không khớp với thứ tự nguồn trong cây DOM. Vì trình duyệt tuân theo thứ tự nguồn này nếu bạn điều hướng trang web bằng bàn phím, nên một số người dùng có thể gặp phải tình trạng chuyển đổi không mong muốn khi điều hướng trên một trang.
Các thuộc tính reading-flow
và reading-order
đã được thiết kế và thêm vào quy cách Màn hình CSS để cố gắng giải quyết vấn đề lâu nay.
reading-flow
Thuộc tính CSS reading-flow
kiểm soát thứ tự các phần tử trong bố cục flex, lưới hoặc khối hiển thị cho các công cụ hỗ trợ tiếp cận và cách các phần tử đó được lấy tiêu điểm bằng cách sử dụng các phương thức điều hướng tuần tự tuyến tính.
Phương thức này nhận một giá trị từ khoá, với giá trị mặc định là normal
, giúp duy trì hành vi sắp xếp các phần tử theo thứ tự DOM.
Để sử dụng thuộc tính này bên trong vùng chứa flex, hãy đặt giá trị của thuộc tính này thành flex-visual
hoặc flex-flow
. Để sử dụng thuộc tính này bên trong vùng chứa lưới, hãy đặt giá trị của thuộc tính này thành grid-rows
, grid-columns
hoặc grid-order
.
reading-order
Thuộc tính CSS reading-order
cho phép bạn ghi đè thứ tự của các mục trong vùng chứa luồng đọc theo cách thủ công. Để sử dụng thuộc tính này bên trong một lưới, flex hoặc vùng chứa khối, hãy đặt giá trị reading-flow
trên vùng chứa thành source-order
và đặt reading-order
của từng mục thành một giá trị số nguyên.
Ví dụ trong flexbox
Ví dụ: bạn có thể có một vùng chứa bố cục flex với ba phần tử theo thứ tự hàng đảo ngược và cũng muốn sử dụng thuộc tính thứ tự để xáo trộn lại thứ tự đó.
<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;
}
Bạn có thể thử điều hướng các phần tử này bằng phím TAB để tìm phần tử có thể lấy làm tiêu điểm tiếp theo và phím TAB+SHIFT để tìm phần tử có thể lấy làm tiêu điểm trước đó. Tên này tuân theo thứ tự nguồn: Một, Hai, Ba.
Từ góc độ của người dùng cuối, điều này không hợp lý và có thể gây nhầm lẫn. Điều tương tự cũng xảy ra nếu chúng ta sử dụng công cụ điều hướng không gian hỗ trợ tiếp cận để di chuyển trên trang.
Để khắc phục vấn đề này, hãy đặt thuộc tính reading-flow
:
.box {
reading-flow: flex-visual;
}
Trình tự tiêu điểm hiện là: Một, Ba, Hai. Thứ tự này giống với thứ tự hình ảnh mà bạn sẽ thấy nếu đọc bằng tiếng Anh từ trái sang phải.
Nếu muốn giữ nguyên thứ tự tiêu điểm như ban đầu, theo thứ tự đảo ngược, bạn có thể đặt:
.box {
reading-flow: flex-flow;
}
Thứ tự tiêu điểm hiện là thứ tự flex đảo ngược: Hai, Ba, Một. Trong cả hai trường hợp, thuộc tính order
CSS đều được tính đến.
Ví dụ về bố cục lưới
Để xem cách hoạt động của tính năng này trong lưới, hãy tưởng tượng bạn đang tạo một bố cục có các mục được đặt tự động trong lưới CSS với 12 khu vực có thể lấy tiêu điểm.
<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>
Bạn muốn thành phần con thứ năm chiếm không gian lớn nhất ở trên cùng, theo sau là thành phần con thứ hai ở giữa lưới. Tất cả các phần tử con khác có thể được tự động đặt trong lưới theo mẫu cột.
.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;
}
Hãy thử điều hướng các phần tử này bằng phím TAB để tìm phần tử có thể lấy làm tiêu điểm tiếp theo và phím TAB+SHIFT để tìm phần tử có thể lấy làm tiêu điểm trước đó. Tên này tuân theo thứ tự các mục trong nguồn: Một đến Mười hai.
Để khắc phục vấn đề này, hãy đặt thuộc tính reading-flow
:
.wrapper {
reading-flow: grid-rows;
}
Trình tự tiêu điểm hiện tại là: Năm, Một, Ba, Hai, Bốn, Sáu, Bảy, Tám, Chín, Mười, Mười một, Mười hai. Tệp này tuân theo thứ tự hình ảnh, từng hàng một.
Nếu muốn luồng đọc tuân theo thứ tự cột, bạn có thể sử dụng giá trị từ khoá grid-columns
. Sau đó, thứ tự tiêu điểm sẽ trở thành Năm,
Sáu, Chín, Bảy, Mười, Một, Hai, Mười một, Ba, Bốn, Tám, Mười hai.
.wrapper {
reading-flow: grid-columns;
}
Bạn cũng có thể thử sử dụng grid-order
. Thứ tự tiêu điểm vẫn là Một đến Mười hai.
Nguyên nhân là do bạn chưa đặt thứ tự CSS cho bất kỳ mục nào.
Vùng chứa khối sử dụng reading-order
Thuộc tính reading-order
cho phép bạn chỉ định thời điểm trong luồng đọc cần truy cập vào một mục, ghi đè thứ tự do thuộc tính reading-flow
đặt. Thuộc tính này chỉ có hiệu lực trên vùng chứa luồng đọc hợp lệ, khi thuộc tính reading-flow
không phải là normal
.
.wrapper {
display: block;
reading-flow: source-order;
}
.top {
reading-order: -1;
inset-inline-start: 50px;
inset-block-start: 50px;
}
Vùng chứa khối sau đây chứa 5 mục. Không có quy tắc bố cục nào sắp xếp lại các phần tử theo thứ tự nguồn, nhưng có một mục luồng cần được truy cập trước tiên.
<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>
Bằng cách đặt reading-order
của mục này thành -1
, thứ tự tiêu điểm sẽ truy cập vào mục này trước khi quay lại thứ tự nguồn cho các mục còn lại trong luồng đọc.
Bạn có thể tìm thấy thêm ví dụ trên trang web chrome.dev.
Tương tác với tabindex
Trước đây, các nhà phát triển đã sử dụng thuộc tính chung tabindex
của HTML để đặt tiêu điểm cho các phần tử HTML và xác định thứ tự tương đối để điều hướng tiêu điểm tuần tự. Tuy nhiên, thuộc tính này có nhiều hạn chế và vấn đề về khả năng hỗ trợ tiếp cận. Mối lo ngại chính là việc điều hướng tiêu điểm theo thứ tự tabindex được tạo bằng cách sử dụng tabindex dương không được cây hỗ trợ tiếp cận nhận dạng. Khi sử dụng không đúng cách, bạn có thể gặp phải thứ tự tiêu điểm bị nhảy không khớp với trải nghiệm trên trình đọc màn hình. Để khắc phục vấn đề đó, hãy theo dõi thứ tự bằng thuộc tính HTML aria-owns.
Trong ví dụ về flex trước, để có được kết quả tương tự như khi sử dụng reading-flow: flex-visual
, bạn có thể làm như sau.
<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>
Nhưng điều gì sẽ xảy ra nếu một phần tử khác bên ngoài vùng chứa cũng có tabindex=1
?
Sau đó, tất cả các phần tử có tabindex=1
sẽ được truy cập cùng nhau, trước khi chúng ta chuyển sang giá trị tabindex gia tăng tiếp theo. Thao tác điều hướng tuần tự bị giật này sẽ khiến người dùng có trải nghiệm không tốt. Do đó, các chuyên gia về hỗ trợ tiếp cận nên tránh sử dụng tabindex dương. Chúng tôi đã cố gắng khắc phục vấn đề này khi thiết kế reading-flow
.
Vùng chứa có thuộc tính reading-flow
được đặt sẽ trở thành chủ sở hữu phạm vi tiêu điểm.
Điều này có nghĩa là nó sẽ điều hướng tiêu điểm tuần tự để truy cập vào mọi phần tử bên trong vùng chứa trước khi chuyển sang phần tử có thể lấy tiêu điểm tiếp theo trong tài liệu web. Ngoài ra, các phần tử con trực tiếp của phần tử này được sắp xếp bằng cách sử dụng thuộc tính reading-flow và tabindex dương sẽ bị bỏ qua cho mục đích sắp xếp. Bạn vẫn có thể đặt tabindex dương trên các phần tử con của một mục luồng đọc.
Xin lưu ý rằng một phần tử có display: contents
kế thừa thuộc tính reading-flow
từ phần tử mẹ bố cục cũng sẽ là một vùng chứa luồng đọc hợp lệ. Hãy lưu ý điều này khi thiết kế trang web. Hãy đọc thêm về vấn đề này trong yêu cầu phản hồi của chúng tôi về reading-flow
và display: contents
.
Hãy cho chúng tôi biết
Hãy thử các ví dụ trong bài đăng này và trong các ví dụ về reading-flow
trên chrome.dev, đồng thời sử dụng các thuộc tính CSS này trên trang web của bạn. Nếu bạn có ý kiến phản hồi, hãy gửi ý kiến đó dưới dạng vấn đề trên kho lưu trữ GitHub của Nhóm làm việc về CSS. Nếu bạn có ý kiến phản hồi cụ thể về tabindex và hành vi xác định phạm vi tiêu điểm, hãy báo cáo vấn đề đó trong kho lưu trữ GitHub HTML WHATNOT. Chúng tôi rất mong nhận được ý kiến phản hồi của bạn về tính năng này.