الوحدة 4 · الحركة والمعمارية
أداء الرسم في المتصفّح
18 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
اعرف أيّ تغييرات CSS تستدعي التخطيط أو الرسم أو التركيب وحده، وحرّك الخصائص الرخيصة، واستخدم content-visibility وaspect-ratio لتبقى الصفحات الطويلة سريعة ومستقرّة.
- 1خط الرسم في المتصفّح
- 2حرّك الخصائص الرخيصة
- 3تخطَّ العمل الذي لا تراه
- 4لا تحرّك الأشياء بعد ظهورها
- 5أين أنت الآن
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
بدا جدول Waypoint مكتملًا، ثم فتحه الفريق على هاتف Android عمره ثلاث سنوات عبر شبكة Wi-Fi المزدحمة في قاعة المؤتمر. تقطّع إشعار الحفظ، وبدا التمرير الأول لزجًا، ودفعت صور المتحدّثين النص إلى الأسفل وهي تُحمَّل. لم يكن شيء معطوبًا؛ كانت الصفحة ببساطة تؤدّي عملًا أكثر مما تحتاج.
أداء CSS يعود إلى سؤال واحد: كم من مراحل خط الرسم يجبر هذا التغيير المتصفّح على تشغيلها؟
خط الرسم في المتصفّح
بعد أن تغيّر الـ CSS شيئًا ما، يشغّل المتصفّح حتى أربع مراحل لتحديث الشاشة:
- الأنماط (Style): تحديد القواعد المنطبقة وحساب قيم كل عنصر.
- التخطيط (Layout): حساب حجم كل صندوق وموضعه.
- الرسم (Paint): ملء البكسلات: النصوص والألوان والحدود والظلال والصور.
- التركيب (Composite): تجميع الطبقات المرسومة على الـ GPU، مع تطبيق الـ transforms والشفافية.
السرّ أن كل تغيير لا يحتاج إلا إلى البدء من مرحلة معيّنة. غيّر width فيجب أن يعمل التخطيط، ثم الرسم، ثم التركيب. وغيّر background-color فيمكن تخطّي التخطيط. وغيّر transform أو opacity على عنصر له طبقة خاصة به، فيستطيع المتصفّح تخطّي التخطيط والرسم معًا، وتحريك بكسلات موجودة أصلًا على الـ GPU.
في نقرة واحدة لا يهمّ الفرق. أما في حركة تعمل 60 مرة في الثانية، أو تغيير نمط يلمس 500 عنصر، فهو ما يقرّر هل ستبدو الصفحة سلسة أم لا.
حرّك الخصائص الرخيصة
كان إشعار الحفظ يتحرّك هكذا:
@keyframes toast-in {
from { left: -320px; }
to { left: 16px; }
}left خاصية أبعاد: كل إطار يعيد تشغيل التخطيط للإشعار (ويفحص هل تحرّك أيّ شيء آخر)، ثم يعيد الرسم. والإصلاح يُبقي موضع الإشعار ثابتًا ويحرّك صورته بدلًا من ذلك:
.toast {
position: fixed;
left: 16px;
bottom: 16px;
animation: toast-in 250ms ease-out;
}
@keyframes toast-in {
from { translate: -336px 0; opacity: 0; }
to { translate: 0 0; opacity: 1; }
}النتيجة البصرية نفسها، بجزء صغير من العمل. ولهذا استخدمت كل حركة في هذه الدورة translate وscale وopacity وأخواتها. والمنطق نفسه ينطبق على الـ transitions: مرورٌ يغيّر box-shadow يعيد الرسم في كل إطار، وهذا مقبول لبطاقة واحدة وملحوظ لشبكة من خمسين بطاقة تتحرّك معًا. وإظهار ظلّ مرسوم مسبقًا على pseudo-element بتحريك opacity هو البديل الأرخص حين يهمّ الأمر.
تخطَّ العمل الذي لا تراه
يرسم الجدول جلسات يومين، لكن المستخدم يرى ملء شاشة واحدة في كل مرة. content-visibility: auto تتيح للمتصفّح تخطّي التخطيط والرسم للأقسام الواقعة خارج الشاشة:
.day {
content-visibility: auto;
contain-intrinsic-size: auto 1200px;
}المحتوى المتخطّى ليس له حجم، لذا تعطي contain-intrinsic-size المتصفّح تقديرًا يستخدمه كعنصر نائب؛ ومع auto يتذكّر الحجم الحقيقي بعد أن يُرسم القسم مرة. ودونها تنهار الأقسام إلى الصفر ويقفز شريط التمرير أثناء التمرير. يبقى المحتوى في الـ DOM وفي شجرة إمكانية الوصول، ويظل البحث داخل الصفحة يعمل. وcontent-visibility: auto ضمن Baseline منذ سبتمبر 2025، حين أضاف Safari 26 القيمة auto؛ والمتصفّح الذي لا يدعمها يرسم كل الأقسام ببساطة، كما كان يفعل من قبل.
لا تحرّك الأشياء بعد ظهورها
مقياس Cumulative Layout Shift، أحد مقاييس Core Web Vitals، يقيس قفز المحتوى أثناء تحميل الصفحة. وفي CSS يكون المذنب المعتاد وسائط بلا مساحة محجوزة. صورة متحدّث لها width: 100% بلا ارتفاع يكون ارتفاعها 0px حتى تصل الصورة، ثم تدفع كل شيء إلى الأسفل. احجز المساحة:
.speaker img {
width: 100%;
height: auto;
aspect-ratio: 1;
object-fit: cover;
}سمتا width وheight على <img> تؤدّيان العمل نفسه، لأن المتصفّحات تستنتج منهما نسبة الأبعاد. وللخطوط من الويب، font-display: swap مع خط احتياطي بمقاييس مشابهة تمنع النص من إعادة الانسياب حين يُحمَّل الخط.
أين أنت الآن
على مدى عشرين درسًا نقلت جدول Waypoint من ملف أنماط يصارعك إلى ملف تستطيع توقّعه: الـ layers و:where() تحسم التعارضات، والـ custom properties تكشف واجهات الـ components، وgrid والـ subgrid والـ container queries تتولّى التخطيط، وoklch() وlight-dark() تتولّيان الألوان، والخصائص المنطقية تجعله يعمل بالعربية، والحركة لطيفة ورخيصة. والعادة التي تستحق أن تحتفظ بها هي عادة الدرس الأول: قبل أن تغيّر الـ CSS، توقّع ما سيفعله المتصفّح، ثم تحقّق.
أهم النقاط
- كل تغيير بصري يمرّ ببعض مراحل الأنماط والتخطيط والرسم والتركيب؛ خصائص الأبعاد تستدعي التخطيط، والخصائص البصرية تستدعي الرسم، و
transformوopacityتستطيعان تخطّي الاثنين. - حرّك
translateوscaleوrotateوopacity؛ أما تحريكleftأوwidthأوmarginفيعيد تشغيل التخطيط في كل إطار. content-visibility: autoمعcontain-intrinsic-sizeتتيح للمتصفّح تخطّي رسم الأقسام الواقعة خارج الشاشة في الصفحة الطويلة.- حجز المساحة بـ
aspect-ratio(أو بسمتي width وheight) يمنع إزاحات التخطيط حين تُحمَّل الصور والمحتوى المضمّن. - قِس قبل أن تحسّن، باستخدام لوحة Performance في DevTools وخيار وميض الرسم (paint flashing)، وأزل
will-changeحين تنتهي الحركة.