متتبّع التمرير
ScrollspyIntersectionObserver
اسمه كمانسكرول سباي، قائمة «في هذه الصفحة»، فهرس جانبي متتبّع، محتويات الصفحة، مؤشّر القسم الحالي، روابط داخل الصفحة، on this page، in-page navigation، active section nav، page outline، anchor nav، jump links
متتبّع التمرير قائمة بعناوين مستند واحد، والرابط الذي يقابل القسم الظاهر أمام القارئ يُعلَّم فيها وحده، وينتقل التعليم إلى الرابط التالي كلّما تحرّك التمرير. وهو مكوّن من شيئين: روابط تشير إلى معرّفات داخل نفس الصفحة، ومراقب يقرّر أيّها النشط في هذه اللحظة. وهو ليس مسار تنقّل (breadcrumbs)، ولا جدول محتويات، ولا شريط تقدّم قراءة. فمسار التنقّل يصف موقع الصفحة في شجرة الموقع ولا يتغيّر ما دمت فيها، أمّا المتتبّع فلا يتكلّم عن الموقع إطلاقاً بل عن موضعك داخل مستند واحد. وجدول المحتويات هو هذه القائمة نفسها منقوصةً من سلوك التتبّع: روابطه تقفز ولا يعرف أحد أين وصلت. وشريط تقدّم القراءة يعرض نسبة متّصلة من طول المستند ولا يعطيك هدفاً تضغطه، بينما يعطيك المتتبّع اسم قسم محدّد يمكن الانتقال إليه. والفيصل بسيط: مرّر الصفحة دون أن تضغط شيئاً، فإن لم يتغيّر شيء في القائمة فما عندك جدول محتويات.
لو قلت عليه…
العيّنة الحيّة
تفاعل مع الديمو. كل الأجزاء حقيقية ومرقّمة.
ثبّت الحزمة من مدير الحزم الذي تستعمله، ثم استوردها في نقطة الدخول.
كل الخيارات لها قيم افتراضية، فابدأ بملفّ فارغ وأضف ما تحتاجه فقط.
السمة الفاتحة هي الافتراضية، والداكنة تتبع إعداد النظام.
سؤالان يتكرّران: لماذا لا يظهر العنوان؟ ولماذا يتأخّر التعليم؟
تشريح العنصر: كل جزء واسمه
مرّر على أي سطر ليتحدّد مكانه في الديمو فوق.
برومبت البناء
سلوكه في الاتجاه من اليمين لليسار
الجزء ده حصري عندنا.
جهة العمود
ينعكسالقائمة تجلس عند النهاية المنطقية للمقال: يمين الصفحة في الإنجليزية، ويسارها في العربية. نفّذ التخطيط بـ grid-template-columns: 1fr 15rem أو بصفّ flex، فمسارات الأعمدة تُرصف على المحور المضمّن وتنعكس مع direction من تلقاء نفسها. ولا تثبّت العمود بـ position: absolute مع right: 0 ولا بـ float: right، فكلاهما يبقى على اليمين بعد الانعكاس ويجلس فوق النصّ العربي.
شريط التعليم
ينعكسالخط الرفيع الذي يعلّم الرابط النشط يقف على الحافّة المواجهة للنصّ، فهو يسار الرابط في الإنجليزية ويمينه في العربية. اكتبه border-inline-start: 2px solid لا border-left، وارسمه على كل الروابط بلون transparent ثم لوّن النشط وحده، وإلا زحف النصّ بمقدار بكسلين كلّما تبدّل القسم. والحشو المقابل له padding-inline-start حتى تبقى المسافة بين الخط والكلمة على الجهة الصحيحة.
إزاحة المستويات المتداخلة
ينعكسرابط h3 يُزاح للداخل تحت رابط h2 الذي يعلوه، والإزاحة على المحور المضمّن، فمكانها padding-inline-start على العنصر أو margin-inline-start على القائمة الفرعية. والفخّ في التصفير لا في الإضافة: ورقة أنماط المتصفّح تعطي ol و ul أصلاً padding-inline-start: 40px، فسطر padding-left: 0 لا يحذف منها شيئاً في العربية ويترك فجوة ٤٠ بكسل على اليمين. صفّرها بـ padding-inline-start: 0 ثم أعِد إزاحتك أنت، وإن رسمت خطّاً إرشادياً بمحاذاة القائمة الفرعية فاجعله border-inline-start عليها.
المراقب لا ينعكس
لا ينعكسقيم rootMargin أربع قيم فيزيائية بترتيب top ثم right ثم bottom ثم left، لا تقبل كلمة منطقية واحدة ولا تتبدّل مع dir. وهذا لا يضرّ متتبّعاً رأسياً لأن العاملتين فيه هما القيمة العلوية والسفلية، فاترك الجانبيتين صفراً. ونفس الحكم على boundingClientRect داخل كل IntersectionObserverEntry: قيمتا left و right فيه إحداثيان فيزيائيان بالنسبة للشاشة، فإذا رتّبت الأقسام لتختار أعلاها فرتّبها بـ top لأنها وحدها لا تتأثّر بالاتجاه.
شريط تقدّم القراءة
ينعكسإن وضعت شريط تقدّم فوق القائمة فهو يمتلئ من البداية المنطقية، أي من اليمين في العربية. النسبة نفسها لا علاقة لها بالاتجاه لأنها تُقرأ من scrollTop على المحور الرأسي، والذي ينعكس هو الرسم وحده. ولأن transform-origin لا تقبل أي كلمة منطقية أصلاً، فإمّا أن تحرّك inline-size من صفر إلى ١٠٠٪ على عنصر مرسى بـ inset-inline-start: 0، وإمّا أن تكتب transform-origin: right بيدك داخل [dir="rtl"].
أسماؤه في الكود
كل سطر هو كلمة مكتبة واحدة عن نفس الشيء. خد السطر اللي بيكلّم مشروعك.
شوف كمان
آخر تحديث · 2026-08-19