CLS หรือ Cumulative Layout Shift คือตัวชี้วัดที่บอกว่าหน้าเว็บของเราขยับตำแหน่งเนื้อหาโดยที่ผู้ใช้ไม่ได้สั่งมากแค่ไหน อาการที่แทบทุกคนเคยเจอคือกำลังจะกดปุ่มอยู่ดีๆ แล้วรูปหรือแบนเนอร์โหลดขึ้นมาแทรก ทำให้ปุ่มเลื่อนหนีไปที่อื่น นิ้วจึงไปกดโดนสิ่งที่ไม่ได้ตั้งใจ หรือกำลังอ่านย่อหน้าหนึ่งอยู่แล้วบรรทัดที่อ่านค้างไว้กระโดดหายไปจากสายตา CLS คือความพยายามวัดความหงุดหงิดตรงนี้ออกมาเป็นตัวเลข
CLS เป็นหนึ่งในสามตัวของ Core Web Vitals คู่กับ LCP ที่วัดความเร็วโหลด และ INP ที่วัดการตอบสนองเมื่อผู้ใช้กด เกณฑ์ผ่านของ CLS คือ ไม่เกิน 0.1 บทความนี้เจาะเฉพาะ CLS ตัวเดียวแบบลงลึก ตั้งแต่ที่มาของคะแนน เกณฑ์ผ่าน วิธีเช็กค่าจริงของเว็บตัวเอง สาเหตุที่ทำให้ค่าแย่แยกเป็นข้อๆ ไปจนถึงวิธีแก้แต่ละสาเหตุว่าต้องลงมือที่จุดไหน
CLS คืออะไร และคะแนนนี้คิดมาจากอะไร
CLS คือคะแนนที่รวมการขยับตำแหน่งของเนื้อหาบนหน้าเว็บแบบไม่คาดคิดทุกครั้งที่เกิดขึ้น ตลอดช่วงที่ผู้ใช้เปิดหน้านั้นอยู่ ค่ายิ่งต่ำแปลว่าหน้านิ่ง อ่านและกดได้ตามที่ตาเห็น ค่ายิ่งสูงแปลว่าเนื้อหาเด้งไปเด้งมาจนผู้ใช้ตามไม่ทัน
จุดที่ทำให้ CLS ต่างจากตัวชี้วัดอื่นในชุดเดียวกันคือมันไม่ใช่หน่วยเวลา LCP วัดเป็นวินาที INP วัดเป็นมิลลิวินาที แต่ CLS เป็นคะแนนไม่มีหน่วย (unitless) เพราะคำนวณจากสัดส่วนของพื้นที่หน้าจอที่ถูกกระทบคูณกับระยะที่เนื้อหาเลื่อนไป ไม่ใช่จำนวนพิกเซลดิบๆ เหตุผลที่ต้องคิดเป็นสัดส่วนก็เพราะการเลื่อน 100 พิกเซลบนจอมือถือเครื่องเล็กสร้างความรำคาญมากกว่าการเลื่อนเท่ากันบนจอเดสก์ท็อปใหญ่ๆ อย่างเทียบไม่ได้
อีกเรื่องที่ต้องเข้าใจให้ชัดคือ CLS นับเฉพาะ การขยับที่ผู้ใช้ไม่ได้เป็นคนสั่ง เท่านั้น ถ้าผู้ใช้กดปุ่มแล้วเมนูกางลงมาดันเนื้อหาข้างล่างให้เลื่อน หรือกดปุ่มอ่านเพิ่มเติมแล้วข้อความยืดออก การขยับแบบนั้นไม่ถูกนับเป็นโทษ เพราะผู้ใช้เป็นคนทำให้เกิดเองและคาดหวังไว้แล้ว เบราว์เซอร์จะยกเว้นการขยับที่เกิดขึ้นในช่วงสั้นๆ ราวครึ่งวินาทีหลังผู้ใช้โต้ตอบให้ ถ้าอยากเห็นภาพว่า CLS วางตัวอยู่ตรงไหนเมื่อเทียบกับอีกสองตัว อ่านภาพรวมได้ที่ Core Web Vitals คืออะไร LCP INP CLS แล้วค่อยกลับมาเจาะตัวนี้
พูดให้ตรงที่สุด CLS ไม่ใช่ตัวชี้วัดความเร็ว แต่เป็นตัวชี้วัดความน่าเชื่อถือของหน้าจอ เว็บที่โหลดเร็วมากแต่วาดเสร็จแล้วยังขยับอีกสามรอบก็ได้คะแนน CLS แย่ได้สบาย ในทางกลับกันเว็บที่โหลดช้าหน่อยแต่จองพื้นที่ทุกอย่างไว้ครบตั้งแต่ต้นก็ได้ CLS เป็นศูนย์ได้
คะแนนของการขยับแต่ละครั้งคิดยังไง
คะแนนของการขยับหนึ่งครั้งมาจากสองส่วนคูณกัน ส่วนแรกคือสัดส่วนพื้นที่ของหน้าจอที่ได้รับผลกระทบ นับจากพื้นที่รวมของตำแหน่งเดิมกับตำแหน่งใหม่ของสิ่งที่ขยับ ส่วนที่สองคือระยะที่มันเลื่อนไปเทียบกับขนาดหน้าจอ
ยกตัวอย่างให้เห็นภาพ ถ้ามีข้อความกินพื้นที่ครึ่งบนของจอแล้วถูกดันลงมาหนึ่งในสี่ของความสูงจอ พื้นที่ที่กระทบจะกลายเป็นสามในสี่ของจอและระยะเลื่อนคือหนึ่งในสี่ คูณกันได้ประมาณ 0.19 ซึ่งเกินเกณฑ์ดีไปแล้วจากการขยับครั้งเดียวเท่านั้น นี่คือเหตุผลที่คะแนน CLS พังง่ายกว่าที่คนคิด เพราะการขยับใหญ่ๆ เพียงจังหวะเดียวก็เพียงพอ
ข้อสรุปเชิงปฏิบัติที่ได้จากสูตรนี้คือ การขยับที่อยู่บนสุดของหน้าอันตรายที่สุด เพราะมันดันทุกอย่างที่อยู่ใต้มันลงไปพร้อมกัน ทำให้สัดส่วนพื้นที่ที่กระทบสูงมาก ในขณะที่การขยับของสิ่งที่อยู่ล่างสุดของหน้ามักเสียคะแนนน้อยกว่าเยอะ
ทำไมต้องเป็นคะแนนสะสม ไม่ใช่วัดครั้งเดียว
คำว่า Cumulative ในชื่อมาจากการที่ CLS เก็บการขยับตลอดอายุของหน้า ไม่ได้วัดเฉพาะจังหวะโหลดหน้าแรกแล้วจบ เหตุผลก็เพราะเว็บสมัยนี้โหลดของเพิ่มเรื่อยๆ ระหว่างที่ผู้ใช้เลื่อนอ่าน ทั้งรูปแบบ lazy load โฆษณาที่เปลี่ยนใบใหม่ระหว่างทาง รายการสินค้าที่ต่อท้ายแบบไม่มีที่สิ้นสุด และเนื้อหาที่ดึงมาภายหลังด้วยสคริปต์
ถ้าวัดแค่ตอนโหลด เว็บที่นิ่งสามวินาทีแรกแล้วกระตุกทุกครั้งที่เลื่อนลงจะสอบผ่านอย่างไม่สมเหตุสมผล เพราะผู้ใช้จริงไม่ได้เปิดหน้าแล้วนิ่งอยู่เฉยๆ แต่เลื่อนอ่านต่อไปเรื่อยๆ การเก็บตลอดอายุหน้าจึงตรงกับประสบการณ์จริงมากกว่า
รายละเอียดที่ควรรู้เพิ่มคือ Google ไม่ได้เอาทุกการขยับมาบวกรวมกันแบบดิบๆ ตลอดทั้งหน้า แต่จัดกลุ่มการขยับที่เกิดติดๆ กันเป็นช่วงแล้วรายงานช่วงที่แย่ที่สุด เพื่อไม่ให้หน้าที่คนเปิดอ่านนานเป็นสิบนาทีเสียเปรียบหน้าที่คนเปิดแค่แป๊บเดียวโดยไม่เป็นธรรม แต่ในทางปฏิบัติผลก็เหมือนเดิม คือจังหวะกระตุกรุนแรงที่สุดของหน้านั้นคือตัวที่ตัดสินคะแนน
ทำไมเว็บกระตุกตอนโหลด
เพราะเบราว์เซอร์ไม่ได้รอให้ทุกชิ้นพร้อมก่อนค่อยวาดหน้า มันวาดสิ่งที่ได้มาก่อนทันที แล้วค่อยเติมชิ้นที่มาช้าลงไปทีหลัง ทุกครั้งที่ชิ้นใหม่แทรกเข้ามาโดยไม่มีที่ว่างจองไว้ให้ เนื้อหาที่วาดไปแล้วจึงถูกดันให้ขยับ
พฤติกรรมนี้ไม่ใช่ข้อบกพร่อง มันเป็นการออกแบบที่ตั้งใจให้ผู้ใช้เห็นอะไรบางอย่างเร็วที่สุด ซึ่งเป็นผลดีกับ LCP โดยตรง ปัญหาเกิดตอนที่เราไม่ได้บอกเบราว์เซอร์ล่วงหน้าว่าของที่ยังมาไม่ถึงจะกินพื้นที่เท่าไหร่ เบราว์เซอร์จึงวาดหน้าโดยอนุมานว่าช่องนั้นสูงศูนย์ พอไฟล์จริงมาถึงแล้วมันสูง 400 พิกเซล ทุกอย่างที่อยู่ใต้ช่องนั้นก็ต้องเลื่อนลงทั้งแถบ
ฝั่งมือถือเจอหนักกว่าเดสก์ท็อปเสมอด้วยสองเหตุผล หนึ่งคือเลย์เอาต์มือถือเป็นคอลัมน์เดียว ของทุกชิ้นเรียงต่อกันในแนวตั้ง การขยับของชิ้นเดียวจึงลากทุกอย่างใต้มันไปด้วย ต่างจากเดสก์ท็อปที่เนื้อหาถูกแบ่งเป็นหลายคอลัมน์ สองคือเน็ตมือถือช้าและไม่สม่ำเสมอกว่า ช่องว่างเวลาระหว่างการวาดหน้ารอบแรกกับตอนที่ของมาถึงจึงยาวกว่า ผู้ใช้เห็นหน้าแล้วเริ่มอ่านหรือเริ่มกดไปแล้วก่อนที่หน้าจะนิ่ง
- เบราว์เซอร์วาดหน้าเป็นรอบๆ ไม่ได้รอให้ทุกอย่างพร้อมก่อน จึงต้องจัดวางใหม่เมื่อของมาถึงช้า
- ของที่ไม่ได้บอกขนาดไว้ล่วงหน้าถูกคิดเป็นสูงศูนย์ก่อน แล้วค่อยเบียดที่ตอนโหลดเสร็จ
- การขยับที่เกิดเหนือเนื้อหาที่ผู้ใช้กำลังดูอยู่ทำให้เสียคะแนนมากที่สุด
- มือถือเสียเปรียบเพราะเลย์เอาต์คอลัมน์เดียวและเน็ตที่ไม่สม่ำเสมอ
- หน้าที่คนเลื่อนอ่านยาวมีโอกาสเจอการขยับเพิ่มระหว่างทางจากของที่โหลดตามมา
CLS เท่าไหร่ถึงเรียกว่าผ่าน
เกณฑ์ของ CLS คือไม่เกิน 0.1 ถือว่าดี อยู่ระหว่าง 0.1 ถึง 0.25 คือต้องปรับปรุง และมากกว่า 0.25 คือแย่ ตัวเลขนี้ไม่มีหน่วยกำกับ ไม่ใช่วินาทีและไม่ใช่เปอร์เซ็นต์ จึงอ่านได้แค่ในฐานะคะแนนเทียบกับเกณฑ์เท่านั้น
การวัดใช้ค่าที่ เปอร์เซ็นไทล์ 75 ของการโหลดหน้าจริง แยกมือถือกับเดสก์ท็อปเป็นคนละชุด แปลว่าต้องมีผู้ใช้จริงอย่างน้อยสามในสี่ที่ได้ค่าอยู่ในเกณฑ์ดีหน้านั้นจึงจะผ่าน จุดนี้สำคัญเพราะมันทำให้การทดสอบบนเครื่องของทีมพัฒนาที่เน็ตแรงและแคชอุ่นอยู่แล้วเชื่อถือไม่ได้ ในเครื่องเราของอาจมาทันจนไม่เห็นการกระตุกเลย ขณะที่ผู้ใช้จริงบนเน็ตมือถือเจอหน้าเด้งทุกครั้ง
ควรจำไว้ด้วยว่า CLS ผ่านตัวเดียวไม่ได้แปลว่า Core Web Vitals ผ่าน หน้าหนึ่งจะถือว่าผ่านต้องได้เกณฑ์ดีทั้งสามตัว การจับ CLS ให้นิ่งจึงควรทำควบคู่ไปกับการดูตัวตอบสนอง ซึ่งอ่านรายละเอียดแยกได้ที่ INP คืออะไร ตัวชี้วัดที่มาแทน FID และสองตัวนี้มักแย่ด้วยเหตุผลคนละเรื่องกันอย่างสิ้นเชิง
- เกณฑ์ดีคือไม่เกิน 0.1 ต้องปรับปรุง 0.1 ถึง 0.25 และแย่คือเกิน 0.25
- เป็นค่าไม่มีหน่วย อ่านเทียบกับเกณฑ์อย่างเดียว ไม่ใช่วินาทีและไม่ใช่เปอร์เซ็นต์
- วัดที่เปอร์เซ็นไทล์ 75 ของการโหลดหน้าจริง แยกมือถือกับเดสก์ท็อป
- การขยับใหญ่เพียงครั้งเดียวก็ดัน CLS ให้เกินเกณฑ์ได้ ไม่จำเป็นต้องกระตุกหลายรอบ
- ต้องผ่านครบทั้ง LCP, INP และ CLS หน้านั้นจึงจะถือว่าผ่าน Core Web Vitals
| ระดับคะแนน | ช่วงค่า CLS | สิ่งที่ผู้ใช้เจอจริง |
|---|---|---|
| ดี (Good) | ไม่เกิน 0.1 | หน้านิ่งพอที่จะอ่านและกดได้ตามตำแหน่งที่ตาเห็น |
| ต้องปรับปรุง (Needs Improvement) | มากกว่า 0.1 ถึง 0.25 | เห็นหน้าขยับเป็นบางจังหวะ เริ่มอ่านหลุดบรรทัดหรือกดพลาด |
| แย่ (Poor) | มากกว่า 0.25 | หน้าเด้งชัดเจนหลายรอบ กดผิดปุ่มได้ง่ายจนน่ารำคาญ |
จะเช็กคะแนน CLS ของเว็บตัวเองที่ไหน
เช็กได้ฟรีจากเครื่องมือของ Google เป็นหลัก คือ PageSpeed Insights สำหรับดูทีละหน้า และรายงาน Core Web Vitals ใน Google Search Console สำหรับดูภาพรวมทั้งเว็บว่ากลุ่ม URL ไหนตกเกณฑ์ CLS ทั้งสองตัวดึงข้อมูลผู้ใช้จริงจากฐานเดียวกันคือ Chrome UX Report หรือ CrUX ซึ่งเป็นค่าเฉลี่ยแบบ rolling window 28 วัน
เรื่องที่ต้องแยกให้ออกคือ field data กับ lab data ข้อมูลฝั่ง field มาจากผู้ใช้จริงและเป็นตัวที่ Google ใช้ ส่วน lab data อย่าง Lighthouse รันในสภาพแวดล้อมจำลองเพื่อให้ทดสอบซ้ำได้ ข่าวดีของ CLS คือ lab data จำลองได้ใกล้เคียงกว่ากรณีของ INP อยู่มาก เพราะการกระตุกส่วนใหญ่เกิดในช่วงโหลดหน้าเอง ไม่ต้องรอให้มีคนกดอะไรก่อนถึงจะวัดได้ แต่ ค่าจากแล็บก็ยังไม่ใช่ตัวเลขที่ Google ใช้จัดอันดับ และมันมองไม่เห็นการขยับที่เกิดตอนผู้ใช้เลื่อนอ่านลงไปเรื่อยๆ หรือตอนโฆษณาสลับใบใหม่
ระดับที่ลึกขึ้นคือ Chrome DevTools ที่ Performance panel ซึ่งบันทึกการโหลดหน้าแล้วชี้ให้เห็นเป็นกรอบว่าบริเวณไหนของหน้าขยับในจังหวะไหน จุดนี้มีค่ามากเพราะบอกได้ถึงระดับ element ว่าตัวไหนเป็นต้นเหตุ ต่างจากรายงานภาพรวมที่บอกแค่ว่าหน้านี้คะแนนเท่าไหร่ ส่วนวิธีอ่านรายงาน Core Web Vitals และไล่ดูทีละกลุ่ม URL ดูขั้นตอนได้ที่ คู่มือใช้งาน Google Search Console
- PageSpeed Insights — ดูค่า CLS ของผู้ใช้จริงรายหน้า พร้อมรายการ element ที่ทำให้เกิดการขยับ
- Search Console รายงาน Core Web Vitals — ดูภาพรวมทั้งเว็บว่า URL กลุ่มไหนตก CLS
- Chrome DevTools Performance panel — บันทึกการโหลดแล้วดูกรอบบริเวณที่ขยับทีละจังหวะ
- ส่วนขยาย Web Vitals ของ Chrome — เห็นค่าสะสมแบบเรียลไทม์ขณะเลื่อนอ่านหน้าจริง
- ทดสอบซ้ำโดยจำลองเน็ตช้าและล้างแคชทุกครั้ง ไม่งั้นจะไม่เห็นการกระตุกที่ผู้ใช้จริงเจอ
| ปัจจัย | Field data (ผู้ใช้จริง) | Lab data (จำลอง) |
|---|---|---|
| แหล่งข้อมูล | Chrome UX Report จากผู้ใช้ Chrome จริงแบบไม่ระบุตัวตน | Lighthouse หรือ DevTools ที่รันในเครื่องทดสอบ |
| ช่วงเวลาที่สรุปค่า | rolling window 28 วัน รายงานที่เปอร์เซ็นไทล์ 75 | ผลของการทดสอบรอบนั้นรอบเดียว |
| Google ใช้จัดอันดับไหม | ใช้ตัวนี้ | ไม่ใช้ เป็นเครื่องมือสำหรับหาสาเหตุ |
| ความแม่นกับ CLS | ตรงกับที่ผู้ใช้เจอจริงทุกอุปกรณ์และทุกความเร็วเน็ต | ใกล้เคียงกว่ากรณี INP เพราะการกระตุกเกิดช่วงโหลดเป็นส่วนใหญ่ |
| ข้อจำกัดที่ต้องรู้ | เว็บทราฟฟิกน้อยอาจยังไม่มีข้อมูล และแก้แล้วต้องรอค่าสะสมใหม่ | ไม่เห็นการขยับตอนผู้ใช้เลื่อนอ่านหรือตอนโฆษณาสลับใบ |
สาเหตุที่ทำให้ CLS แย่มีอะไรบ้าง
สาเหตุเกือบทั้งหมดของ CLS ที่แย่สรุปได้ประโยคเดียว คือมีของบางอย่างเข้ามากินพื้นที่บนหน้าโดยที่ไม่มีใครจองที่ไว้ให้มันล่วงหน้า ส่วนที่เหลือเป็นเรื่องของการเลือกวิธีขยับที่ผิด คือไปขยับสิ่งที่กระทบการจัดวางของทั้งหน้า
แต่การรู้แค่หลักการรวมยังแก้อะไรไม่ได้ ต้องแยกให้ออกว่าปัญหาเข้าข่ายแบบไหน เพราะจุดที่ต้องลงมือแก้อยู่คนละที่กันคนละไฟล์กัน หัวข้อย่อยข้างล่างคือห้ากลุ่มสาเหตุที่เจอบ่อยที่สุด เรียงจากที่พบมากที่สุดลงไป และในเว็บจริงมักเจอพร้อมกันหลายข้อ ไม่ได้มีข้อเดียว
1. รูป วิดีโอ หรือ iframe ที่ไม่กำหนดขนาด
นี่คือต้นเหตุอันดับหนึ่งของ CLS ที่เจอในเว็บทั่วไป เมื่อแท็กรูปไม่มีแอตทริบิวต์ width และ height และ CSS ก็ไม่ได้กำหนด aspect-ratio ไว้ เบราว์เซอร์ไม่มีทางรู้เลยว่ารูปใบนั้นสูงเท่าไหร่จนกว่าจะดาวน์โหลดไฟล์มาอ่านหัวไฟล์เสร็จ ระหว่างนั้นมันจึงจัดวางหน้าโดยให้ช่องรูปสูงศูนย์
ผลคือข้อความใต้รูปถูกวาดขึ้นไปชิดขอบบนก่อน แล้วพอรูปมาถึงก็เด้งลงมาทั้งก้อนตามความสูงจริงของรูป ยิ่งรูปใหญ่และยิ่งอยู่สูงบนหน้า ยิ่งเสียคะแนนหนัก กรณีที่เจอบ่อยเป็นพิเศษคือรูปในเนื้อบทความที่ทีมคอนเทนต์อัปโหลดเองโดยไม่ผ่านระบบที่ใส่ขนาดให้อัตโนมัติ และ iframe ของวิดีโอหรือแผนที่ที่ก๊อปโค้ดฝังมาแปะตรงๆ
2. โฆษณาและ embed ที่ไม่จองพื้นที่ล่วงหน้า
ช่องโฆษณา วิดเจ็ตรีวิว ฟีดโซเชียล และกล่องแนะนำสินค้าจากระบบภายนอก ล้วนเป็นของที่ขนาดสุดท้ายถูกตัดสินหลังจากสคริปต์ฝั่งนั้นตอบกลับมา ถ้าเราไม่กำหนดความสูงของกล่องไว้เอง หน้าจะถูกจัดวางใหม่ทุกครั้งที่ของมาถึง
กรณีนี้ร้ายกว่ารูปธรรมดาอยู่สองอย่าง อย่างแรกคือขนาดของมันไม่คงที่ โฆษณาใบนี้อาจสูง 250 พิกเซล อีกรอบสูง 100 พิกเซล และบางรอบไม่มีอะไรมาเลย อย่างที่สองคือมันมักเปลี่ยนใบใหม่ระหว่างที่ผู้ใช้ยังอยู่บนหน้า ทำให้เกิดการขยับเพิ่มหลังโหลดเสร็จไปนานแล้ว ซึ่งเป็นการกระตุกที่การทดสอบในแล็บมองไม่เห็นเลย
3. เว็บฟอนต์ที่ทำให้ข้อความเปลี่ยนขนาดกลางทาง
เว็บส่วนใหญ่ใช้ฟอนต์ที่ต้องดาวน์โหลด ระหว่างที่ไฟล์ฟอนต์ยังไม่มาถึง เบราว์เซอร์มีสองทางเลือก คือซ่อนข้อความไว้ก่อนจนฟอนต์มา หรือวาดด้วยฟอนต์สำรองของเครื่องไปก่อนแล้วสลับทีหลัง ทางแรกเรียกว่า FOIT ทางที่สองเรียกว่า FOUT และพฤติกรรมนี้คุมได้ด้วยค่า font-display
ปัญหา CLS เกิดตอนสลับฟอนต์ เพราะฟอนต์สำรองกับฟอนต์จริงมีความกว้างตัวอักษรและความสูงบรรทัดไม่เท่ากัน พอสลับแล้วข้อความอาจกินบรรทัดเพิ่มหรือลดลง ทำให้ทุกอย่างใต้ก้อนข้อความนั้นเลื่อน กรณีภาษาไทยมีประเด็นเพิ่มคือความสูงของสระและวรรณยุกต์ต่างกันตามฟอนต์ ความสูงบรรทัดจริงจึงเปลี่ยนได้มากกว่าที่คาด และหัวข้อใหญ่ตัวหนาบนสุดของหน้าคือจุดที่เห็นผลชัดที่สุด
4. เนื้อหาที่แทรกเข้ามาทีหลังเหนือของที่มีอยู่แล้ว
ทุกอย่างที่ถูกยัดเข้าไปด้านบนของหน้าหลังจากที่ผู้ใช้เห็นเนื้อหาไปแล้วคือบ่อเกิดของ CLS ตัวอย่างที่เจอทุกวันคือแถบแจ้งเตือนคุกกี้ แถบโปรโมชันที่เด้งลงมาจากด้านบน กล่องสมัครรับข่าวสาร ประกาศจัดส่งฟรี และข้อความแจ้งเตือนผลการกรอกฟอร์มที่ทำให้ฟิลด์ข้างล่างเลื่อนลง
อีกรูปแบบที่แนบเนียนกว่าคือเนื้อหาที่ดึงมาด้วยสคริปต์หลังหน้าโหลดเสร็จ เช่นราคาสินค้าที่ดึงสดจาก API รายการ เพิ่งดูล่าสุด บล็อกรีวิวดาว และเมนูที่ประกอบร่างด้วย JavaScript ฝั่งไคลเอนต์ ของพวกนี้ทำให้หน้าที่ดูเหมือนโหลดเสร็จแล้วยังขยับได้อีกหนึ่งหรือสองรอบ
5. แอนิเมชันที่ขยับด้วยคุณสมบัติที่กระทบการจัดวาง
แอนิเมชันไม่ได้เสีย CLS ทุกตัว มันเสียเฉพาะเมื่อเราเลือกขยับด้วยคุณสมบัติที่บังคับให้เบราว์เซอร์คำนวณการจัดวางใหม่ ได้แก่ top, left, margin, width และ height การเปลี่ยนค่าพวกนี้แบบต่อเนื่องเท่ากับสั่งให้หน้าจัดเรียงใหม่ทุกเฟรม และของข้างเคียงก็ถูกเบียดตามไปด้วย
ทางที่ถูกคือขยับด้วย transform และไล่ความจางด้วย opacity เพราะสองตัวนี้เบราว์เซอร์จัดการในชั้นการวาดภาพได้เลยโดยไม่ต้องคิดการจัดวางของหน้าใหม่ ผลพลอยได้คือแอนิเมชันลื่นกว่าด้วย เพราะไม่ต้องไปแย่งเวลาคำนวณ layout ในทุกเฟรม
แก้ CLS ยังไงให้หน้าเว็บนิ่ง
หลักการแก้ CLS มีข้อเดียวคือ จองพื้นที่ล่วงหน้าให้ทุกอย่างที่มาช้า ให้เบราว์เซอร์รู้ขนาดของทุกช่องตั้งแต่การวาดหน้ารอบแรก ของที่มาถึงทีหลังก็จะเข้าไปนั่งในช่องที่เตรียมไว้พอดีโดยไม่ต้องเบียดใครเลย
ข้อดีของ CLS เมื่อเทียบกับตัวชี้วัดอื่นคือแก้แล้วเห็นผลเป็นรูปธรรมและไม่ค่อยต้องรื้อสถาปัตยกรรม ส่วนใหญ่เป็นการเติมแอตทริบิวต์ ตั้งค่า CSS และย้ายตำแหน่งการแทรกเนื้อหา ต่างจาก INP ที่มักต้องไปยุ่งกับตรรกะของโค้ดจริงจัง ลำดับที่คุ้มแรงที่สุดคือเริ่มจากของที่อยู่บนสุดของหน้าในจุดที่ผู้ใช้เห็นก่อนเลื่อน เพราะการขยับตรงนั้นกินคะแนนมากที่สุด แล้วค่อยไล่ลงล่าง
และเนื่องจาก CLS ผูกกับจังหวะที่ทรัพยากรมาถึง งานแก้ความเร็วโดยรวมของเว็บก็ช่วยลดโอกาสกระตุกไปด้วยในทางอ้อม เพราะยิ่งของมาถึงเร็วและใกล้กัน ช่องว่างที่หน้าจะจัดวางใหม่ก็ยิ่งแคบ อ่านภาพรวมเรื่องนี้ได้ที่ เว็บโหลดช้าส่งผลต่อ SEO อย่างไร
- ใส่ width และ height หรือกำหนด aspect-ratio ให้รูป วิดีโอ และ iframe ทุกชิ้น
- กำหนดความสูงต่ำสุดให้ช่องโฆษณาและวิดเจ็ตภายนอกทุกช่องตั้งแต่ก่อนของมาถึง
- เลี่ยงการวางของที่ขนาดไม่แน่นอนไว้ในส่วนบนสุดของหน้า
- preload ฟอนต์ที่ใช้ในส่วนบนของหน้า ตั้ง font-display และจับคู่ฟอนต์สำรองให้สัดส่วนใกล้กัน
- ทำแถบแจ้งเตือนและป๊อปอัปให้ลอยทับ ไม่ใช่แทรกดันเนื้อหาเดิม
- เปลี่ยนแอนิเมชันจาก top, left, width, height มาใช้ transform และ opacity
- จองพื้นที่ให้ข้อมูลที่ดึงมาทีหลัง หรือเรนเดอร์จากฝั่งเซิร์ฟเวอร์ไปเลยถ้าทำได้
- ทดสอบซ้ำโดยจำลองเน็ตช้าและเลื่อนอ่านหน้าจนจบ ไม่ใช่ดูแค่ตอนเปิดหน้า
แก้รูปและวิดีโอ — ใส่ขนาดให้ครบทุกใบ
ใส่ width และ height เป็นตัวเลขจริงให้แท็กรูปทุกใบ ให้เบราว์เซอร์คำนวณอัตราส่วนแล้วจองความสูงไว้ได้ทันทีก่อนไฟล์มาถึง วิธีนี้ใช้ได้แม้รูปจะยืดหยุ่นตามความกว้างจอก็ตาม เพราะเบราว์เซอร์สมัยใหม่เอาสองค่านั้นไปคิดเป็นอัตราส่วนให้เอง หรือกำหนด aspect-ratio ใน CSS ให้กล่องรูปก็ได้ผลเหมือนกัน
กรณี iframe ของวิดีโอหรือแผนที่ที่ควบคุมความสูงไม่ได้ตรงๆ ให้ครอบด้วยกล่องที่มีอัตราส่วนคงที่แล้วให้ iframe ขยายเต็มกล่องนั้น ส่วนรูปหลักบนสุดของหน้าอย่าเผลอสั่ง lazy load เพราะจะได้ทั้ง CLS ที่แย่และ LCP ที่ช้าลงพร้อมกัน
ถ้าเว็บใช้ระบบจัดการรูปอยู่แล้วให้ตรวจที่ระดับคอมโพเนนต์แทนที่จะไล่แก้ทีละหน้า เพราะแก้จุดเดียวได้ทั้งเว็บและกันไม่ให้เนื้อหาที่เพิ่มในอนาคตพลาดซ้ำ
แก้โฆษณาและวิดเจ็ตภายนอก — ล็อกความสูงกล่องไว้ก่อน
กำหนดความสูงต่ำสุดให้กล่องที่จะบรรจุของจากภายนอกทุกช่อง โดยใช้ขนาดที่พบบ่อยที่สุดของช่องนั้นเป็นเกณฑ์ ถ้าของจริงเล็กกว่าที่จองก็เหลือช่องว่างซึ่งไม่เสียคะแนนอะไร แต่ถ้าของจริงใหญ่กว่าที่จองไว้ หน้าจะกระตุกทันที
หลีกเลี่ยงการวางช่องที่ขนาดไม่แน่นอนไว้ในส่วนบนสุดของหน้าที่ผู้ใช้เห็นก่อนเลื่อน ถ้าจำเป็นต้องมีจริงๆ ให้เลือกขนาดคงที่ตายตัวไปเลย ส่วนกรณีที่ช่องนั้นอาจไม่มีของมาแสดงเลย ให้ยุบทั้งช่องทิ้งตั้งแต่ฝั่งเซิร์ฟเวอร์ ดีกว่าให้มันโผล่มาแทรกกลางหน้าทีหลัง
ถ้าใช้กล่องโครงเปล่าแบบ skeleton ระหว่างรอ ต้องทำให้ขนาดของกล่องโครงเท่ากับขนาดของจริงที่จะมาแทน ไม่ใช่แค่พอเป็นพิธี เพราะถ้าขนาดไม่ตรงก็ยังเกิดการขยับตอนสลับอยู่ดี
แก้ฟอนต์ — ลดแรงกระเพื่อมตอนสลับ
โหลดฟอนต์ที่ใช้ในส่วนบนของหน้าให้เร็วขึ้นด้วย preload และเก็บไฟล์ฟอนต์ไว้บนโดเมนตัวเองแทนการดึงจากภายนอก เพื่อตัดขั้นตอนการต่อเชื่อมไปอีกโดเมนหนึ่ง ยิ่งฟอนต์มาถึงเร็วเท่าไหร่ ช่วงเวลาที่หน้าจะสลับฟอนต์ก็ยิ่งสั้น
ตั้งค่า font-display ให้ตรงกับเจตนา ถ้ายอมให้เห็นข้อความด้วยฟอนต์สำรองก่อนใช้ swap ถ้าไม่อยากให้สลับหลังจากเลยจุดหนึ่งไปแล้วใช้ optional ซึ่งแลกด้วยการที่ผู้ใช้บางคนอาจไม่เห็นฟอนต์แบรนด์เลยในการโหลดครั้งแรก
ที่ช่วยได้มากคือเลือกฟอนต์สำรองที่สัดส่วนใกล้เคียงกับฟอนต์จริง และปรับค่าของฟอนต์สำรองให้ความกว้างและความสูงบรรทัดใกล้กันที่สุด เพื่อให้จำนวนบรรทัดก่อนและหลังสลับเท่ากัน การขยับก็จะแทบไม่เกิดขึ้น
แก้เนื้อหาที่แทรกทีหลัง — อย่าดันของที่ผู้ใช้เห็นแล้ว
แถบคุกกี้ แถบโปรโมชัน และป๊อปอัปทุกชนิดควรลอยทับเนื้อหาแบบ fixed หรือ sticky ไม่ใช่แทรกเข้าไปในสายเนื้อหาเพื่อดันทุกอย่างลง วิธีนี้ทำให้ผู้ใช้เห็นข้อความเดียวกันแต่หน้าไม่ขยับแม้แต่พิกเซลเดียว
ข้อมูลที่ดึงมาด้วยสคริปต์ทีหลังอย่างราคา สต็อก หรือคะแนนรีวิว ควรจองพื้นที่ในขนาดที่ใกล้เคียงกับค่าจริงไว้ก่อน หรือถ้าทำได้ควรเรนเดอร์มาจากฝั่งเซิร์ฟเวอร์ตั้งแต่แรกเพื่อตัดปัญหาทั้งหมดนี้ไปเลย
ส่วนข้อความแจ้งเตือนของฟอร์ม ให้เตรียมพื้นที่ใต้ช่องกรอกไว้ล่วงหน้าหนึ่งบรรทัด แทนที่จะให้ข้อความโผล่มาแล้วดันปุ่มส่งลงไปตอนที่ผู้ใช้กำลังเอานิ้วจ่อจะกดอยู่
CLS มีผลกับ SEO มากแค่ไหน
CLS เป็นหนึ่งในสามตัวของ Core Web Vitals ซึ่งเป็นสัญญาณด้านประสบการณ์หน้าเว็บที่ Google ใช้ประกอบการจัดอันดับ แต่เป็นสัญญาณน้ำหนักเบาเมื่อเทียบกับความตรงประเด็นและคุณภาพของเนื้อหา ทำให้ CLS ดีขึ้นไม่ได้แปลว่าอันดับจะขยับตามทันที และไม่มีใครควบคุมหรือการันตีอันดับของ Google ได้
มุมที่ควรมองคือ CLS ทำหน้าที่คล้ายตัวช่วยตัดสินเมื่อหลายหน้าที่แข่งกันมีเนื้อหาสูสี แต่ผลที่หนักกว่าเรื่องอันดับคือความเสียหายทางธุรกิจตรงหน้า หน้าที่กระตุกทำให้ผู้ใช้กดปุ่มผิด กดเข้าโฆษณาที่ไม่ได้ตั้งใจ กรอกฟอร์มผิดช่อง หรือกดยืนยันคำสั่งซื้อก่อนที่จะอ่านสรุปยอดเสร็จ ความรู้สึกที่เหลือคือเว็บนี้ไม่น่าเชื่อถือ ซึ่งกระทบ conversion ทันทีโดยไม่ต้องรอ Google มาตัดสินอะไร
อีกมุมที่มักถูกลืมคือหน้าที่คนแวะเข้ามาจากผลค้นหาแล้วต้องเลื่อนหาคำตอบ ถ้าพอเลื่อนแล้วตำแหน่งเนื้อหาเปลี่ยนไปเรื่อยๆ คนก็หาคำตอบไม่เจอและกดย้อนกลับไปเลือกผลอื่น พฤติกรรมแบบนั้นแปลว่าเสียโอกาสไปตั้งแต่ยังไม่ได้อ่านเนื้อหาที่เราตั้งใจเขียน ทางที่สมเหตุสมผลคือทำให้หน้าที่สำคัญต่อรายได้นิ่งก่อน เช่นหน้าสินค้า หน้าบริการ และหน้าที่มีฟอร์ม แล้วค่อยไล่เก็บหน้าอื่นตามลำดับความสำคัญ
สรุป: ควรเริ่มจับ CLS จากตรงไหนก่อน
เริ่มจากดูรายงาน Core Web Vitals ใน Search Console ว่ามีกลุ่ม URL ไหนตก CLS แล้วเลือกเทมเพลตหน้าที่มีทราฟฟิกสูงหรือเกี่ยวข้องกับรายได้ขึ้นมาก่อน เพราะเว็บส่วนใหญ่ใช้เทมเพลตซ้ำกันหลายร้อยหน้า แก้ที่เทมเพลตหนึ่งตัวจึงมักลากคะแนนขึ้นทั้งกลุ่มพร้อมกัน
จากนั้นเปิดหน้านั้นใน Chrome DevTools แบบจำลองเน็ตช้า บันทึกการโหลดแล้วดูว่าบริเวณไหนขยับในจังหวะไหน ไล่แก้ตามสาเหตุที่เจอจริง ไม่ใช่เดาจากรายการข้อแนะนำทั่วไป เรียงจากของที่อยู่บนสุดของหน้าลงไปเพราะจุดนั้นกินคะแนนมากที่สุด แก้เสร็จแล้วรอให้ข้อมูลผู้ใช้จริงสะสมสักช่วงหนึ่งก่อนค่อยสรุปว่าดีขึ้น เพราะค่าที่ Google ใช้เป็นค่าเฉลี่ยย้อนหลัง 28 วัน ไม่ได้เปลี่ยนในวันเดียว
สุดท้ายคือกันไม่ให้ปัญหากลับมา วางกฎของทีมไว้เลยว่ารูปทุกใบต้องมีขนาด ช่องของจากภายนอกทุกช่องต้องจองความสูง และแถบแจ้งเตือนทุกชนิดต้องลอยทับไม่ดันเนื้อหา ถ้าไม่แน่ใจว่าเว็บของตัวเองติดตรงไหนหรือควรแก้อะไรก่อน บริการ ตรวจสุขภาพเว็บ SEO Audit ของ SEONo1 ช่วยไล่ดูทั้ง Core Web Vitals และงาน Technical SEO ส่วนอื่นให้เป็นลำดับได้
คำถามที่พบบ่อย
01CLS เท่าไหร่ถึงถือว่าผ่านเกณฑ์+
ไม่เกิน 0.1 ถือว่าดี ระหว่าง 0.1 ถึง 0.25 คือต้องปรับปรุง และมากกว่า 0.25 คือแย่ โดยวัดที่เปอร์เซ็นไทล์ 75 ของการโหลดหน้าจริง แยกมือถือกับเดสก์ท็อปคนละชุด หมายความว่าต้องมีผู้ใช้จริงอย่างน้อยสามในสี่ที่ได้ค่าอยู่ในเกณฑ์ดีหน้านั้นจึงจะผ่าน ค่านี้ไม่มีหน่วยกำกับ อ่านเทียบกับเกณฑ์ได้เท่านั้น ไม่ใช่วินาทีและไม่ใช่เปอร์เซ็นต์
02ทำไมหน้าเว็บกระตุกตอนโหลด+
เพราะเบราว์เซอร์วาดหน้าจากสิ่งที่ได้มาก่อนโดยไม่รอให้ทุกอย่างพร้อม เมื่อรูป โฆษณา ฟอนต์ หรือเนื้อหาที่ดึงมาทีหลังมาถึงโดยไม่มีพื้นที่จองไว้ล่วงหน้า ของที่วาดไปแล้วจึงถูกดันให้เลื่อน สาเหตุที่พบบ่อยที่สุดคือรูปและ iframe ที่ไม่กำหนด width กับ height หรือไม่ได้ตั้ง aspect-ratio ไว้
03การขยับที่ผู้ใช้กดเองนับเป็น CLS ด้วยไหม+
ไม่นับ ถ้าผู้ใช้กดปุ่มแล้วเมนูกางลงมาหรือกดอ่านเพิ่มเติมแล้วข้อความยืดออก การขยับนั้นถูกยกเว้นเพราะผู้ใช้เป็นคนทำให้เกิดเองและคาดหวังไว้แล้ว เบราว์เซอร์จะไม่นับการขยับที่เกิดขึ้นในช่วงสั้นๆ ราวครึ่งวินาทีหลังการโต้ตอบ ที่ถูกนับคือการขยับที่เกิดขึ้นเองโดยผู้ใช้ไม่ได้สั่งเท่านั้น
04ทดสอบในเครื่องแล้วคะแนน CLS ดี แต่ของจริงแย่ เพราะอะไร+
เพราะการทดสอบในเครื่องมักใช้เน็ตเร็วและมีไฟล์อยู่ในแคชอยู่แล้ว ของจึงมาถึงทันจนไม่เห็นการกระตุก ขณะที่ผู้ใช้จริงบนเน็ตมือถือเจอช่องว่างเวลาที่ยาวกว่ามาก อีกจุดคือการทดสอบแบบจำลองมักดูแค่ช่วงโหลดหน้า ไม่ได้เลื่อนอ่านลงไปจนจบ จึงไม่เห็นการขยับที่เกิดจากของที่โหลดตามมาหรือโฆษณาที่สลับใบใหม่
05CLS แย่แล้วอันดับจะตกทันทีไหม+
ไม่ถึงขั้นนั้น CLS เป็นสัญญาณด้านประสบการณ์หน้าเว็บที่มีน้ำหนักเบาเมื่อเทียบกับความตรงประเด็นและคุณภาพของเนื้อหา มันมีผลชัดกว่าในแง่ที่ว่าเมื่อหลายหน้าสูสีกัน ประสบการณ์ที่ดีกว่าย่อมได้เปรียบ และผลกระทบที่เห็นก่อนเรื่องอันดับคือผู้ใช้กดผิดปุ่ม อ่านหลุดบรรทัด แล้วเลิกกรอกฟอร์มหรือย้อนกลับไปเลือกผลอื่น

