معضلة الحساب التقليدي: عندما نكرر ما يعرفه المتصفح بالفعل

تخيل هذا الموقف المألوف: لديك شبكة من البطاقات التفاعلية، وتريد تطبيق تأثير ظهور متتابع (Staggered Cascade) يضفي لمسة جمالية عند التحميل. يبدو الأمر بسيطاً ومباشراً، أليس كذلك؟ لكن عند التنفيذ الشعلي، تجد نفسك أمام خيارات تشعرك بالاستنزاف التقني.

الخيارات المتاحة سابقاً كانت تنحصر في مسارين أحلاهما مر. إما كتابة حلقة تكرارية بلغة Sass لتوليد عشرات القواعد باستخدام المحدِّد :nth-child() وتضمين متغيرات مخصصة لكل عنصر برقم موقعه الثابت، أو اللجوء إلى حلقة تكرارية بلغة JavaScript لزرع المتغيرات مباشرة في وسم HTML الداخلي عبر style='--idx: 3'.

رياضيات-التصميم-بذكاء-كيف-تنهي-دالتا-sibling-index-و-sibling-count-تعقيدات-css-القديمة

دعنا نكون صادقين: الكود في الحالتين كان مفرطاً وتكرارياً. السبب بسيط: أنت تخبر المتصفح بمعلومة يملكها بالفعل في شجرة DOM. المتصفح يعرف تماماً أن هذا العنصر هو الابن الثالث. البيانات موجودة في أحشائه، لكن لغة CSS لم تكن تملك المفتاح للوصول اليها. الآن، تغيَّر المشهد تماماً.

فك الشفرة: دالتان تبسطان التنسيق الحسابي

قدمت مواصفة CSS Values and Units Module Level 5 حلاً جذرياً عبر دالتين جديدتين: sibling-index() و sibling-count(). بلا وسائط إضافية، وبلا حاجة للالتفاف حول المحرك.

تعيد دالة sibling-index() الترتيب المباشر للعنصر بين أشقائه التابعين لنفس الأب، بدءاً من الرقم 1. العنصر الأول يعيد 1، الخامس يعيد 5. الميزة الذهبية هنا هي أنها تحسب عقد العناصر فقط (Element Nodes)، وتتجاهل النصوص والتعليقات والمسافات الفارغة تماماً. أما دالة sibling-count() فتقدم المجموع الكلي لأشقاء العنصر داخل نفس الأب. هي المقابل المباشر لخاصية children.length في JavaScript، لكنها تسكن الآن داخل ملف التنسيقات.

رياضيات-التصميم-بذكاء-كيف-تنهي-دالتا-sibling-index-و-sibling-count-تعقيدات-css-القديمة

وهنا الفكرة الحاسمة: كليتهما تعيدان عدداً صحيحاً حقيقياً من نوع <integer> وليس نصاً. هذا يعني إمكانية دمجها مباشرة داخل calc()، ودوال الرياضيات المثلثية مثل sin() و cos()، ودوال التقريب. فارق شاسع بينها وبين counter() القديمة التي تعيد نصاً محصوراً في خاصية Content للمركّبات الوهمية.

يجب التمييز بوضوح بين المحدِّد والدالة. المحدد :nth-child() يختار عناصر ولا ينتج قيماً مقاسة، بينما تجلس sibling-index() داخل التصريحات لتمنحك رقماً يمكنك إجراء العمليات الحسابية عليه فوراً.

أنماط برمجية ذكية تستحق التطبيق اليوم

بمجرد استيعاب فكرة أن الناتج مجرد أرقام صحيحة، تتفتح آفاق واسعة لتنفيذ أفكار كانت تتطلب سكريبتات معقدة. التتابع العكسي للتأثيرات ينحصر الآن في معادلة حسابية واحدة: طرح الفهرس من المجموع الكلي مضروباً في الفارق الزمني. العنصر الأخير يبدأ فوراً، والأول يتأخر بتناسب ممتع.

ماذا عن توزيع الألوان؟ يمكنك توزيع تدرجات Hue على عجلة الألوان بالتساوي بدقة عبر تقسين 360 درجة على sibling-count() وضرب الناتج في sibling-index(). لو كان لديك 3 عناصر ستحصل على فوارق 120 درجة، ولو كانت 12 عنصرستحصل على فوارق 30 درجة تلقائياً دون أي تدخل يدوي.

