پرفورمنس CSS و Core Web Vitals؛ وقتی استایل‌ها روی امتیاز گوگل هم اثر می‌ذارن

تا اینجا تو این دوره، چند بار به‌طور پراکنده به پرفورمنس اشاره کردیم؛ مثلاً تو فصل انیمیشن‌ها دیدیم که transform و opacity ارزون‌تر از width و left هستن. حالا با شروع یه فصل مستقل درباره‌ی پرفورمنس، وقتشه یه قدم عقب‌تر بریم و ببینیم CSS دقیقاً چطور روی معیارهای رسمی و قابل‌اندازه‌گیری‌ای مثل Core Web Vitals اثر می‌ذاره؛ معیارهایی که گوگل مستقیم برای رتبه‌بندی صفحات هم ازشون استفاده می‌کنه.

Core Web Vitals دقیقاً چیه؟

Core Web Vitals یه مجموعه از سه معیار اصلیه که گوگل برای اندازه‌گیری تجربه‌ی واقعی کاربر از یه صفحه تعریف کرده. این‌ها فقط عدد انتزاعی نیستن؛ هر کدوم یه جنبه‌ی مشخص از تجربه‌ی کاربر رو می‌سنجن:

معیارچی رو می‌سنجههدف مطلوب
LCP (Largest Contentful Paint)چقدر طول می‌کشه بزرگ‌ترین المنت قابل‌مشاهده رندر بشهکمتر از 2.5 ثانیه
CLS (Cumulative Layout Shift)چقدر محتوای صفحه بدون هشدار جابه‌جا می‌شهکمتر از 0.1
INP (Interaction to Next Paint)چقدر طول می‌کشه صفحه به یه تعامل کاربر (کلیک، تایپ) واکنش نشون بدهکمتر از 200 میلی‌ثانیه

از این سه‌تا، CLS مستقیم‌ترین ارتباط رو با CSS داره، ولی LCP هم به‌شدت تحت‌تأثیر نحوه‌ی نوشتن استایل‌هاست. تو این درس بیشتر رو همین دوتا تمرکز می‌کنیم.

CLS: وقتی صفحه زیر پای کاربر جابه‌جا می‌شه

حتماً براتون پیش اومده که خواستید رو یه دکمه کلیک کنید ولی درست همون لحظه، یه تصویر یا تبلیغ لود شده و همه‌چیز چند سانت پایین‌تر رفته و شما رو یه چیز دیگه کلیک کردید. این دقیقاً همون چیزیه که CLS اندازه می‌گیره.

تو فصل ۲۱ با aspect-ratio آشنا شدیم و دیدیم چطور جلوی پرش تصاویر و iframe ها رو می‌گیره. این دقیقاً یکی از مؤثرترین راه‌های کاهش CLS هست:

img, iframe, video {
  aspect-ratio: attr(width) / attr(height);
  width: 100%;
  height: auto;
}

یه منبع رایج دیگه‌ی CLS، فونت‌های وب هست. وقتی یه فونت سفارشی لود می‌شه، اگه فاصله‌اش تا فونت fallback (که قبل از لود شدن فونت اصلی نمایش داده می‌شه) زیاد باشه، متن با لود شدن فونت جدید، کل چیدمان صفحه رو جابه‌جا می‌کنه:

@font-face {
  font-family: "MyFont";
  src: url("myfont.woff2") format("woff2");
  font-display: swap;
}

ویژگی font-display رفتار این لحظه‌ی انتقال رو کنترل می‌کنه. مقدار swap باعث می‌شه فونت fallback فوراً نمایش داده بشه و بعد جایگزین بشه (که ممکنه کمی جابه‌جایی داشته باشه ولی متن سریع خونا می‌شه)، در حالی که optional اگه فونت به‌موقع لود نشه، اصلاً منتظرش نمی‌مونه و همون fallback رو نگه می‌داره؛ این یکی برای کاهش CLS معمولاً بهتره.

منبع دیگه‌ی CLS: المنت‌هایی که دیرتر داخل صفحه اضافه می‌شن

وقتی یه بنر تبلیغاتی، کوکی‌نوتیس یا هر المنت داینامیک دیگه با جاوااسکریپت به صفحه اضافه می‌شه، اگه از قبل فضایی براش رزرو نشده باشه، بقیه‌ی محتوا رو هل می‌ده. راه‌حل، رزرو کردن فضا از قبل با min-height، حتی اگه محتوا هنوز نیومده باشه:

.ad-slot {
  min-height: 250px;
}

LCP: بزرگ‌ترین المنت باید سریع دیده بشه

LCP معمولاً روی یه تصویر بزرگ، یه ویدیو، یا یه بلوک متنی بزرگ تو بالای صفحه اندازه‌گیری می‌شه. CSS می‌تونه به چند شکل مستقیم روش اثر بذاره:

