استفاده از جریان خواندن CSS برای ناوبری فوکوس متوالی منطقی، استفاده از جریان خواندن CSS برای ناوبری فوکوس متوالی منطقی، استفاده از جریان خواندن CSS برای ناوبری فوکوس متوالی منطقی، استفاده از جریان خواندن CSS برای ناوبری فوکوس متوالی منطقی

منتشر شده: ۱ مه ۲۰۲۵

ویژگی‌های reading-flow و reading-order CSS از Chrome 137 در دسترس هستند. این پست دلایل طراحی این ویژگی‌ها و برخی جزئیات مختصر برای شروع کار با آنها را توضیح می‌دهد.

روش‌های طرح‌بندی مانند grid و flex توسعه frontend را متحول کرده‌اند، با این حال انعطاف‌پذیری آنها می‌تواند برای برخی از کاربران مشکل ایجاد کند. ایجاد موقعیتی که در آن ترتیب بصری با ترتیب منبع در درخت DOM مطابقت نداشته باشد، بسیار آسان است. از آنجایی که این ترتیب منبع همان چیزی است که مرورگر در صورت پیمایش سایت با استفاده از صفحه کلید دنبال می‌کند، برخی از کاربران ممکن است هنگام پیمایش در یک صفحه با پرش‌های غیرمنتظره مواجه شوند.

ویژگی‌های reading-flow و reading-order طراحی و به مشخصات نمایش CSS اضافه شده‌اند تا این مشکل دیرینه را حل کنند.

reading-flow

ویژگی CSS reading-flow ترتیب نمایش عناصر در یک طرح‌بندی flex، grid یا block را در معرض ابزارهای دسترسی‌پذیری و نحوه‌ی فوکوس شدن آنها با استفاده از روش‌های ناوبری خطی متوالی را کنترل می‌کند.

این تابع یک مقدار کلمه کلیدی می‌گیرد که مقدار پیش‌فرض آن normal و رفتار مرتب‌سازی عناصر را به ترتیب DOM حفظ می‌کند. برای استفاده از آن درون یک کانتینر flex، مقدار آن را روی flex-visual یا flex-flow تنظیم کنید. برای استفاده از آن درون یک کانتینر grid، مقدار آن را روی grid-rows ، grid-columns یا grid-order تنظیم کنید.

reading-order

ویژگی reading-order در CSS به شما امکان می‌دهد تا به صورت دستی ترتیب آیتم‌ها را در یک محفظه جریان خواندن تغییر دهید. برای استفاده از این ویژگی در یک محفظه grid، flex یا block، مقدار reading-flow را در محفظه روی source-order تنظیم کنید و reading-order هر آیتم را روی یک مقدار صحیح تنظیم کنید.

مثال در فلکس باکس

برای مثال، ممکن است یک کانتینر طرح‌بندی فلکس با سه عنصر با ترتیب ردیف معکوس داشته باشید و همچنین بخواهید از ویژگی order برای تغییر ترتیب آنها استفاده کنید.

<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;
}

ترتیب تمرکز اکنون به این صورت است: یک، سه، دو. این همان ترتیب بصری است که اگر به زبان انگلیسی از چپ به راست می‌خوانید، خواهید داشت.

اگر در عوض، ترجیح می‌دهید ترتیب فوکوس را همانطور که در ابتدا منظور شده بود، به ترتیب معکوس حفظ کنید، می‌توانید تنظیم کنید:

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

ترتیب فوکوس اکنون به صورت معکوس flex order است: Two، Three، One. در هر دو مورد، ویژگی order در CSS در نظر گرفته شده است.

مثال با طرح شبکه‌ای

برای اینکه ببینید این چطور در یک شبکه کار می‌کند، تصور کنید که در حال ایجاد یک طرح‌بندی با آیتم‌های قرار داده شده خودکار در شبکه 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 استفاده کنید. ترتیب فوکوس از یک تا دوازده باقی می‌ماند. دلیل این امر این است که هیچ ترتیب 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

از لحاظ تاریخی، توسعه‌دهندگان از ویژگی سراسری tabindex در HTML برای قابل فوکوس کردن عناصر 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 برویم، تمام عناصر با tabindex=1 با هم بازدید می‌شوند. این پیمایش متوالی پرش‌دار منجر به تجربه کاربری بدی خواهد شد. از این رو، متخصصان دسترسی‌پذیری توصیه می‌کنند از tabindex مثبت اجتناب شود . ما سعی کردیم هنگام طراحی reading-flow ، این مشکل را برطرف کنیم.

یک کانتینر که ویژگی reading-flow آن تنظیم شده باشد، مالک محدوده فوکوس می‌شود. این بدان معناست که ناوبری فوکوس متوالی را طوری محدود می‌کند که قبل از رفتن به عنصر قابل فوکوس بعدی در یک سند وب، از هر عنصر داخل کانتینر بازدید کند. علاوه بر این، فرزندان مستقیم آن با استفاده از ویژگی reading-flow مرتب می‌شوند و tabindex مثبت برای اهداف مرتب‌سازی نادیده گرفته می‌شود. هنوز هم می‌توان یک tabindex مثبت برای فرزندان یک آیتم reading-flow تنظیم کرد.

توجه داشته باشید که عنصری با display: contents که ویژگی reading-flow را از والد layout خود به ارث می‌برد، یک محفظه معتبر برای جریان خواندن نیز خواهد بود. هنگام طراحی سایت خود به این نکته توجه داشته باشید. در درخواست ما برای بازخورد در مورد reading-flow و display: contents بیشتر در این مورد بخوانید.

به ما اطلاع دهید

مثال‌های این پست و مثال‌های reading-flow در chrome.dev را امتحان کنید و از این ویژگی‌های CSS در سایت‌های خود استفاده کنید. اگر بازخوردی دارید، آن را به عنوان یک مشکل در مخزن گروه کاری CSS در گیت‌هاب مطرح کنید. اگر به طور خاص در مورد رفتار tabindex و focus scoping بازخوردی دارید، آن را به عنوان یک مشکل در مخزن HTML WHATNOT گیت‌هاب مطرح کنید. ما از بازخورد شما در مورد این ویژگی استقبال می‌کنیم.