رياضيات-التصميم-بذكاء-كيف-تنهي-دالتا-sibling-index-و-sibling-count-تعقيدات-css-القديمة

القوائم الدائرية هي الأخرى أصبحت لعبة أطفال. التوزيع على محيط دائرية كان يتطلب حساب المثلثات عبر JavaScript. الآن، بدمج sin() و cos() مع شجرة العد الديناميكية، تصبح القائمة الدائرية ميزة CSS خالصة ومستقلة. أضف أو أزل أي عنصر، وسيعيد التصميم تشكيل نفسه بتناسق هندسي عجيب.

المطبات والمفاجآت التقنية: ما لا تخبرك به الأمثلة البسيطة

العمل مع هذه الدوال يخبئ بعض التفاصيل الدقيقة التي قد تسبب حيرة أثناء التطوير. أولى هذه المفاجآت تتجلى في مكونات Web Components وتقنية Shadow DOM. الدالتان تعملان على شجرة DOM الهيكلية وليس الشجرة المرئية المدمجة. إذا حاولت استخدام sibling-index() على عنصر داخلي داخل Shadow Tree، فسيحسب أشقاءه المباشرين هناك فقط، متجاهلاً العناصر التي تم تمريرها عبر وسم <slot> مهما كان عددها.

كذلك، لو حاولت جلب القيمة من خارج المكون عبر ::part()، سيعيد المتصفح الرقم صفر حماية للخصوصية ومنعاً لاستكشاف البنية الداخلية للمكونات المستقلة.

المطب الثاني الأكثر خداعاً هو العنصر المخفي عبر display: none. العناصر التي تمتلك هذا التنسيق تختفي مرئياً ومن شجرة التخطيط، لكنها تظل حية في شجرة DOM. وبما أن دالة sibling-index() تقرأ شجرة المستند، فإن العنصر المخفي سيحتفظ برقمه وحصته في العد!

والنتيجة؟ لو أنشأت قائمة تصفية تخفي العناصر غير المطابقة باستخدام display: none، ستظهر لديك فجوات حركية أو مساحات فارغة في التنسيقات الدائرية المحسوبة. الحل الوحيد هنا هو حذف العناصر نهائياً من DOM أو الاعتماد على حسابات خارجية.

الأداء، الدعم، وإمكانية الوصول

على صعيد الأداء، إعادة ترتيب العناصر أو إضافتها بـ DOM يستدعي إعادة حساب التنسيقات للأشقاء التأثرين. المحرك ينفذ هذا خلال مرحلة Cascade قبل التخطيط والرسم، وهو أسرع بمراحل من التكرار عبر JavaScript. لكن إقحام عنصر في بداية قائمة تضم 10,000 عقدة سيتطلب إعادة حساب المؤشر لـ 10,000 عنصر. للقوائم الضخمة جداً والتغذية اللانهائية، يظل استخدام القوائم الافتراضية (Virtualization) هو الخيار الأرشد.

رياضيات-التصميم-بذكاء-كيف-تنهي-دالتا-sibling-index-و-sibling-count-تعقيدات-css-القديمة

بالنسبة لدعم المتصفحات، أطلقت متصفحات Chrome و Edge (النسخة 138) ومتصفح Safari (النسخة 26.2) الدعم المباشر، بينما يعمل فريق Firefox على إتمام التنفيذ حالياً. للاستخدام في البيئات الإنتاجية اليوم، يظل التدرج المتقدم (Progressive Enhancement) عبر قاعدة @supports (z-index: sibling-index()) هو الطريق الآمن دون المخاطرة بتعطيل الصفحات للمستخدمين.

تذكر دائماً أن هذه الدوال جمالية وتنظيمية فقط. تحريك العناصر مرئياً عبر معادلات الحساب لا يغير ترتيبها الهيكلي في DOM ولا يؤثر على قارئات الشاشة أو التنقل عبر لوحة المفاتيح. احرص على استخدام خصائص ARIA مثل aria-posinset و aria-setsize عبر JavaScript عندما تكون الرؤية الهيكلية ضرورية لذوي الاحتياجات الخاصة.