/* بد: پس‌زمینه‌ی بزرگ که از CSS لود می‌شه، دیرتر از تصویر HTML کشف می‌شه */
.hero {
  background-image: url("hero.jpg");
}

مشکل اینجاست: مرورگر تا زمانی که CSS رو کامل پارس نکنه، متوجه نمی‌شه باید background-image رو دانلود کنه؛ در حالی که یه تگ <img> تو HTML، خیلی زودتر (تو همون preload scanner اولیه) کشف می‌شه. برای المنت‌های بزرگ و حیاتی مثل تصویر اصلی هیرو، استفاده از تگ img به‌جای background-image معمولاً LCP بهتری می‌ده.

مسدود کردن رندر: چرا CSS باید کوچیک و سریع باشه

یه نکته‌ی پایه‌ای که خیلی وقت‌ها نادیده گرفته می‌شه: CSS به‌طور پیش‌فرض یه منبع «مسدودکننده‌ی رندر» (render-blocking) هست. یعنی مرورگر تا وقتی فایل CSS رو کامل دانلود و پارس نکنه، هیچی رو رو صفحه نشون نمی‌ده (حتی اگه HTML از قبل رسیده باشه). به همین دلیل، حجم فایل CSS مستقیم روی LCP اثر می‌ذاره.

راه‌حل‌های رایج شامل حذف کدهای استفاده‌نشده، و جدا کردن استایل‌های «حیاتی» (critical CSS، یعنی چیزی که برای بالای صفحه لازمه) از بقیه هست تا مرورگر زودتر بتونه چیزی نشون بده. این تکنیک‌ها معمولاً بیشتر سمت ابزارهای build انجام می‌شن تا خود نویسنده‌ی CSS، ولی دونستن این‌که «CSS مسدودکننده‌ست» به شما کمک می‌کنه حجم فایل‌هاتون رو از همون ابتدا منطقی نگه دارید.

content-visibility: رندر نکردن چیزی که دیده نمی‌شه

یه ویژگی جدیدتر و خیلی قدرتمند برای پرفورمنس، content-visibility هست. این بهتون اجازه می‌ده به مرورگر بگید بخش‌هایی از صفحه که فعلاً تو viewport نیستن (مثلاً پایین یه صفحه‌ی خیلی طولانی) رو اصلاً رندر نکنه، تا وقتی که کاربر بهشون نزدیک بشه:

.article-section {
  content-visibility: auto;
  contain-intrinsic-size: 0 500px;
}

contain-intrinsic-size یه تخمین اولیه از ارتفاع بخش رندرنشده می‌ده تا مرورگر بتونه از قبل جای مناسبی براش تو اسکرول‌بار در نظر بگیره و از CLS هم جلوگیری بشه.

نکته سئو: Core Web Vitals مستقیم جزو فاکتورهای رتبه‌بندی گوگله، پس بهینه‌سازی CSS از این نظر فقط یه بحث فنی نیست؛ می‌تونه مستقیم رو جایگاه سایت تو نتایج جستجو هم اثر بذاره. با این حال، محتوای مرتبط و باکیفیت همچنان مهم‌ترین فاکتوره؛ Core Web Vitals بیشتر یه فاکتور «تای‌بریکر» بین صفحاتی با کیفیت محتوایی مشابهه.

اشتباه رایج: بهینه‌سازی فقط بر اساس حس شخصی، نه اندازه‌گیری واقعی

خیلی از توسعه‌دهنده‌ها فکر می‌کنن چون سایت رو لپ‌تاپ خودشون سریع لود می‌شه، پس پرفورمنسش خوبه. ولی Core Web Vitals باید با ابزارهای واقعی اندازه‌گیری بشن (مثل Lighthouse یا PageSpeed Insights)، نه فقط با حس چشمی، چون شرایط شبکه و دستگاه کاربر واقعی معمولاً خیلی بدتر از محیط توسعه‌ست.

جمع‌بندی

Core Web Vitals سه معیار قابل‌اندازه‌گیریه که تجربه‌ی واقعی کاربر رو می‌سنجن؛ CSS مستقیم روی CLS (با aspect-ratio و font-display) و LCP (با انتخاب img به‌جای background-image برای تصاویر حیاتی، و کوچیک نگه‌داشتن حجم CSS) اثر می‌ذاره. ویژگی‌های جدیدتری مثل content-visibility هم امکان رندر تنبل بخش‌های خارج از دید رو می‌دن. این‌ها فقط بحث فنی نیستن؛ مستقیم روی تجربه‌ی کاربر و حتی رتبه‌بندی سایت تو گوگل اثر دارن.