การเปลี่ยนเลย์เอาต์ที่ไม่คาดคิดอาจรบกวนประสบการณ์การใช้งานของผู้ใช้ได้หลายวิธี ตั้งแต่ทำให้ผู้ใช้เสียตำแหน่งขณะอ่านหากข้อความเลื่อนไปอย่างกะทันหัน ไปจนถึงทำให้ผู้ใช้คลิกลิงก์หรือปุ่มที่ไม่ถูกต้อง ซึ่งในบางกรณีอาจทำให้เกิดความเสียหายร้ายแรง
การเคลื่อนไหวของเนื้อหาหน้าเว็บที่ไม่คาดคิดมักเกิดขึ้นเมื่อทรัพยากรโหลดแบบไม่พร้อมกันหรือมีการเพิ่มองค์ประกอบ DOM ลงในหน้าเว็บแบบไดนามิกก่อนเนื้อหาที่มีอยู่ สาเหตุของการเปลี่ยนเลย์เอาต์อาจเป็นรูปภาพหรือวิดีโอที่ไม่ทราบขนาด แบบอักษรที่แสดงผลขนาดใหญ่หรือเล็กกว่าวิดีโอสำรองเริ่มต้น หรือโฆษณาหรือวิดเจ็ตของบุคคลที่สามที่ปรับขนาดแบบไดนามิก
ความแตกต่างระหว่างการทำงานของเว็บไซต์ในการพัฒนากับประสบการณ์ของผู้ใช้ทำให้ปัญหานี้แย่ลง เช่น
- เนื้อหาที่ปรับเปลี่ยนในแบบของคุณหรือเนื้อหาของบุคคลที่สามมักจะทำงานแตกต่างกันระหว่างการพัฒนาและเวอร์ชันที่ใช้งานจริง
- รูปภาพทดสอบมักจะอยู่ในแคชเบราว์เซอร์ของนักพัฒนาแอปอยู่แล้ว แต่ผู้ใช้ปลายทางจะใช้เวลาโหลดนานกว่า
- การเรียก API ที่ทำงานภายในมักจะรวดเร็วมากจนทำให้ความล่าช้าของการพัฒนาไม่สามารถสังเกตเห็นได้กลายเป็นส่วนสำคัญในการใช้งานจริง
เมตริก Cumulative Layout Shift (CLS) ช่วยคุณแก้ปัญหานี้โดยวัดความถี่ที่ปัญหาเกิดขึ้นสำหรับผู้ใช้จริง
CLS คืออะไร
CLS คือการวัดคะแนนการเปลี่ยนเลย์เอาต์ที่พุ่งขึ้นสูงสุดสําหรับการเปลี่ยนเลย์เอาต์ที่ไม่คาดคิดทุกครั้งซึ่งเกิดขึ้นตลอดอายุการใช้งานของหน้าเว็บ
การเปลี่ยนเลย์เอาต์จะเกิดขึ้นทุกครั้งที่องค์ประกอบที่มองเห็นได้เปลี่ยนตำแหน่งจากเฟรมที่แสดงผลเฟรมหนึ่งไปยังอีกเฟรมหนึ่ง (โปรดดูรายละเอียดเกี่ยวกับวิธีคํานวณคะแนนการเปลี่ยนเลย์เอาต์แต่ละรายการในบทถัดไปของคู่มือนี้)
การเปลี่ยนแปลงของเลย์เอาต์หรือที่เรียกว่ากรอบเวลาเซสชัน คือการเปลี่ยนแปลงเลย์เอาต์แบบต่อเนื่องอย่างน้อย 1 รายการแบบต่อเนื่องกันอย่างรวดเร็ว โดยมีเวลาไม่ถึง 1 วินาทีระหว่างแต่ละกะและไม่เกิน 5 วินาทีสำหรับระยะเวลาของกรอบเวลาทั้งหมด
ช่วงที่มีการเพิ่มขึ้นสูงสุดคือกรอบเวลาเซสชันที่มีคะแนนสะสมสูงสุดของการเปลี่ยนเลย์เอาต์ทั้งหมดภายในกรอบเวลานั้น
คะแนน CLS ที่ดีคือเท่าใด
เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดี เว็บไซต์ต้องพยายามให้มีคะแนน CLS ไม่เกิน 0.1 เกณฑ์การวัดที่ดีเพื่อให้มั่นใจว่าคุณบรรลุเป้าหมายนี้สําหรับผู้ใช้ส่วนใหญ่คือเปอร์เซ็นต์ไทล์ที่ 75 ของการโหลดหน้าเว็บ ซึ่งแบ่งกลุ่มตามอุปกรณ์เคลื่อนที่และเดสก์ท็อป
ดูข้อมูลเพิ่มเติมเกี่ยวกับการวิจัยและวิธีการที่แนะนํานี้ได้ที่การกำหนดเกณฑ์เมตริก Core Web Vitals
รายละเอียดการเปลี่ยนแปลงเลย์เอาต์
การเปลี่ยนแปลงของเลย์เอาต์จะกำหนดโดย Layout Instability API ซึ่งจะรายงานรายการ layout-shift
รายการทุกครั้งที่องค์ประกอบที่มองเห็นได้ภายในวิวพอร์ตเปลี่ยนตำแหน่งเริ่มต้น (เช่น ตำแหน่งด้านบนและซ้ายในโหมดการเขียนเริ่มต้น) ระหว่าง 2 เฟรม องค์ประกอบดังกล่าวถือเป็นองค์ประกอบที่ไม่เสถียร
โปรดทราบว่าการเปลี่ยนแปลงเลย์เอาต์จะเกิดขึ้นเฉพาะเมื่อองค์ประกอบที่มีอยู่เปลี่ยนตำแหน่งเริ่มต้นเท่านั้น หากมีการเพิ่มองค์ประกอบใหม่ลงใน DOM หรือองค์ประกอบที่มีอยู่เปลี่ยนขนาด ระบบจะไม่นับการเปลี่ยนแปลงดังกล่าวเป็นการเปลี่ยนเลย์เอาต์ ตราบใดที่การเปลี่ยนแปลงไม่ทําให้องค์ประกอบอื่นๆ ที่มองเห็นได้เปลี่ยนตําแหน่งเริ่มต้น
คะแนนการเปลี่ยนเลย์เอาต์
ในการคํานวณคะแนนการเปลี่ยนเลย์เอาต์เบราว์เซอร์จะพิจารณาขนาดวิวพอร์ตและการเคลื่อนไหวขององค์ประกอบที่ไม่เสถียรในวิวพอร์ตระหว่างเฟรมที่แสดงผล 2 เฟรม คะแนนการเปลี่ยนแปลงเลย์เอาต์คือผลคูณของค่าการวัดการเคลื่อนไหว 2 ค่า ได้แก่ เศษส่วนของผลลัพธ์และเศษส่วนของระยะทาง (ทั้ง 2 ค่ามีคำจำกัดความอยู่ด้านล่าง)
layout shift score = impact fraction * distance fraction
สัดส่วนผลกระทบ
เศษส่วนผลกระทบจะวัดว่าองค์ประกอบที่ไม่เสถียรส่งผลต่อพื้นที่วิวพอร์ตระหว่าง 2 เฟรมอย่างไร
เศษส่วนผลกระทบสำหรับเฟรมหนึ่งๆ เป็นการรวมพื้นที่ที่มองเห็นได้ขององค์ประกอบที่ไม่เสถียรทั้งหมดของเฟรมนั้นและเฟรมก่อนหน้า เข้าด้วยกันเป็นเศษส่วนของพื้นที่รวมของวิวพอร์ต
ในรูปภาพก่อนหน้า มีองค์ประกอบที่ใช้พื้นที่ครึ่งหนึ่งของวิวพอร์ตใน 1 เฟรม จากนั้นในเฟรมถัดไป องค์ประกอบจะเลื่อนลงไป 25% ของความสูงของวิวพอร์ต สี่เหลี่ยมผืนผ้าสีแดงจุดๆ แสดงการรวมพื้นที่ที่มองเห็นได้ขององค์ประกอบในทั้ง 2 เฟรม ซึ่งในกรณีนี้คิดเป็น 75% ของวิวพอร์ตทั้งหมด ดังนั้นเศษส่วนของผลลัพธ์คือ 0.75
เศษส่วนระยะทาง
ส่วนอื่นๆ ของสมการคะแนนการเปลี่ยนเลย์เอาต์จะวัดระยะทางที่องค์ประกอบที่ไม่เสถียรเคลื่อนไหวเมื่อเทียบกับวิวพอร์ต เศษส่วนของระยะทางคือระยะทางแนวนอนหรือแนวตั้งสูงสุดที่องค์ประกอบที่ไม่เสถียรได้เคลื่อนที่ในเฟรมหารด้วยมิติข้อมูลของวิวพอร์ตที่ใหญ่ที่สุด (ความกว้างหรือความสูง แล้วแต่ว่าค่าใดจะมากกว่า)
ในตัวอย่างนี้ มิติข้อมูลวิวพอร์ตที่ใหญ่ที่สุดคือความสูง และองค์ประกอบที่ไม่เสถียรได้เลื่อนไป 25% ของความสูงของวิวพอร์ต ซึ่งทําให้เศษส่วนของระยะทางเท่ากับ 0.25
ในตัวอย่างนี้ เศษส่วนของผลลัพธ์คือ 0.75
และเศษส่วนของระยะทางคือ 0.25
ดังนั้นคะแนนการเปลี่ยนแปลงเลย์เอาต์คือ 0.75 * 0.25 = 0.1875
ตัวอย่าง
ตัวอย่างต่อไปนี้จะแสดงให้เห็นว่าการเพิ่มเนื้อหาลงในองค์ประกอบที่มีอยู่ส่งผลต่อคะแนนการเปลี่ยนเลย์เอาต์อย่างไร
ในตัวอย่างนี้ กล่องสีเทาจะเปลี่ยนขนาด แต่ตำแหน่งเริ่มต้นไม่เปลี่ยนแปลง จึงไม่ใช่องค์ประกอบที่ไม่เสถียร
ก่อนหน้านี้ปุ่ม "คลิกฉัน!" ไม่เคยมีอยู่ใน DOM ดังนั้น ตำแหน่งเริ่มต้นของปุ่มจึงจะไม่เปลี่ยนแปลง
อย่างไรก็ตาม ตำแหน่งเริ่มต้นของกล่องสีเขียวจะเปลี่ยนแปลง แต่เนื่องจากมีการย้ายกล่องบางส่วนออกจากวิวพอร์ต ระบบจะไม่พิจารณาพื้นที่ที่มองไม่เห็นเมื่อคำนวณเศษส่วนของผลลัพธ์ การรวมพื้นที่ที่มองเห็นได้ของกล่องสีเขียวในทั้ง 2 เฟรม (แสดงด้วยสี่เหลี่ยมผืนผ้าสีแดงจุดๆ) เท่ากับพื้นที่ของกล่องสีเขียวในเฟรมแรก ซึ่งเป็น 50% ของวิวพอร์ต เศษส่วนของผลลัพธ์คือ 0.5
เศษส่วนของระยะทางแสดงด้วยลูกศรสีม่วง กล่องสีเขียวเลื่อนลงประมาณ 14% ของวิวพอร์ต ดังนั้นเศษส่วนของระยะทางคือ 0.14
คะแนนการเปลี่ยนเลย์เอาต์คือ 0.5 x 0.14 = 0.07
ตัวอย่างต่อไปนี้แสดงวิธีที่องค์ประกอบที่ไม่เสถียรหลายรายการส่งผลต่อคะแนนการเปลี่ยนแปลงเลย์เอาต์ของหน้า
ในเฟรมแรกในรูปภาพก่อนหน้า มีผลการค้นหา 4 รายการของคำขอ API สำหรับสัตว์ ซึ่งจัดเรียงตามลำดับตัวอักษร ในเฟรมที่ 2 ระบบจะเพิ่มผลการค้นหาเพิ่มเติมลงในรายการที่จัดเรียง
รายการแรกในรายการ ("Cat") จะไม่เปลี่ยนตำแหน่งเริ่มต้นระหว่างเฟรม ดังนั้นจึงคงที่ ในทำนองเดียวกัน รายการใหม่ที่เพิ่มในรายการนั้นไม่ได้อยู่ใน DOM ก่อนหน้านี้ ดังนั้นตำแหน่งเริ่มต้นของรายการเหล่านั้นก็จะไม่เปลี่ยนแปลงเช่นกัน แต่รายการที่มีป้ายกำกับว่า "สุนัข" "ม้า" และ "ม้าลาย" ทั้งหมดเลื่อนตำแหน่งเริ่มต้น ทำให้เป็นองค์ประกอบที่ไม่เสถียร
อีกครั้ง สี่เหลี่ยมผืนผ้าสีแดงจุดๆ แสดงการรวมพื้นที่ก่อนและหลังขององค์ประกอบที่ไม่เสถียร 3 รายการนี้ ซึ่งในกรณีนี้คิดเป็นประมาณ 60% ของพื้นที่ในวิวพอร์ต (เศษส่วนของผลลัพธ์ 0.60
)
ลูกศรแสดงระยะทางที่องค์ประกอบที่ไม่เสถียรเคลื่อนที่จากตำแหน่งเริ่มต้น องค์ประกอบ "Zebra" ที่แสดงด้วยลูกศรสีน้ำเงินมีการย้ายมากที่สุดประมาณ 30% ของความสูงของวิวพอร์ต เศษส่วนของระยะทางในตัวอย่างนี้จึงเท่ากับ 0.3
คะแนนการเปลี่ยนเลย์เอาต์คือ 0.60 x 0.3 = 0.18
การเปลี่ยนแปลงเลย์เอาต์ที่คาดไว้และที่ไม่คาดไว้
การเปลี่ยนเลย์เอาต์ไม่ได้แย่เสมอไป ความจริงแล้ว เว็บแอปพลิเคชันแบบไดนามิกหลายรายการเปลี่ยนแปลงตําแหน่งเริ่มต้นขององค์ประกอบในหน้าเว็บอยู่บ่อยครั้ง การเปลี่ยนเลย์เอาต์จะมีผลเมื่อผู้ใช้ไม่ได้คาดหวังเท่านั้น
การเปลี่ยนแปลงเลย์เอาต์ที่เริ่มต้นโดยผู้ใช้
โดยทั่วไปการเปลี่ยนเลย์เอาต์ที่เกิดขึ้นเพื่อตอบสนองการโต้ตอบของผู้ใช้ (เช่น การคลิกหรือแตะลิงก์ การกดปุ่ม หรือพิมพ์ในช่องค้นหา) เป็นสิ่งที่สามารถทำได้ ตราบใดที่การเปลี่ยนเกิดขึ้นใกล้กับการโต้ตอบที่ผู้ใช้จะเห็นได้อย่างชัดเจน
เช่น หากการโต้ตอบของผู้ใช้ทริกเกอร์คำขอเครือข่ายที่อาจใช้เวลาสักครู่จึงจะเสร็จสมบูรณ์ คุณควรสร้างพื้นที่ว่างทันทีและแสดงตัวบ่งชี้การโหลดเพื่อหลีกเลี่ยงการเปลี่ยนเลย์เอาต์ที่ไม่พึงประสงค์เมื่อคำขอเสร็จสมบูรณ์ หากผู้ใช้ไม่ทราบว่ากำลังโหลดข้อมูลอยู่ หรือไม่รู้ว่าทรัพยากรจะพร้อมเมื่อใด ผู้ใช้อาจพยายามคลิกสิ่งอื่นขณะรอ ซึ่งอาจทำให้สิ่งนั้นหายไป
การเปลี่ยนเลย์เอาต์ที่เกิดขึ้นภายใน 500 มิลลิวินาทีหลังจากอินพุตของผู้ใช้จะมีการตั้งค่า Flag hadRecentInput
เพื่อให้ระบบยกเว้นจากการคำนวณ
ภาพเคลื่อนไหวและการเปลี่ยน
ภาพเคลื่อนไหวและทรานซิชันเป็นวิธีที่ดีในการอัปเดตเนื้อหาในหน้าเว็บโดยไม่ทำให้ผู้ใช้ประหลาดใจ หากทำอย่างถูกต้อง เนื้อหาที่เปลี่ยนไปอย่างกะทันหันและไม่คาดคิดในหน้าเว็บมักจะสร้างประสบการณ์ที่ไม่ดีให้แก่ผู้ใช้ แต่เนื้อหาที่ค่อยๆ เลื่อนจากตำแหน่งหนึ่งไปยังอีกตำแหน่งหนึ่งอย่างเป็นธรรมชาติมักจะช่วยให้ผู้ใช้เข้าใจสิ่งที่เกิดขึ้นได้ดีขึ้นและแนะนำระหว่างการเปลี่ยนแปลงสถานะ
อย่าลืมคำนึงถึงการตั้งค่าเบราว์เซอร์ prefers-reduced-motion
เนื่องจากผู้เข้าชมเว็บไซต์บางรายอาจพบผลเสียหรือปัญหาด้านความสนใจจากภาพเคลื่อนไหว
พร็อพเพอร์ตี้ transform
ของ CSS ช่วยให้คุณทำให้องค์ประกอบเคลื่อนไหวได้โดยไม่ต้องทริกเกอร์การเปลี่ยนเลย์เอาต์
- ให้ใช้
transform: scale()
แทนการเปลี่ยนพร็อพเพอร์ตี้height
และwidth
- หากต้องการย้ายองค์ประกอบ ให้หลีกเลี่ยงการเปลี่ยนพร็อพเพอร์ตี้
top
,right
,bottom
หรือleft
และใช้transform: translate()
แทน
วิธีวัด CLS
CLS สามารถวัดได้ในห้องทดลองหรือในสนาม และเครื่องมือต่อไปนี้มี CLS
เครื่องมือภาคสนาม
- รายงานประสบการณ์ของผู้ใช้ Chrome
- PageSpeed Insights
- Search Console (รายงาน Core Web Vitals)
web-vitals
ไลบรารี JavaScript
เครื่องมือของห้องทดลอง
วัดการเปลี่ยนแปลงเลย์เอาต์ใน JavaScript
หากต้องการวัดการเปลี่ยนแปลงของเลย์เอาต์ใน JavaScript ให้ใช้ Layout Instability API
ตัวอย่างต่อไปนี้แสดงวิธีสร้าง PerformanceObserver
เพื่อบันทึกรายการ layout-shift
ลงในคอนโซล
new PerformanceObserver((entryList) => {
for (const entry of entryList.getEntries()) {
console.log('Layout shift:', entry);
}
}).observe({type: 'layout-shift', buffered: true});
วัด CLS ใน JavaScript
หากต้องการวัด CLS ใน JavaScript คุณต้องจัดกลุ่มรายการ layout-shift
ที่ไม่คาดคิดเหล่านี้เป็นเซสชัน และคำนวณค่าเซสชันสูงสุด คุณสามารถดูweb vitals
ซอร์สโค้ดของไลบรารี JavaScript ซึ่งมีการใช้งานอ้างอิงเกี่ยวกับวิธีคํานวณ CLS
ในกรณีส่วนใหญ่ ค่า CLS ปัจจุบัน ณ เวลาที่มีการยกเลิกการโหลดหน้าเว็บคือค่า CLS สุดท้ายของหน้านั้น แต่มีข้อยกเว้นสำคัญ 2-3 ข้อตามที่ระบุไว้ในส่วนถัดไป ไลบรารี JavaScript ของ web vitals
คำนึงถึงรายการเหล่านี้มากที่สุดเท่าที่เป็นไปได้ภายใต้ข้อจำกัดของ Web API
ความแตกต่างระหว่างเมตริกกับ API
- หากหน้าเว็บโหลดในเบื้องหลังหรืออยู่ในเบื้องหลังก่อนที่เบราว์เซอร์จะแสดงเนื้อหาใดๆ หน้านั้นไม่ควรรายงานค่า CLS
- หากมีการกู้คืนหน้าเว็บจากแคชย้อนกลับ/ไปข้างหน้า ระบบควรรีเซ็ตค่า CLS ของหน้าเว็บเป็น 0 เนื่องจากผู้ใช้จะเห็นว่าหน้าเว็บนี้เป็นการเข้าชมหน้าเว็บที่แตกต่างกัน
- API จะไม่รายงานรายการ
layout-shift
สำหรับการเปลี่ยนแปลงที่เกิดขึ้นภายใน iframe แต่เมตริกจะรายงานเนื่องจากเป็นส่วนหนึ่งของประสบการณ์ของผู้ใช้หน้าเว็บ ซึ่งอาจแสดงเป็นความแตกต่างระหว่าง CrUX กับ RUM คุณควรพิจารณาปัจจัยเหล่านี้เพื่อวัด CLS อย่างเหมาะสม เฟรมย่อยสามารถใช้ API เพื่อรายงานรายการlayout-shift
ไปยังเฟรมหลักเพื่อการรวม
นอกจากข้อยกเว้นเหล่านี้แล้ว CLS ยังมีความซับซ้อนเพิ่มเติมเนื่องจากจะวัดอายุการใช้งานทั้งหมดของหน้าเว็บ
- ผู้ใช้อาจเปิดแท็บไว้นานมาก เช่น วัน สัปดาห์ หรือเดือน ที่จริงแล้ว ผู้ใช้อาจไม่ได้ปิดแท็บเลย
- ในระบบปฏิบัติการของอุปกรณ์เคลื่อนที่ เบราว์เซอร์มักไม่เรียกใช้การเรียกกลับการยกเลิกการโหลดหน้าเว็บสําหรับแท็บที่ทำงานอยู่เบื้องหลัง ซึ่งทําให้รายงานค่า "สุดท้าย" ได้ยาก
หากต้องการจัดการกับกรณีเช่นนี้ คุณควรรายงาน CLS ทุกครั้งที่หน้าเว็บอยู่เบื้องหลัง นอกเหนือจากเวลาที่หน้าเว็บถูกยกเลิกการโหลด (เหตุการณ์ visibilitychange
ครอบคลุมทั้ง 2 สถานการณ์นี้) จากนั้นระบบวิเคราะห์ที่ได้รับข้อมูลนี้จะต้องคํานวณค่า CLS สุดท้ายในแบ็กเอนด์
แทนที่จะจำและจัดการกับกรณีเหล่านี้ทั้งหมดด้วยตัวเอง นักพัฒนาแอปสามารถใช้ไลบรารี JavaScript web-vitals
เพื่อวัด CLS ซึ่งครอบคลุมทุกอย่างที่กล่าวถึงข้างต้น ยกเว้นกรณี iframe
import {onCLS} from 'web-vitals';
// Measure and log CLS in all situations
// where it needs to be reported.
onCLS(console.log);
วิธีปรับปรุง CLS
ดูคําแนะนําเพิ่มเติมเกี่ยวกับการระบุการเปลี่ยนแปลงเลย์เอาต์ในสนามและการใช้ข้อมูลในร้านเพื่อเพิ่มประสิทธิภาพได้ที่คู่มือการเพิ่มประสิทธิภาพ CLS
แหล่งข้อมูลเพิ่มเติม
- คําแนะนําของแท็กผู้เผยแพร่โฆษณาผ่าน Google เกี่ยวกับการลดการเปลี่ยนแปลงของเลย์เอาต์
- การทำความเข้าใจการเปลี่ยนแปลงเลย์เอาต์แบบสะสมโดย Annie Sullivan และ Steve Kobes จาก #PerfMatters (2020)
บันทึกการเปลี่ยนแปลง
บางครั้งเราอาจพบข้อบกพร่องใน API ที่ใช้วัดเมตริก และบางครั้งก็พบในคําจํากัดความของเมตริกเอง ด้วยเหตุนี้ จึงต้องมีการทําการเปลี่ยนแปลงในบางครั้ง และการเปลี่ยนแปลงเหล่านี้อาจปรากฏเป็นการเพิ่มประสิทธิภาพหรือการถดถอยในรายงานและหน้าแดชบอร์ดภายใน
เพื่อช่วยให้คุณจัดการเรื่องนี้ได้ การเปลี่ยนแปลงทั้งหมดในการใช้งานหรือคําจํากัดความของเมตริกเหล่านี้จะแสดงในบันทึกการเปลี่ยนแปลงนี้
หากมีความคิดเห็นเกี่ยวกับเมตริกเหล่านี้ โปรดแสดงความคิดเห็นในกลุ่ม Google สำหรับ Web Vitals Feedback