استخدام مسار القراءة في CSS للتنقّل المنطقي التسلسلي في التركيز

تاريخ النشر: 1 مايو 2025

تتوفّر السمتان reading-flow وreading-order في CSS من الإصدار 137 من Chrome. توضّح هذه المشاركة الأسباب الكامنة وراء تصميم هذه الخصائص وبعض التفاصيل الموجزة لمساعدتك في البدء باستخدامها.

لقد غيّرت طرق التصميم، مثل الشبكة وflex، عملية تطوير الواجهة الأمامية، ولكن قد تتسبّب مرونتها في حدوث مشكلة لبعض المستخدمين. من السهل جدًا إنشاء حالة لا يتطابق فيها الترتيب المرئي مع ترتيب المصدر في شجرة نموذج المستند (DOM). بما أنّ ترتيب المصدر هو ما يتّبعه المتصفّح عند التنقّل في الموقع الإلكتروني باستخدام لوحة المفاتيح، قد يواجه بعض المستخدمين تنقّلاً غير متوقّع أثناء تصفّح الصفحة.

تم تصميم السمتَين reading-flow وreading-order وإضافتهما إلى مواصفات إعلانات CSS الصورية في محاولة لحلّ هذه المشكلة القديمة.

reading-flow

تتحكّم السمة reading-flow CSS في ترتيب عرض العناصر في تصميم مرن أو شبكي أو على شكل مربّعات لأدوات تسهيل الاستخدام، وفي طريقة التركيز عليها باستخدام طرق التنقّل التسلسلي الخطي.

تأخذ هذه السمة قيمة كلمة رئيسية واحدة، مع قيمة تلقائية هي normal، ما يحافظ على سلوك ترتيب العناصر حسب ترتيب نموذج العناصر في المستند (DOM). لاستخدامها داخل حاوية مرنة، اضبط قيمتها على flex-visual أو flex-flow. لاستخدامها داخل حاوية شبكة، اضبط قيمتها على grid-rows أو grid-columns أو grid-order.

reading-order

تتيح لك خاصية reading-order في CSS إلغاء ترتيب العناصر يدويًا ضمن حاوية تسلسل القراءة. لاستخدام هذه السمة داخل شبكة أو حاوية مرنة أو حاوية حظر، اضبط قيمة reading-flow في الحاوية على source-order واضبط قيمة reading-order للعنصر الفردي على قيمة عدد صحيح.

مثال في flexbox

على سبيل المثال، قد يكون لديك حاوية بتصميم مرن تتضمّن ثلاثة عناصر بترتيب الصفوف العكسي، وتريد أيضًا استخدام السمة 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 للعثور على العنصر السابق القابل للتركيز. يتبع هذا الترتيب العناصر حسب ترتيب المصدر: One وTwo وThree.

من منظور المستخدم النهائي، لا يبدو هذا الإجراء منطقيًا وقد يكون مربكًا جدًا. ويحدث الشيء نفسه إذا استخدمنا أداة للتنقّل المكاني مخصّصة لذوي الاحتياجات الخاصة للتنقّل في الصفحة.

لحلّ هذه المشكلة، اضبط السمة reading-flow:

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

أصبح ترتيب التركيز الآن: واحد، ثلاثة، اثنان. وهذا الترتيب هو نفسه الترتيب المرئي الذي يظهر عند القراءة باللغة الإنجليزية من اليسار إلى اليمين.

إذا كنت تفضّل بدلاً من ذلك الحفاظ على ترتيب التركيز كما كان من المفترض أن يكون في الأصل، أي بترتيب عكسي، يمكنك ضبط ما يلي:

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

أصبح ترتيب التركيز الآن هو ترتيب flex العكسي: اثنان، ثلاثة، واحد. في كلتا الحالتين، يتم احتساب السمة order الخاصة بـ CSS.

مثال على تصميم الشبكة

لمعرفة طريقة عمل ذلك في شبكة، تخيَّل أنّك بصدد إنشاء تخطيط باستخدام CSS للعناصر التي يتم وضعها تلقائيًا في الشبكة مع 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>

نريد أن يشغل العنصر الخامس أكبر مساحة في الأعلى، يليه العنصر الثاني في منتصف الشبكة. يمكن وضع جميع العناصر الفرعية الأخرى تلقائيًا ضمن الشبكة باتّباع نموذج عمود.

.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 لا يتم التعرّف عليه من خلال شجرة تسهيل الاستخدام. عند استخدامها بشكل غير صحيح، قد ينتهي بك الأمر بترتيب تركيز متقطع لا يتطابق مع تجربة قارئ الشاشة. لحلّ هذه المشكلة، تتبَّع الترتيب باستخدام سمة 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 على العناصر الفرعية لعنصر reading-flow.

يُرجى العِلم أنّ العنصر الذي يتضمّن display: contents والذي يرث السمة reading-flow من العنصر الرئيسي للتنسيق سيكون أيضًا حاوية صالحة لترتيب القراءة. يجب مراعاة ذلك عند تصميم موقعك الإلكتروني. يمكنك الاطّلاع على مزيد من المعلومات حول هذا الموضوع في طلبنا للحصول على ملاحظات حول reading-flow وdisplay: contents.

أخبرنا برأيك

جرِّب الأمثلة الواردة في هذه المشاركة وفي reading-flow الأمثلة على chrome.dev، واستخدِم خصائص CSS هذه على مواقعك الإلكترونية. إذا كانت لديك أي ملاحظات، يُرجى طرحها كمشكلة في مستودع CSS Working Group على GitHub. إذا كانت لديك ملاحظات حول سلوك tabindex ونطاق التركيز، يُرجى طرحها كمشكلة في مستودع HTML WHATNOT على GitHub. يسرّنا تلقّي ملاحظاتك حول هذه الميزة.