Layout جایی است که مرورگر اطلاعات هندسی عناصر - اندازه و مکان آنها را در صفحه کشف می کند. هر عنصر بر اساس CSS مورد استفاده، محتویات عنصر یا یک عنصر والد، اطلاعات اندازه صریح یا ضمنی خواهد داشت. این فرآیند در کروم Layout نام دارد.
Layout جایی است که مرورگر اطلاعات هندسی عناصر را مشخص می کند: اندازه و مکان آنها در صفحه. هر عنصر بر اساس CSS مورد استفاده، محتویات عنصر یا یک عنصر والد، اطلاعات اندازه صریح یا ضمنی خواهد داشت. این فرآیند در کروم Layout (و مرورگرهای مشتق شده مانند Edge) و Safari نامیده می شود. در فایرفاکس به آن Reflow گفته می شود، اما روند عملاً یکسان است.
مشابه محاسبات سبک، نگرانی های فوری برای هزینه طرح بندی عبارتند از:
- تعداد عناصری که نیاز به چیدمان دارند، که محصول فرعی اندازه DOM صفحه است.
- پیچیدگی آن طرحبندیها.
خلاصه
- Layout تأثیر مستقیمی بر تأخیر تعامل دارد
- طرح بندی معمولاً به کل سند اختصاص دارد.
- تعداد عناصر DOM بر عملکرد تأثیر می گذارد. شما باید تا حد امکان از فعال کردن طرح بندی خودداری کنید.
- از طرحبندیهای همزمان اجباری و کوبیدن چیدمان خودداری کنید. مقادیر سبک را بخوانید سپس تغییراتی در سبک ایجاد کنید.
اثرات طرحبندی بر تأخیر تعامل
هنگامی که کاربر با صفحه تعامل دارد، این تعاملات باید تا حد امکان سریع باشد. مدت زمانی که طول می کشد تا یک تعامل کامل شود - زمانی که مرورگر فریم بعدی را برای نشان دادن نتایج تعامل ارائه می دهد پایان می یابد - به عنوان تأخیر تعامل شناخته می شود. این جنبه ای از عملکرد صفحه است که متریک Interaction to Next Paint اندازه گیری می کند.
مدت زمانی که مرورگر برای ارائه فریم بعدی در پاسخ به تعامل کاربر طول می کشد، به عنوان تاخیر ارائه تعامل شناخته می شود. هدف از تعامل، ارائه بازخورد بصری به منظور ارسال سیگنال به کاربر مبنی بر وقوع چیزی است، و بهروزرسانیهای بصری میتوانند مقداری کار طرحبندی را برای دستیابی به آن هدف شامل شوند.
برای اینکه INP وب سایت خود را تا حد امکان پایین نگه دارید، مهم است که در صورت امکان از طرح بندی خودداری کنید. اگر امکان اجتناب از طرح بندی به طور کامل وجود ندارد، مهم است که کار طرح بندی را محدود کنید تا مرورگر بتواند فریم بعدی را به سرعت ارائه دهد.
تا جایی که امکان دارد از طرح بندی خودداری کنید
وقتی استایل را تغییر میدهید، مرورگر بررسی میکند که آیا هر یک از تغییرات نیاز به محاسبه چیدمان دارد یا خیر و درخت رندر بهروزرسانی میشود. تغییرات در «ویژگیهای هندسی»، مانند عرض، ارتفاع، سمت چپ یا بالا، همگی به چیدمان نیاز دارند.
.box {
width: 20px;
height: 20px;
}
/**
* Changing width and height
* triggers layout.
*/
.box--expanded {
width: 200px;
height: 350px;
}
Layout تقریباً همیشه به کل سند اختصاص دارد. اگر عناصر زیادی دارید، زمان زیادی طول می کشد تا مکان ها و ابعاد همه آنها را بفهمید.
اگر امکان اجتناب از طرحبندی وجود ندارد، نکته کلیدی این است که یک بار دیگر از Chrome DevTools استفاده کنید تا ببینید چقدر طول میکشد، و تعیین کنید که آیا چیدمان دلیل ایجاد گلوگاه است یا خیر. ابتدا DevTools را باز کنید، به تب Timeline بروید، رکورد را بزنید و با سایت خود تعامل برقرار کنید. هنگامی که ضبط را متوقف می کنید، جزئیات عملکرد سایت خود را مشاهده می کنید:
هنگامی که ردیابی را در مثال بالا بررسی می کنیم، می بینیم که برای هر فریم بیش از 28 میلی ثانیه در طرح بندی داخلی صرف می شود، که وقتی 16 میلی ثانیه برای دریافت یک فریم روی صفحه در یک انیمیشن داریم، بسیار زیاد است. همچنین میتوانید ببینید که DevTools اندازه درخت (1618 عنصر در این مورد) و تعداد گرههایی را که به چیدمان نیاز دارند (در این مورد 5) به شما میگوید.
به خاطر داشته باشید که توصیه کلی در اینجا این است که در صورت امکان از طرح بندی خودداری کنید - اما همیشه نمی توان از طرح بندی اجتناب کرد. در مواردی که نمی توانید از طرح بندی اجتناب کنید، بدانید که هزینه چیدمان با اندازه DOM ارتباط دارد. اگرچه رابطه بین این دو به طور محکم مرتبط نیست، DOM های بزرگتر معمولاً هزینه های طرح بندی بیشتری را متحمل می شوند.
از طرحبندیهای همزمان اجباری خودداری کنید
ارسال یک قاب به صفحه نمایش به این ترتیب است:
ابتدا جاوا اسکریپت اجرا می شود، سپس محاسبات استایل، سپس layout. با این حال، میتوان مرورگر را مجبور کرد که طرحبندی را زودتر با جاوا اسکریپت انجام دهد. این چیدمان همزمان اجباری نامیده می شود.
اولین چیزی که باید در نظر داشته باشید این است که با اجرای جاوا اسکریپت، تمام مقادیر طرح بندی قدیمی از فریم قبلی شناخته شده و در دسترس شما هستند تا بتوانید پرس و جو کنید. بنابراین اگر، برای مثال، می خواهید ارتفاع یک عنصر را بنویسید (بیایید آن را "جعبه" بنامیم) در ابتدای فریم، می توانید کدی مانند این بنویسید:
// Schedule our function to run at the start of the frame:
requestAnimationFrame(logBoxHeight);
function logBoxHeight () {
// Gets the height of the box in pixels and logs it out:
console.log(box.offsetHeight);
}
اگر قبل از درخواست ارتفاع جعبه، استایل آن را تغییر داده باشید، همه چیز مشکل ساز می شود:
function logBoxHeight () {
box.classList.add('super-big');
// Gets the height of the box in pixels and logs it out:
console.log(box.offsetHeight);
}
حال برای پاسخ به سوال ارتفاع ابتدا مرورگر باید تغییر استایل را اعمال کند (به دلیل اضافه شدن کلاس super-big
) و سپس layout را اجرا کند. تنها در این صورت است که می تواند ارتفاع صحیح را برگرداند. این کار غیر ضروری و بالقوه گران است.
به همین دلیل، همیشه باید استایلهای خود را دستهبندی کنید و ابتدا آنها را انجام دهید (جایی که مرورگر میتواند از مقادیر طرحبندی قاب قبلی استفاده کند) و سپس هر نوع نوشتنی را انجام دهید:
عملکرد فوق به درستی انجام شود:
function logBoxHeight () {
// Gets the height of the box in pixels and logs it out:
console.log(box.offsetHeight);
box.classList.add('super-big');
}
در بیشتر موارد، نیازی به اعمال استایل ها و سپس پرس و جو کردن مقادیر نیست. استفاده از مقادیر آخرین فریم باید کافی باشد. اجرای محاسبات سبک و طرحبندی بهصورت همزمان و زودتر از آنچه مرورگر میخواهد، تنگناهای بالقوه است و چیزی نیست که معمولاً بخواهید انجام دهید.
از کوبیدن طرح بندی خودداری کنید
راهی برای بدتر کردن طرحبندیهای همزمان اجباری وجود دارد: بسیاری از آنها را پشت سر هم انجام دهید . به این کد نگاهی بیندازید:
function resizeAllParagraphsToMatchBlockWidth () {
// Puts the browser into a read-write-read-write cycle.
for (let i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = `${box.offsetWidth}px`;
}
}
این کد روی گروهی از پاراگراف ها حلقه می زند و عرض هر پاراگراف را متناسب با عرض عنصری به نام "جعبه" تنظیم می کند. به اندازه کافی بی ضرر به نظر می رسد، اما مشکل اینجاست که هر تکرار حلقه یک مقدار سبک را می خواند ( box.offsetWidth
) و سپس بلافاصله از آن برای به روز رسانی عرض یک پاراگراف استفاده می کند ( paragraphs[i].style.width
). در تکرار بعدی حلقه، مرورگر باید این واقعیت را در نظر بگیرد که سبکها از آخرین درخواست offsetWidth
(در تکرار قبلی) تغییر کردهاند، بنابراین باید تغییرات سبک را اعمال کند و طرحبندی را اجرا کند. این در هر تکرار اتفاق می افتد! .
راه حل برای این نمونه این است که یک بار دیگر مقادیر را بخوانید و سپس بنویسید :
// Read.
const width = box.offsetWidth;
function resizeAllParagraphsToMatchBlockWidth () {
for (let i = 0; i < paragraphs.length; i++) {
// Now write.
paragraphs[i].style.width = `${width}px`;
}
}
اگر میخواهید ایمنی را تضمین کنید، از FastDOM استفاده کنید، که بهطور خودکار خواندن و نوشتن شما را دستهبندی میکند و از ایجاد طرحبندیهای همزمان اجباری یا بههم ریختن طرحبندی بهطور تصادفی جلوگیری میکند.