เผยแพร่: 1 พฤษภาคม 2025
พร็อพเพอร์ตี้ CSS reading-flow
และ reading-order
พร้อมใช้งานใน Chrome 137
โพสต์นี้จะอธิบายเหตุผลเบื้องหลังการออกแบบพร็อพเพอร์ตี้เหล่านี้และรายละเอียดคร่าวๆ เพื่อช่วยให้คุณเริ่มต้นใช้งาน
วิธีการจัดวาง เช่น ตารางกริดและ Flex ได้เปลี่ยนแปลงการพัฒนาส่วนหน้าไปอย่างมาก แต่ความยืดหยุ่นของวิธีการเหล่านี้อาจทำให้เกิดปัญหากับผู้ใช้บางราย การสร้างสถานการณ์ที่ลําดับภาพไม่ตรงกับลําดับแหล่งที่มาในลําดับ DOM นั้นทําได้ง่ายๆ เนื่องจากเบราว์เซอร์จะทําตามลําดับแหล่งที่มานี้หากคุณไปยังส่วนต่างๆ ของเว็บไซต์โดยใช้แป้นพิมพ์ ผู้ใช้บางรายจึงอาจพบการกระโดดไปมาโดยไม่คาดคิดขณะไปยังส่วนต่างๆ ของหน้า
เราได้ออกแบบและเพิ่มพร็อพเพอร์ตี้ reading-flow
และ reading-order
ลงในข้อกำหนดการแสดงผล CSS เพื่อพยายามแก้ปัญหานี้ที่แก้มาอย่างยาวนาน
reading-flow
พร็อพเพอร์ตี้ reading-flow
CSS จะควบคุมลําดับที่องค์ประกอบในเลย์เอาต์ Flex, ตาราง หรือบล็อกจะแสดงต่อเครื่องมือการช่วยเหลือพิเศษ และวิธีที่องค์ประกอบเหล่านั้นได้รับโฟกัสโดยใช้วิธีการไปยังส่วนต่างๆ ตามลําดับ
โดยจะใช้ค่าคีย์เวิร์ด 1 ค่า โดยมีค่าเริ่มต้นเป็น normal
ซึ่งจะคงลักษณะการเรียงลําดับองค์ประกอบตามลําดับ DOM
หากต้องการใช้ภายในคอนเทนเนอร์ Flex ให้ตั้งค่าเป็น flex-visual
หรือ flex-flow
หากต้องการใช้ภายในคอนเทนเนอร์ตารางกริด ให้ตั้งค่าเป็น grid-rows
, grid-columns
หรือ grid-order
reading-order
พร็อพเพอร์ตี้ CSS reading-order
ช่วยให้คุณลบล้างลําดับของรายการในคอนเทนเนอร์ขั้นตอนการอ่านด้วยตนเองได้ หากต้องการใช้พร็อพเพอร์ตี้นี้ภายในคอนเทนเนอร์ตารางกริด คอนเทนเนอร์ Flex หรือคอนเทนเนอร์บล็อก ให้ตั้งค่า reading-flow
ในคอนเทนเนอร์เป็น source-order
และตั้งค่า reading-order
ของแต่ละรายการเป็นค่าจำนวนเต็ม
ตัวอย่างใน Flexbox
ตัวอย่างเช่น คุณอาจมีคอนเทนเนอร์เลย์เอาต์ Flex ที่มีองค์ประกอบ 3 รายการเรียงตามลําดับแถวย้อนกลับ และต้องการใช้พร็อพเพอร์ตี้ลําดับเพื่อสับเปลี่ยนลําดับนั้นใหม่
<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 เพื่อค้นหาองค์ประกอบที่โฟกัสได้ก่อนหน้า ซึ่งจะเป็นไปตามลําดับรายการในแหล่งที่มา เช่น หนึ่ง สอง สาม
จากมุมมองของผู้ใช้ปลายทาง การดำเนินการนี้ไม่สมเหตุสมผลและอาจสร้างความสับสนอย่างมาก สิ่งเดียวกันนี้จะเกิดขึ้นหากเราใช้เครื่องมือการนําทางเชิงพื้นที่เพื่อการช่วยเหลือพิเศษเพื่อไปยังส่วนต่างๆ ของหน้า
วิธีแก้ไขปัญหานี้ ให้ตั้งค่าพร็อพเพอร์ตี้ reading-flow
ดังนี้
.box {
reading-flow: flex-visual;
}
ตอนนี้ลําดับโฟกัสคือ 1, 3, 2 ซึ่งจะเหมือนกับลำดับภาพที่คุณจะเห็นหากอ่านภาษาอังกฤษจากซ้ายไปขวา
หากต้องการคงลําดับโฟกัสตามเดิมโดยเรียงจากหลังไปหน้า ให้ตั้งค่าดังนี้
.box {
reading-flow: flex-flow;
}
ตอนนี้ลําดับโฟกัสจะเป็นลําดับ Flex แบบย้อนกลับ คือ 2, 3, 1 ในกรณีทั้ง 2 รูปแบบ ระบบจะพิจารณาพร็อพเพอร์ตี้ order
ของ CSS
ตัวอย่างที่มีเลย์เอาต์ตารางกริด
หากต้องการดูวิธีการทํางานในตารางกริด ให้จินตนาการว่าคุณกําลังสร้างเลย์เอาต์ด้วยรายการที่วางโดยอัตโนมัติของ CSS Grid ซึ่งมีพื้นที่ที่โฟกัสได้ 12 รายการ
<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>
คุณต้องการให้รูปภาพเด็กคนที่ 5 ใช้พื้นที่มากที่สุดที่ด้านบนสุด ตามด้วยรูปภาพเด็กคนที่ 2 ตรงกลางตารางกริด ระบบจะวางองค์ประกอบย่อยอื่นๆ ทั้งหมดภายในตารางกริดโดยอัตโนมัติตามเทมเพลตคอลัมน์
.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 เพื่อค้นหาองค์ประกอบก่อนหน้าที่โฟกัสได้ รายการนี้ตามรายการในลําดับแหล่งที่มา: 1 ถึง 12
วิธีแก้ไขปัญหานี้ ให้ตั้งค่าพร็อพเพอร์ตี้ reading-flow
ดังนี้
.wrapper {
reading-flow: grid-rows;
}
ตอนนี้ลําดับโฟกัสคือ 5, 1, 3, 2, 4, 6, 7, 8, 9, 10, 11, 12 โดยจะเรียงตามลำดับภาพทีละแถว
หากต้องการให้ขั้นตอนการอ่านเป็นไปตามลําดับคอลัมน์แทน ให้ใช้ค่าคีย์เวิร์ด grid-columns
แทน ลำดับโฟกัสจึงกลายเป็น 5, 6, 9, 7, 10, 1, 2, 11, 3, 4, 8, 12
.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;
}
คอนเทนเนอร์บล็อกต่อไปนี้มี 5 รายการ ไม่มีกฎเลย์เอาต์ที่จะจัดเรียงองค์ประกอบใหม่จากลําดับแหล่งที่มา แต่มีรายการที่ควรเข้าชมก่อน 1 รายการซึ่งอยู่นอกลําดับ
<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
ที่ผ่านมา นักพัฒนาซอฟต์แวร์ใช้แอตทริบิวต์ส่วนกลาง tabindex
ของ HTML เพื่อให้องค์ประกอบ HTML โฟกัสได้ และกำหนดลําดับสัมพัทธ์สำหรับการไปยังส่วนต่างๆ แบบโฟกัสตามลำดับ อย่างไรก็ตาม แอตทริบิวต์นี้มีข้อเสียและข้อกังวลด้านการช่วยเหลือพิเศษหลายประการ ข้อกังวลหลักคือ การนำทางโฟกัสตามลําดับ tabindex ที่สร้างขึ้นโดยใช้ tabindex บวกจะไม่ได้รับการยอมรับจากต้นไม้การช่วยเหลือพิเศษ หากใช้ไม่ถูกต้อง คุณอาจพบว่าลําดับโฟกัสกระโดดไปมาซึ่งไม่ตรงกับประสบการณ์การใช้งานในโปรแกรมอ่านหน้าจอ วิธีแก้ไขคือติดตามการสั่งซื้อโดยใช้แอตทริบิวต์ HTML ของ aria-owns
ในตัวอย่าง 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-flow
และ display: contents
โปรดแจ้งให้เราทราบ
ลองใช้ตัวอย่างในโพสต์นี้และในตัวอย่าง reading-flow
ใน chrome.dev และใช้พร็อพเพอร์ตี้ CSS เหล่านี้ในเว็บไซต์ของคุณ หากมีความคิดเห็นใดๆ โปรดแจ้งเป็นปัญหาในที่เก็บ GitHub ของกลุ่มทํางาน CSS หากมีความคิดเห็นเกี่ยวกับแท็บอินเด็กซ์และลักษณะการกําหนดขอบเขตโฟกัสโดยเฉพาะ โปรดแจ้งปัญหาใน HTML WHATNOT GitHub Repo เราอยากทราบความคิดเห็นของคุณเกี่ยวกับฟีเจอร์นี้