ดูวิธีระบุและแก้ไขการเปลี่ยนเลย์เอาต์
ส่วนแรกของบทความนี้กล่าวถึงเครื่องมือสำหรับการแก้ไขข้อบกพร่องของการเปลี่ยนเลย์เอาต์ ส่วนส่วนที่ 2 จะกล่าวถึงกระบวนการคิดที่จะใช้เมื่อระบุสาเหตุของการเปลี่ยนเลย์เอาต์
เครื่องมือ
API ความไม่เสถียรของเลย์เอาต์
Layout Instability API เป็นกลไกของเบราว์เซอร์สำหรับวัดและรายงานการเปลี่ยนแปลงของเลย์เอาต์ เครื่องมือทั้งหมดสำหรับการแก้ไขข้อบกพร่องของการเปลี่ยนแปลงเลย์เอาต์ รวมถึงเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ (DevTools) สร้างขึ้นจาก Layout Instability API อย่างไรก็ตาม การใช้ Layout Instability API โดยตรงเป็นเครื่องมือแก้ไขข้อบกพร่องที่มีประสิทธิภาพสูงเนื่องจากมีความยืดหยุ่น
การใช้งาน
ข้อมูลโค้ดเดียวกันที่วัด Cumulative Layout Shift (CLS) จะแสดงเพื่อแก้ไขข้อบกพร่องของการเปลี่ยนแปลงเลย์เอาต์ได้ด้วย ข้อมูลโค้ดด้านล่างจะบันทึกข้อมูลเกี่ยวกับการเปลี่ยนแปลงเลย์เอาต์ลงในคอนโซล การตรวจสอบบันทึกนี้จะให้ข้อมูลเกี่ยวกับ เวลา ตำแหน่ง และลักษณะการเปลี่ยนเลย์เอาต์
let cls = 0;
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
console.log('Current CLS value:', cls, entry);
}
}
}).observe({type: 'layout-shift', buffered: true});
โปรดทราบว่าเมื่อเรียกใช้สคริปต์นี้
- ตัวเลือก
buffered: true
ระบุว่าPerformanceObserver
ควรตรวจสอบบัฟเฟอร์รายการประสิทธิภาพของเบราว์เซอร์สำหรับรายการประสิทธิภาพที่สร้างขึ้นก่อนผู้สังเกตการณ์ ด้วยเหตุนี้PerformanceObserver
จะรายงานการเปลี่ยนแปลงเลย์เอาต์ที่เกิดขึ้นทั้งก่อนและหลังการเริ่มต้น โปรดคำนึงถึงเรื่องนี้เมื่อตรวจสอบบันทึกคอนโซล การเปลี่ยนแปลงเลย์เอาต์จำนวนมากในช่วงแรกอาจแสดงถึงงานรายงานที่รอดำเนินการ ไม่ใช่การเปลี่ยนแปลงเลย์เอาต์จำนวนมากที่เกิดขึ้นอย่างฉับพลัน PerformanceObserver
จะรอจนกว่าเธรดหลักจะว่างเพื่อรายงานการเปลี่ยนแปลงเลย์เอาต์เพื่อไม่ให้ส่งผลกระทบต่อประสิทธิภาพ ด้วยเหตุนี้ จึงอาจเกิดความล่าช้าเล็กน้อยระหว่างเวลาที่เลย์เอาต์เปลี่ยนไปและเวลาที่บันทึกในคอนโซล ทั้งนี้ขึ้นอยู่กับความยุ่งเหยิงของเธรดหลัก- สคริปต์นี้จะละเว้นการเปลี่ยนแปลงเลย์เอาต์ที่เกิดขึ้นภายใน 500 มิลลิวินาทีหลังจากผู้ใช้ป้อนข้อมูล และจะไม่นับรวมใน CLS
ระบบจะรายงานข้อมูลเกี่ยวกับการเปลี่ยนแปลงเลย์เอาต์โดยใช้ API 2 รายการร่วมกัน ได้แก่ อินเทอร์เฟซ LayoutShift
และ LayoutShiftAttribution
อินเทอร์เฟซแต่ละรายการเหล่านี้จะอธิบายอย่างละเอียดในส่วนต่อไป
LayoutShift
ระบบจะรายงานการเปลี่ยนเลย์เอาต์แต่ละครั้งโดยใช้อินเทอร์เฟซ LayoutShift
เนื้อหาของรายการจะ
มีลักษณะดังต่อไปนี้
duration: 0
entryType: "layout-shift"
hadRecentInput: false
lastInputTime: 0
name: ""
sources: (3) [LayoutShiftAttribution, LayoutShiftAttribution, LayoutShiftAttribution]
startTime: 11317.934999999125
value: 0.17508567530168798
รายการด้านบนระบุการเปลี่ยนเลย์เอาต์ระหว่างที่องค์ประกอบ DOM 3 รายการเปลี่ยนตำแหน่ง คะแนนการเปลี่ยนเลย์เอาต์ของการเปลี่ยนเลย์เอาต์นี้เท่ากับ 0.175
ต่อไปนี้คือพร็อพเพอร์ตี้ของอินสแตนซ์ LayoutShift
ที่เกี่ยวข้องมากที่สุดกับการแก้ไขข้อบกพร่องของการเปลี่ยนเลย์เอาต์
พร็อพเพอร์ตี้ | คำอธิบาย |
---|---|
sources |
พร็อพเพอร์ตี้ sources จะแสดงรายการองค์ประกอบ DOM ที่ย้ายไปในระหว่างการเปลี่ยนเลย์เอาต์ อาร์เรย์นี้มีแหล่งที่มาได้สูงสุด 5 รายการ ในกรณีที่มีองค์ประกอบมากกว่า 5 รายการที่ได้รับผลกระทบจากการเปลี่ยนเลย์เอาต์ ระบบจะรายงานแหล่งที่มาของการเปลี่ยนเลย์เอาต์ 5 รายการที่มีขนาดใหญ่ที่สุด (วัดจากผลกระทบต่อความเสถียรของเลย์เอาต์) ข้อมูลนี้ถูกรายงานโดยใช้อินเทอร์เฟซ LayoutShiftAttribution (รายละเอียดเพิ่มเติมด้านล่าง) |
value |
พร็อพเพอร์ตี้ value จะรายงานคะแนนการเปลี่ยนแปลงเลย์เอาต์สำหรับการเปลี่ยนเลย์เอาต์ที่เฉพาะเจาะจง |
hadRecentInput |
พร็อพเพอร์ตี้ hadRecentInput จะระบุว่ามีการเปลี่ยนแปลงเลย์เอาต์ภายใน 500 มิลลิวินาทีหลังจากอินพุตของผู้ใช้หรือไม่ |
startTime |
พร็อพเพอร์ตี้ startTime ระบุเวลาที่เลย์เอาต์เปลี่ยน startTime จะระบุเป็นมิลลิวินาทีและวัดที่เกี่ยวข้องกับเวลาที่เริ่มโหลดหน้าเว็บ |
duration |
พร็อพเพอร์ตี้ duration จะตั้งค่าเป็น 0 เสมอ พร็อพเพอร์ตี้นี้รับช่วงมาจากอินเทอร์เฟซ PerformanceEntry (อินเทอร์เฟซ LayoutShift ขยายอินเทอร์เฟซ PerformanceEntry ) แต่แนวคิดของระยะเวลาไม่มีผลกับเหตุการณ์ที่มีการเปลี่ยนเลย์เอาต์ ระบบจึงตั้งค่าเป็น 0 ดูข้อมูลเกี่ยวกับอินเทอร์เฟซของ PerformanceEntry ได้ที่ข้อกำหนด |
LayoutShiftAttribution
อินเทอร์เฟซ LayoutShiftAttribution
อธิบายการเปลี่ยนตำแหน่งขององค์ประกอบ DOM รายการเดียว หากองค์ประกอบหลายรายการมีการเปลี่ยนแปลงระหว่างการเปลี่ยนเลย์เอาต์ พร็อพเพอร์ตี้ sources
จะมีหลายรายการ
เช่น JSON ด้านล่างสอดคล้องกับการเปลี่ยนเลย์เอาต์ที่มีแหล่งที่มาเดียว นั่นคือ การเปลี่ยนแปลงลงขององค์ประกอบ DOM <div id='banner'>
จาก y: 76
เป็น y:246
// ...
"sources": [
{
"node": "div#banner",
"previousRect": {
"x": 311,
"y": 76,
"width": 4,
"height": 18,
"top": 76,
"right": 315,
"bottom": 94,
"left": 311
},
"currentRect": {
"x": 311,
"y": 246,
"width": 4,
"height": 18,
"top": 246,
"right": 315,
"bottom": 264,
"left": 311
}
}
]
พร็อพเพอร์ตี้ node
จะระบุองค์ประกอบ HTML ที่เลื่อน การวางเมาส์เหนือพร็อพเพอร์ตี้นี้ในเครื่องมือสำหรับนักพัฒนาเว็บจะไฮไลต์องค์ประกอบของหน้าที่เกี่ยวข้อง
พร็อพเพอร์ตี้ previousRect
และ currentRect
จะรายงานขนาดและตำแหน่งของโหนด
- พิกัด
x
และy
จะรายงานพิกัด x และพิกัด y ตามมุมบนซ้ายขององค์ประกอบ - พร็อพเพอร์ตี้
width
และheight
จะรายงานความกว้างและความสูงขององค์ประกอบตามลำดับ - พร็อพเพอร์ตี้
top
,right
,bottom
และleft
จะรายงานค่าพิกัด x หรือ y ที่สอดคล้องกับขอบขององค์ประกอบที่ระบุ กล่าวคือ ค่าของtop
เท่ากับy
และค่าbottom
เท่ากับy+height
หากพร็อพเพอร์ตี้ทั้งหมดของ previousRect
ตั้งค่าเป็น 0 หมายความว่าองค์ประกอบได้เลื่อนเข้ามาในมุมมองแล้ว หากตั้งค่าพร็อพเพอร์ตี้ทั้งหมดของ currentRect
เป็น 0 หมายความว่าองค์ประกอบได้เลื่อนออกไปนอกมุมมองแล้ว
สิ่งสําคัญที่สุดอย่างหนึ่งที่ควรทราบเมื่อตีความเอาต์พุตเหล่านี้คือองค์ประกอบที่แสดงเป็นแหล่งที่มาคือองค์ประกอบที่เปลี่ยนไปในระหว่างการเปลี่ยนแปลงเลย์เอาต์ แต่ก็เป็นไปได้ว่าองค์ประกอบเหล่านี้อาจเกี่ยวข้องโดยอ้อมกับ "สาเหตุที่แท้จริง" ของความไม่เสถียรของเลย์เอาต์เท่านั้น ลองดูตัวอย่างต่อไปนี้
ตัวอย่าง #1
ระบบจะรายงานการเปลี่ยนแปลงเลย์เอาต์นี้ด้วยแหล่งที่มา 1 แหล่ง ได้แก่ องค์ประกอบ ข. อย่างไรก็ตาม สาเหตุของการเปลี่ยนแปลงเลย์เอาต์นี้คือการเปลี่ยนแปลงขนาดขององค์ประกอบ ก.
ตัวอย่าง #2
การเปลี่ยนเลย์เอาต์ในตัวอย่างนี้จะรายงานด้วยแหล่งที่มา 2 แหล่ง ได้แก่ องค์ประกอบ ก และองค์ประกอบ ข สาเหตุของการเปลี่ยนเลย์เอาต์นี้คือการเปลี่ยนแปลงตําแหน่งขององค์ประกอบ ก.
ตัวอย่าง #3
การเปลี่ยนเลย์เอาต์ในตัวอย่างนี้จะได้รับการรายงานด้วยแหล่งที่มาเดียวคือองค์ประกอบ B การเปลี่ยนตําแหน่งขององค์ประกอบ ข. ทําให้เลย์เอาต์นี้เปลี่ยนไป
ตัวอย่าง #4
แม้ว่าองค์ประกอบ B จะเปลี่ยนขนาด แต่ตัวอย่างนี้ไม่มีการเปลี่ยนเลย์เอาต์
ดูการสาธิตวิธีที่ Layout Instability API รายงานการเปลี่ยนแปลง DOM
เครื่องมือสำหรับนักพัฒนาเว็บ
แผงประสิทธิภาพ
แผงประสบการณ์ของแผงประสิทธิภาพของเครื่องมือสำหรับนักพัฒนาเว็บจะแสดงการเปลี่ยนเลย์เอาต์ทั้งหมดที่เกิดขึ้นระหว่างการติดตามประสิทธิภาพที่ระบุ แม้ว่าจะเกิดขึ้นภายใน 500 มิลลิวินาทีของการโต้ตอบของผู้ใช้ ดังนั้นจะไม่มีการนับรวมใน CLS การวางเมาส์เหนือการเปลี่ยนเลย์เอาต์ที่เฉพาะเจาะจงในแผงประสบการณ์การใช้งานจะไฮไลต์องค์ประกอบ DOM ที่ได้รับผลกระทบ
หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับการเปลี่ยนเลย์เอาต์ ให้คลิกการเปลี่ยนเลย์เอาต์ แล้วเปิดลิ้นชักสรุป การเปลี่ยนแปลงขนาดขององค์ประกอบจะแสดงโดยใช้รูปแบบ [width, height]
ส่วนการเปลี่ยนแปลงตำแหน่งขององค์ประกอบจะแสดงโดยใช้รูปแบบ [x,y]
พร็อพเพอร์ตี้อินพุตล่าสุดจะระบุว่าการเปลี่ยนเลย์เอาต์เกิดขึ้นภายใน 500 มิลลิวินาทีหลังการโต้ตอบของผู้ใช้หรือไม่
ดูข้อมูลเกี่ยวกับระยะเวลาของการเปลี่ยนเลย์เอาต์ได้ในแท็บบันทึกเหตุการณ์ คุณยังประมาณระยะเวลาของการเปลี่ยนเลย์เอาต์ได้โดยดูที่แผงประสบการณ์การใช้งานเพื่อหาความยาวของสี่เหลี่ยมผืนผ้าสีแดงที่แสดงการเปลี่ยนเลย์เอาต์
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้แผงประสิทธิภาพได้ที่ข้อมูลอ้างอิงการวิเคราะห์ประสิทธิภาพ
ไฮไลต์บริเวณที่มีการเปลี่ยนเลย์เอาต์
การไฮไลต์บริเวณที่มีการเปลี่ยนเลย์เอาต์เป็นเทคนิคที่มีประโยชน์ในการดูตำแหน่งและเวลาของการเปลี่ยนเลย์เอาต์ที่เกิดขึ้นในหน้าเว็บได้อย่างรวดเร็ว
หากต้องการเปิดใช้ภูมิภาคของการเปลี่ยนเลย์เอาต์ในเครื่องมือสำหรับนักพัฒนาเว็บ ให้ไปที่การตั้งค่า > เครื่องมือเพิ่มเติม > การแสดงผล > บริเวณการเปลี่ยนเลย์เอาต์ แล้วรีเฟรชหน้าเว็บที่คุณต้องการแก้ไขข้อบกพร่อง พื้นที่ของการเปลี่ยนเลย์เอาต์จะไฮไลต์เป็นสีม่วงเป็นเวลาสั้นๆ
กระบวนการคิดในการระบุสาเหตุของการเปลี่ยนเลย์เอาต์
คุณสามารถใช้ขั้นตอนด้านล่างเพื่อระบุสาเหตุของการเปลี่ยนแปลงเลย์เอาต์ไม่ว่าจะเกิดขึ้นเมื่อใดหรืออย่างไรก็ตาม ขั้นตอนเหล่านี้สามารถเสริมได้ด้วยการเรียกใช้ Lighthouse อย่างไรก็ตาม โปรดทราบว่า Lighthouse สามารถระบุการเปลี่ยนแปลงของเลย์เอาต์ที่เกิดขึ้นระหว่างการโหลดหน้าเว็บเริ่มต้นได้เท่านั้น นอกจากนี้ Lighthouse ยังให้คำแนะนำสำหรับบางสาเหตุของการเปลี่ยนเลย์เอาต์เท่านั้น เช่น องค์ประกอบรูปภาพที่ไม่มีความกว้างและความสูงที่ชัดเจน
การระบุสาเหตุของการเปลี่ยนเลย์เอาต์
การเปลี่ยนเลย์เอาต์อาจเกิดจากเหตุการณ์ต่อไปนี้
- การเปลี่ยนแปลงตำแหน่งขององค์ประกอบ DOM
- การเปลี่ยนแปลงมิติข้อมูลขององค์ประกอบ DOM
- การแทรกหรือการนำองค์ประกอบ DOM ออก
- ภาพเคลื่อนไหวที่ทริกเกอร์เลย์เอาต์
โดยเฉพาะอย่างยิ่ง องค์ประกอบ DOM ที่อยู่ก่อนหน้าองค์ประกอบที่เลื่อนไปทันทีเป็นองค์ประกอบที่มีแนวโน้มมากที่สุดที่จะ "ทําให้" เลย์เอาต์เปลี่ยน ดังนั้น เมื่อคุณตรวจสอบสาเหตุที่มีการเปลี่ยนเลย์เอาต์ ให้พิจารณาดังนี้
- ตำแหน่งหรือมิติข้อมูลขององค์ประกอบก่อนหน้ามีการเปลี่ยนแปลงไหม
- องค์ประกอบ DOM ถูกแทรกหรือนำออกก่อนองค์ประกอบที่ขยับหรือไม่
- ตำแหน่งขององค์ประกอบที่เลื่อนมีการเปลี่ยนแปลงอย่างชัดเจนหรือไม่
หากองค์ประกอบก่อนหน้าไม่ทำให้เกิดการเปลี่ยนเลย์เอาต์ ให้ค้นหาต่อไปโดยพิจารณาองค์ประกอบก่อนหน้าและใกล้เคียงอื่นๆ
นอกจากนี้ ทิศทางและระยะห่างของการเปลี่ยนเลย์เอาต์ยังให้คำแนะนำเกี่ยวกับต้นเหตุของปัญหาได้ด้วย ตัวอย่างเช่น การเปลี่ยนแปลงที่ลดลงอย่างมากมักบ่งบอกถึงการแทรกองค์ประกอบ DOM ส่วนการเปลี่ยนแปลงเลย์เอาต์ 1 พิกเซลหรือ 2 พิกเซลมักบ่งบอกถึงการใช้สไตล์ CSS ที่ขัดแย้งกัน หรือการโหลดและการใช้เว็บฟอนต์
ต่อไปนี้คือลักษณะการทำงานบางอย่างที่ทําให้เกิดเหตุการณ์การเปลี่ยนแปลงเลย์เอาต์บ่อยที่สุด
การเปลี่ยนแปลงตําแหน่งขององค์ประกอบ (ที่ไม่ได้เกิดจากการเคลื่อนที่ขององค์ประกอบอื่น)
การเปลี่ยนแปลงประเภทนี้มักเกิดจากสาเหตุต่อไปนี้
- สไตล์ชีตที่โหลดช้าหรือเขียนทับสไตล์ที่ประกาศไว้ก่อนหน้านี้
- เอฟเฟกต์ภาพเคลื่อนไหวและการเปลี่ยน
การเปลี่ยนแปลงขนาดขององค์ประกอบ
การเปลี่ยนแปลงประเภทนี้มักเกิดจากสิ่งต่อไปนี้
- สไตล์ชีตที่โหลดช้าหรือเขียนทับสไตล์ที่ประกาศไว้ก่อนหน้านี้
- รูปภาพและ iframe ที่ไม่มีแอตทริบิวต์
width
และheight
ที่โหลดหลังจากแสดงผล "ช่อง" แล้ว - บล็อกข้อความที่ไม่มีแอตทริบิวต์
width
หรือheight
ซึ่งสลับแบบอักษรหลังจากแสดงผลข้อความแล้ว
การแทรกหรือการนำองค์ประกอบ DOM ออก
ซึ่งมักจะเป็นผลมาจากสิ่งต่อไปนี้
- แทรกโฆษณาและการฝังอื่นๆ ของบุคคลที่สาม
- การแทรกแบนเนอร์ การแจ้งเตือน และโมดัล
- การเลื่อนได้ไม่รู้จบและรูปแบบ UX อื่นๆ ที่โหลดเนื้อหาเพิ่มเติมเหนือเนื้อหาที่มีอยู่
ภาพเคลื่อนไหวที่ทริกเกอร์เลย์เอาต์
เอฟเฟกต์ภาพเคลื่อนไหวบางอย่างอาจทริกเกอร์เลย์เอาต์ ตัวอย่างที่พบบ่อยของกรณีนี้คือเมื่อองค์ประกอบ DOM "เคลื่อนไหว" โดยการเพิ่มขึ้นของพร็อพเพอร์ตี้ เช่น top
หรือ left
แทนที่จะใช้พร็อพเพอร์ตี้ transform
ของ CSS อ่านข้อมูลเพิ่มเติมที่วิธีสร้างภาพเคลื่อนไหว CSS ที่มีประสิทธิภาพสูง
การทำซ้ำการเปลี่ยนแปลงเลย์เอาต์
คุณจะแก้ไขการเปลี่ยนแปลงเลย์เอาต์ที่ไม่สามารถจำลองไม่ได้ วิธีที่ง่ายที่สุดแต่ได้ผลดีที่สุดอย่างหนึ่งที่คุณทําได้เพื่อทําความเข้าใจความเสถียรของเลย์เอาต์เว็บไซต์ได้ดียิ่งขึ้นคือใช้เวลา 5-10 นาทีในการโต้ตอบกับเว็บไซต์โดยมีเป้าหมายเพื่อทริกเกอร์การเปลี่ยนแปลงเลย์เอาต์ เปิดคอนโซลไว้ขณะดำเนินการนี้ และใช้ Layout Instability API เพื่อรายงานเกี่ยวกับการเปลี่ยนแปลงของเลย์เอาต์
หากพบการเปลี่ยนแปลงเลย์เอาต์ที่หายาก ให้ลองทำแบบฝึกหัดนี้ซ้ำโดยใช้อุปกรณ์และความเร็วการเชื่อมต่อที่ต่างกัน โดยเฉพาะอย่างยิ่ง การใช้ความเร็วในการเชื่อมต่อที่ช้าลงจะช่วยให้ระบุการเปลี่ยนเลย์เอาต์ได้ง่ายขึ้น นอกจากนี้ คุณยังใช้คำสั่ง debugger
เพื่อให้ทำการเปลี่ยนแปลงเลย์เอาต์ทีละขั้นได้ง่ายขึ้นได้ด้วย
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
if (!entry.hadRecentInput) {
cls += entry.value;
debugger;
console.log('Current CLS value:', cls, entry);
}
}
}).observe({type: 'layout-shift', buffered: true});
สุดท้าย สำหรับปัญหาเลย์เอาต์ที่ไม่สามารถจำลองได้ในขั้นตอนการพัฒนา ให้ลองใช้ Layout Instability API ร่วมกับเครื่องมือการบันทึกข้อมูลส่วนหน้าเพื่อรวบรวมข้อมูลเพิ่มเติมเกี่ยวกับปัญหาเหล่านี้ ดูตัวอย่างโค้ดสำหรับวิธีติดตามองค์ประกอบที่ขยับมากที่สุดในหน้า