การเปลี่ยนเลย์เอาต์ที่ไม่คาดคิดอาจรบกวนประสบการณ์ของผู้ใช้ในหลายๆ ด้าน ตั้งแต่การทำให้เสียตำแหน่งขณะอ่านหากข้อความเคลื่อนไหวอย่างกะทันหัน ไปจนถึงคลิกลิงก์หรือปุ่มที่ไม่ถูกต้อง ในบางกรณี อาจทำให้เกิดความเสียหายร้ายแรง
การเคลื่อนไหวของเนื้อหาในหน้าเว็บที่ไม่คาดคิดมักเกิดขึ้นเมื่อทรัพยากรโหลดแบบไม่พร้อมกันหรือมีการเพิ่มองค์ประกอบ 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
)
ลูกศรแสดงระยะทางที่องค์ประกอบที่ไม่เสถียรได้ย้ายจากตำแหน่งเริ่มต้น "ม้าลาย" ซึ่งมีการย้ายตำแหน่งมากที่สุดประมาณ 30% ของความสูงของวิวพอร์ต ซึ่งทำให้เศษส่วนระยะทางในตัวอย่างนี้เป็น 0.3
คะแนนการเปลี่ยนเลย์เอาต์คือ 0.60 x 0.3 = 0.18
การเปลี่ยนเลย์เอาต์ที่ไม่คาดคิดเทียบกับที่ไม่คาดคิด
การเปลี่ยนเลย์เอาต์ไม่ได้แย่เสมอไป ที่จริงแล้ว เว็บแอปพลิเคชันแบบไดนามิกจำนวนมากมักเปลี่ยนตำแหน่งเริ่มต้นขององค์ประกอบต่างๆ บนหน้าเว็บ การเปลี่ยนเลย์เอาต์จะมีผลเมื่อผู้ใช้ไม่ได้คาดหวังเท่านั้น
การเปลี่ยนเลย์เอาต์ที่เริ่มต้นโดยผู้ใช้
โดยทั่วไปการเปลี่ยนเลย์เอาต์ที่เกิดขึ้นเพื่อตอบสนองการโต้ตอบของผู้ใช้ (เช่น การคลิกหรือแตะลิงก์ การกดปุ่ม หรือพิมพ์ในช่องค้นหา) เป็นสิ่งที่สามารถทำได้ ตราบใดที่การเปลี่ยนเกิดขึ้นใกล้กับการโต้ตอบที่ผู้ใช้จะเห็นอย่างชัดเจน
ตัวอย่างเช่น หากการโต้ตอบของผู้ใช้ทริกเกอร์คำขอเครือข่ายซึ่งอาจใช้เวลาสักพักในการดำเนินการ ควรจะสร้างพื้นที่ว่างทันทีและแสดงสัญญาณบอกสถานะการโหลดเพื่อหลีกเลี่ยงการเปลี่ยนเลย์เอาต์ที่ไม่พึงประสงค์เมื่อคำขอเสร็จสมบูรณ์ หากผู้ใช้ไม่ทราบว่ามีบางอย่างกำลังโหลดหรือไม่รู้ว่าทรัพยากรจะพร้อมเมื่อใด ผู้ใช้อาจลองคลิกสิ่งอื่นในขณะที่รอ ซึ่งเป็นสิ่งที่อาจย้ายออกมาจากด้านล่าง
การเปลี่ยนเลย์เอาต์ที่เกิดขึ้นภายใน 500 มิลลิวินาทีอินพุตของผู้ใช้จะตั้งค่าแฟล็ก hadRecentInput
ไว้ ทำให้สามารถยกเว้นจากการคำนวณได้
ภาพเคลื่อนไหวและการเปลี่ยน
เมื่อทำได้ดีแล้ว ภาพเคลื่อนไหวและการเปลี่ยนภาพก็เป็นวิธีที่ยอดเยี่ยมในการอัปเดตเนื้อหาในหน้าโดยไม่ทำให้ผู้ใช้แปลกใจ เนื้อหาที่เปลี่ยนแปลงไปอย่างกะทันหันหรือที่ไม่คาดคิดบนหน้าเว็บมักจะสร้างประสบการณ์ที่ไม่ดีแก่ผู้ใช้ แต่เนื้อหาที่ค่อยๆ ย้ายจากตำแหน่งหนึ่งไปยังอีกตำแหน่งหนึ่งอย่างเป็นธรรมชาติมักจะช่วยให้ผู้ใช้เข้าใจได้ดีขึ้น และแนะนำผู้ใช้ในระหว่างการเปลี่ยนสถานะ
โปรดปฏิบัติตามการตั้งค่าเบราว์เซอร์ prefers-reduced-motion
เนื่องจากผู้เข้าชมเว็บไซต์บางรายอาจเจอผลกระทบที่รุนแรงหรือปัญหาด้านความสนใจจากภาพเคลื่อนไหว
พร็อพเพอร์ตี้ CSS transform
ช่วยให้คุณทำให้องค์ประกอบเคลื่อนไหวได้โดยไม่ต้องทริกเกอร์การเปลี่ยนเลย์เอาต์ ดังนี้
- ใช้
transform: scale()
แทนการเปลี่ยนพร็อพเพอร์ตี้height
และwidth
- หากต้องการย้ายองค์ประกอบ ให้หลีกเลี่ยงการเปลี่ยนแปลงพร็อพเพอร์ตี้
top
,right
,bottom
หรือleft
และใช้transform: translate()
แทน
วิธีวัด CLS
คุณวัด CLS ได้ในห้องปฏิบัติการหรือภาคสนาม และมีให้ใช้งานในเครื่องมือต่อไปนี้
เครื่องมือภาคสนาม
- ประสบการณ์ของผู้ใช้ Chrome รายงาน
- PageSpeed Insights
- Search Console (Core Web Vitals) รายงาน)
- ไลบรารี JavaScript
web-vitals
รายการ
เครื่องมือในห้องทดลอง
วัดการเปลี่ยนแปลงเลย์เอาต์ใน 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
ที่ไม่คาดคิดเหล่านี้ไว้ในเซสชัน และคำนวณมูลค่าสูงสุดของเซสชัน คุณสามารถดูซอร์สโค้ดของไลบรารี JavaScript web vitals
ซึ่งมีการใช้งานข้อมูลอ้างอิงเกี่ยวกับวิธีการคำนวณ CLS
ในกรณีส่วนใหญ่ ค่า CLS ปัจจุบันในขณะที่กำลังยกเลิกการโหลดหน้าคือค่า CLS สุดท้ายของหน้านั้น แต่มีข้อยกเว้นที่สำคัญ 2-3 รายการดังที่ระบุไว้ในส่วนถัดไป ไลบรารี JavaScript ของ web vitals
คำนึงถึงรายการเหล่านี้มากที่สุดเท่าที่เป็นไปได้ภายใต้ข้อจำกัดของ Web API
ความแตกต่างระหว่างเมตริกกับ API
- หากหน้าเว็บโหลดอยู่เบื้องหลังหรืออยู่ในเบื้องหลังก่อนที่เบราว์เซอร์จะแสดงเนื้อหาใดๆ หน้าดังกล่าวก็ไม่ควรรายงานค่า CLS
- หากมีการคืนค่าหน้าเว็บจาก Back/Forward Cache ควรรีเซ็ตค่า CLS เป็น 0 เนื่องจากผู้ใช้จะเห็นหน้านี้ว่าเป็นการเข้าชมหน้าเว็บที่ต่างออกไป
- API ไม่รายงานรายการ
layout-shift
สําหรับการเปลี่ยนแปลงที่เกิดขึ้นภายใน iframe แต่เมตริกทําเนื่องจากเป็นส่วนหนึ่งของประสบการณ์ของผู้ใช้หน้าเว็บ ซึ่งอาจแสดงถึงความแตกต่างระหว่าง CrUX และ RUM คุณควรพิจารณาเกณฑ์เหล่านี้เพื่อให้วัด CLS ได้อย่างเหมาะสม เฟรมย่อยสามารถใช้ API เพื่อรายงานรายการlayout-shift
ของตนไปยังเฟรมหลักเพื่อการรวม
นอกจากข้อยกเว้นเหล่านี้แล้ว CLS ยังมีความซับซ้อนเพิ่มเติมเนื่องจากจะวัดตลอดอายุการใช้งานของหน้าเว็บ ดังนี้
- ผู้ใช้อาจเปิดแท็บค้างไว้มาก เช่น วัน สัปดาห์ เดือน ที่จริงแล้ว ผู้ใช้อาจไม่ได้ปิดแท็บเลย
- ในระบบปฏิบัติการบนอุปกรณ์เคลื่อนที่ เบราว์เซอร์มักจะไม่ใช้ Callback ของหน้าเว็บยกเลิกการโหลดสำหรับแท็บที่ทำงานอยู่เบื้องหลัง ทำให้รายงาน "ขั้นสุดท้าย" ได้ยาก
หากต้องการจัดการกรณีดังกล่าว คุณควรรายงาน 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 เกี่ยวกับการลดการเปลี่ยนเลย์เอาต์
- ทำความเข้าใจ Cumulative Layout Shift โดย Annie Sullivan และ Steve Kobes ในงาน #PerfMatters (2020)
บันทึกการเปลี่ยนแปลง
บางครั้งอาจพบข้อบกพร่องใน API ที่ใช้ในการวัดเมตริก และบางครั้งอาจพบข้อบกพร่องในคำจำกัดความของเมตริกเอง ด้วยเหตุนี้ บางครั้งจึงอาจต้องมีการเปลี่ยนแปลง และการเปลี่ยนแปลงเหล่านี้อาจแสดงเป็นการปรับปรุงหรือความถดถอยในรายงานภายในและแดชบอร์ดของคุณ
การเปลี่ยนแปลงทั้งหมดที่เกิดขึ้นกับการใช้งานหรือคำจำกัดความของเมตริกเหล่านี้จะปรากฏในบันทึกการเปลี่ยนแปลงนี้เพื่อช่วยคุณจัดการเรื่องนี้
หากมีความคิดเห็นเกี่ยวกับเมตริกเหล่านี้ ให้ระบุในกลุ่ม Google Web-vitals-feedback