هناك سبب يجعل التأثير المنظوري بـJavaScript يبدو دائماً غير صحيح قليلاً — منفصلاً بعض الشيء، كأن الطبقات تسبح نصف إطار خلف الصفحة. هذا ليس كوداً رديئاً. السبب هو أن أحداث التمرير تصل إلى JavaScript بعد أن يكون المتصفح قد رسم التمرير بالفعل. حلّ المتصفح هذا مرة واحدة، حين حوّل الترويسات اللاصقة إلى position: sticky. Scroll-driven animations هي نفس الخطوة، مطبّقة على جميع التأثيرات المرتبطة بالتمرير دفعة واحدة.
لعشر سنوات، كان تحريك الصور المصغّرة إلى صور البطل يعني تقنية واحدة: قِس العنصر قبل وبعد، وزيّف الفرق بـtransform، ثم اعرضه. FLIP. كل مكتبة حركات تفعل ذلك، وكل منها تدفع ثمنه بـJavaScript على الخيط الرئيسي في أسوأ لحظة ممكنة. View Transitions API ينقل الحيلة بأكملها إلى المتصفح — ومنذ React 19.2 وNext.js 16، يتكون العقد بأكمله من خاصية واحدة اسمها name.
قائمة من ألف تعليق تُعرَض ببطء، فتلجأ إلى react-window – وفي مقابل تمرير سلس تخسر Ctrl+F، وطباعة الصفحة، وجزءًا من تنقّل قارئ الشاشة، لأن العناصر خارج النافذة المرئية تتوقف عن الوجود فعليًا في DOM. تحلّ content-visibility المشكلة نفسها بطريقة مختلفة: تبقى العناصر في DOM، ويكتفي المتصفح بتجاهل العمل المكلف من تخطيط وطلاء لها، إلى أن تقترب من المنطقة المرئية – والمفاجئ أنها قادرة على كشفها مؤقتًا حين تبحث فيها عن نص.
في مقال إتاحة الوصول، كانت النافذة المنبثقة بخاصية display:none، التي بقيت مع ذلك موجودة في شجرة إتاحة الوصول، مثالًا على خطأ نتج عن بناء نافذة منبثقة من الصفر باستخدام عناصر div. السؤال الحقيقي هو: لماذا كان يجب بناؤها من الصفر أصلًا؟ أفحص ما يقدّمه عنصر <dialog> الأصيل وسمة popover مجّانًا – الطبقة العليا، وفخّ التركيز، والإغلاق الخفيف (light dismiss) – وأين يختلف هذان الآليتان بما يكفي لجعل الخلط بينهما طريقًا مباشرًا لواجهة غير قابلة للوصول.
الصنف الأداتي .mt-4 يخسر أمام القاعدة .card .card__header .card__title، رغم أنه منطقيًّا ينبغي أن يفوز لأنه أُضيف لاحقًا. هذا ليس مصادفة – إنها الخصوصية (specificity) تعمل تمامًا كما صُمِّمت لتعمل. تُدخل @layer محورًا جديدًا كليًّا لفضّ النزاعات، يعمل قبل الخصوصية لا معها – وله فخّ واحد غير بديهي لدرجة أن حتى بعض التوثيق على الإنترنت يخطئ فيه.
حقل النموذج ينبغي أن يُضاء بالأحمر حين يكون الإدخال بداخله غير صالح. أمر بسيط – إلا أن CSS ظلّ طوال 25 عامًا عاجزًا عن أن يسأل عنصرًا عمّا يجري في داخله، بل العكس فقط. أفحص كيف تعكس :has() هذا الاتجاه، وكيف تختلف عن أدوات الربط (combinators) المعتادة، وأين تُكلِّف هذه القدرة الجديدة الأداء فعليًّا.