การเปลี่ยนเลย์เอาต์ที่ไม่คาดคิดอาจรบกวนประสบการณ์ของผู้ใช้ได้หลายวิธี ตั้งแต่ทำให้ผู้ใช้เสียตำแหน่งขณะอ่านหากข้อความเลื่อนไปอย่างกะทันหัน ไปจนถึงทำให้ผู้ใช้คลิกลิงก์หรือปุ่มที่ไม่ถูกต้อง ซึ่งในบางกรณีอาจทำให้เกิดความเสียหายร้ายแรง
การเคลื่อนไหวของเนื้อหาหน้าเว็บที่ไม่คาดคิดมักเกิดขึ้นเมื่อทรัพยากรโหลดแบบไม่พร้อมกันหรือมีการเพิ่มองค์ประกอบ DOM ลงในหน้าเว็บแบบไดนามิกก่อนเนื้อหาที่มีอยู่ สาเหตุที่เลย์เอาต์เปลี่ยนอาจเกิดจากรูปภาพหรือวิดีโอที่มีขนาดที่ไม่รู้จัก แบบอักษรที่แสดงผลใหญ่กว่าหรือเล็กกว่าแบบอักษรสำรองแรก หรือโฆษณาหรือวิดเจ็ตของบุคคลที่สามที่ปรับขนาดตัวเองแบบไดนามิก
ความแตกต่างระหว่างวิธีที่เว็บไซต์ทํางานในระหว่างการพัฒนากับประสบการณ์การใช้งานของผู้ใช้ทําให้ปัญหานี้แย่ลง เช่น
- เนื้อหาที่ปรับตามโปรไฟล์ของผู้ใช้หรือเนื้อหาของบุคคลที่สามมักจะทำงานแตกต่างกันระหว่างการพัฒนาและเวอร์ชันที่ใช้งานจริง
- รูปภาพทดสอบมักจะอยู่ในแคชของเบราว์เซอร์ของนักพัฒนาแอปอยู่แล้ว แต่ผู้ใช้ปลายทางจะใช้เวลาโหลดนานกว่า
- การเรียก API ที่ทำงานในเครื่องมักจะเร็วมากจนความล่าช้าที่มองไม่เห็นในการพัฒนาอาจกลายเป็นปัญหาสำคัญในเวอร์ชันที่ใช้งานจริง
เมตริกการเปลี่ยนเลย์เอาต์แบบสะสม (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 ระบบจะเพิ่มผลการค้นหาเพิ่มเติมลงในรายการที่จัดเรียง
รายการแรกในรายการ ("แมว") จะไม่เปลี่ยนตำแหน่งเริ่มต้นระหว่างเฟรม จึงมีความเสถียร ในทํานองเดียวกัน รายการใหม่ที่เพิ่มลงในรายการไม่ได้อยู่ใน 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 สุดท้ายในแบ็กเอนด์
นักพัฒนาซอฟต์แวร์สามารถใช้web-vitals
คลัง JavaScript เพื่อวัด 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