تغییر دادن DOM از طریق حذف عناصر، تغییر attributeهایشان، کلاسهایشان یا توسّط انیمیشن، همه و همه باعث میشوند تا مرورگر دوباره استایلها را بررسی کند و ببیند به چه عناصری باید چه استایلهایی اعمال شود و خیلی وقتها چیدمان صفحه یا قسمتی از آن را درست کند. به این فرآیند «محاسبهی استایلهای نهایی» یا «computed styles calculation» گفته میشود.
اوّلین مرحلهی این فرآیند، تولید لیستی از انتخابگرها مطابق با عناصر صفحه است. در این مرحله مرورگر میفهمد که چه کلاسها، شبهانتخابگرها یا آیدیهایی به چه عناصری باید تعلّق بگیرند.
در مرحلهی دوم این فرآیند، مرورگر نگاه میکند که تک تک دستورات css با کدام انتخابگرها تطابق پیدا کردهاند، اولویّت استایلها چگونه است و هر عنصر در نهایت چه استایلهایی خواهد گرفت. در موتور Blink (یعنی موتور رندر مرورگر Chrome و Opera) هزینهی مرحلهی اوّل و دوم تقریباً یکسان است.
- پیچیدگی انتخابگرها را کم کنید؛ از یک متدلوژی کلاسمحور مثل BEM استفاده کنید.
- تعداد عناصری را که استایلهایشان باید پردازش شود کم کنید.
پیچیدگی انتخابگرها را کم کنید
در سادهترین حالت فقط با یک کلاس، عنصری در صفحه را انتخاب میکنید:
.title {
/* استایلها */
}
امّا هرچه پروژه بزرگتر میشود، انتخابگرها پیچیدهتر میشوند، مثلاً در نهایت ممکن است انتخابگرهایی مثل این بنویسید:
.box:nth-last-child(-n+1) .title {
/* استایلها */
}
در این صورت، برای اینکه مرورگر بفهمد این استایلها را باید به کدام عنصرها بدهد میپرسد «آیا عنصری با کلاس title داریم که پدرش -n+1 اُمین فرزندِ عنصری با کلاس box باشد؟» پیدا کردن جواب این طور سؤالها ممکن است وقت زیادی بگیرد، که نسبت به انتخابگرهای استفاده شده و مرورگری که کد را اجرا میکند این زمان تفاوت دارد. همین عنصر مثال فعلی را میشد با دادن یک کلاس جداگانه به این صورت انتخاب کرد:
.final-box-title {
/* استایلها */
}
شاید برای شما کمی سخت باشد که اسم مناسبی برای کلاسهایتان انتخاب کنید، ولی کار مرورگر در این روش به شدّت سادهتر میشود. مثلاً در حالت قبلی برای اینکه مرورگر بداند که این عنصر چندمین فرزند است، لازم است همه چیز را در مورد سایر عناصر بداند و اینکه هر کدامشان بعد از کدامیک آمدهاند. این خیلی پرهزینهتر از تطبیق انتخابگرهایی است که فقط با یک کلاس خالی منطبق شدهاند.
تعداد عناصری که استایل میگیرند را کم کنید
عامل دیگری که معمولاً مهمتر هم هست، مقدار کاری است که مرورگر هنگام تغییرات عنصر به صورت خالص انجام میدهد.
به طور کلّی در بدترین حالت، هزینهی محاسبهی استایل با ضرب تعداد دستورات css در تعداد عناصر موجود در صفحه به دست میآید، زیرا به ازای هر عنصر باید تک تک انتخابگرهایی که نوشته شده بررسی شود که آیا با آن عنصر تطابق دارد یا نه.
محاسبهی استایل در خیلی از مواقع میتواند فقط چند عنصر خاص را هدف بگیرد، به جای اینکه همهی صفحه را نامعتبر بداند و دوباره استایل تمام عناصر را محاسبه کند. در مرورگرهای جدید این موضوع زیاد مطرح نیست، زیرا این طور نیست که مرورگر به ازای هر تغییر، بیاید تمام عناصری را که قابلیّت تحت تأثیر قرار گرفتن دارند، بررسی کند. ولی از طرفی مرورگرهای قدیمیتر، تا این اندازه بهینه نیستند. اینجاست که شما باید تعداد عناصر نامعتبر را کم کنید (نامعتبر از این لحاظ که استایل قدیمیشان نامعتبر است و باید دوباره محاسبه شود).
هزینهی محاسبهی استایلهای خود را بسنجید
ساده ترین و بهترین روش برای سنجیدن style calculation استفاده از پنل Performance در DevTools مرورگر کروم است. برای شروع کلید F12 را فشار دهید تا DevTools باز شود. سپس به سربرگ Performance بروید و روی دکمهی ضبط کلیک کنید و با سایتتان کار کنید. وقتی ضبط را متوقّف کنید با تصویری مثل زیر مواجه میشوید:

در این تصویر روی قطعاتی که به رنگ بنفش هستند کلیک کنید تا جزئیات بیشتر آن را ببینید.

در این تصویری که الآن میبینید با یک style calculation طولانی که ۱۸ میلیثانیه طول کشیده است مواجه هستیم. اگر این محاسبه در حین اجرای انیمیشنی مثل اسکرول اتّفاق افتاده باشد باعث قفل شدن اسکرول و jank قابل توجّهی شده است.
در قسمت Call Site Stack میتوانید ببینید کدام خط از کد جاوااسکریپت شما مسئول اجرای این style calculation است. علاوه بر آن در قسمت Elements affected میتوانید ببینید چه تعداد عنصر تحت تأثیر آن قرار گرفته اند (که در این مثال حدود ۴۰۰ عنصر است). از طرفی مدّت زمان اجرای این محاسبه را هم میبینید. با استفاده از این اطّلاعات میتوانید دنبال یافتن راهی برای اصلاح کد خود بگردید.
از BEM استفاده کنید
روشهایی مثل BEM (Block, Element, Modifier) برای کدنویسی css واقعاً در افزایش سرعت این بخش تأثیر دارند، زیرا در این روش توصیه شده است که هر چیزی فقط یک کلاس داشته باشد، و در جاهایی که نیاز به نوشتن سلسلهمراتب است به این شکل عمل میشود:
.list { }
.list__list-item { }
در شرایط خاص مثل وقتی که میخواهید به آخرین فرزند، استایلی جداگانه بدهید، به این شکل آن را انتخاب میکنید:
.list__list-item--last-child {}
اگر دنبال راهی برای سازماندهی css میگردید، BEM واقعاً نقطهی شروع خوبی برای این کار است، هم از نظر ساختار کد، و هم از این نظر که وقتی دنبال استایلهایتان میگردید راحت میتوانید آنها را پیدا کنید.
برای یادگیری کامل روش BEM برای نامگذاری کلاسهای CSS به لینک زیر مراجعه کنید:
معرفی روش BEM برای نامگذاری کلاسها
اگر از روش BEM خوشتان نمیآید، روشهای دیگری نزدیک به آن هم وجود دارد. ولی از لحاظ سرعت و performance باید ارزیابی شوند.