คุณเคยอ่านบทความบนมือถือแล้วกำลังจะกดปุ่ม “อ่านต่อ” — แต่ในเสี้ยววินาทีนั้น โฆษณาแบนเนอร์โหลดเสร็จและดันเนื้อหาลงไป ทำให้นิ้วของคุณกดผิดไปที่โฆษณาแทน? นั่นคือ Layout Shift และเมตริกที่วัดความสะเทือนเหล่านี้คือ CLS (Cumulative Layout Shift) — หนึ่งใน Core Web Vitals ที่ Google ใช้ตัดสินคุณภาพประสบการณ์ผู้ใช้และนำมาเป็นปัจจัยจัดอันดับ SEO
บทความนี้คุณจะได้เรียนรู้สูตรคำนวณ CLS เกณฑ์ Good/Needs Improvement/Poor สาเหตุ 8 อย่างที่ทำให้ CLS สูง วิธีแก้พร้อมโค้ดตัวอย่างที่ใช้ได้จริง รวมถึงเคสจริงของเว็บโรงแรมที่ลด CLS จาก 0.45 → 0.05 ภายใน 2 สัปดาห์ ถ้าคุณอยากให้เว็บของคุณนิ่ง ไม่กระตุก และผ่าน Core Web Vitals — บทความนี้คือคำตอบ
CLS คืออะไร และ “Layout Shift” หมายถึงอะไร
CLS (Cumulative Layout Shift) คือเมตริกใน Core Web Vitals ที่วัด “ความเสถียรของการแสดงผล” ของหน้าเว็บ พูดง่าย ๆ คือวัดว่ามีองค์ประกอบบนหน้าจอเกิดการกระโดด เลื่อน หรือขยับโดยที่ผู้ใช้ไม่ได้ร้องขอมากแค่ไหน
CLS จะสะสมคะแนนของทุก “Unexpected Layout Shift” ที่เกิดขึ้นตลอด lifetime ของหน้า โดย:
- Expected Shift (การเลื่อนที่ผู้ใช้คาดหวัง) — เช่น กดปุ่มแล้ว menu ขยายลงมา หรือกดปุ่มแล้วเปิด modal — ไม่นับ
- Unexpected Shift (การเลื่อนที่ไม่ได้คาดหวัง) — เช่น โฆษณาโหลดมาดันเนื้อหา หรือฟอนต์โหลดเสร็จแล้วข้อความขยาย — นับใน CLS
Google เริ่มใช้ CLS เป็นส่วนหนึ่งของ Core Web Vitals ตั้งแต่ปี 2021 และในปี 2024-2026 ยังคงเป็นปัจจัยจัดอันดับ SEO ผ่าน Page Experience Signal ที่สำคัญ
ทำไม CLS ถึงสำคัญ
- UX แย่ — ผู้ใช้กดผิด หน้าเว็บที่กระตุกทำให้ผู้ใช้กดปุ่มผิด ลบข้อความผิด หรือซื้อของผิด
- เพิ่ม Bounce Rate ผู้ใช้รู้สึกหงุดหงิดและออกจากเว็บ
- ลดอันดับ SEO Google ลดอันดับเว็บที่ CLS > 0.25 ในผลค้นหา
- กระทบ Conversion เว็บ E-commerce ที่ CLS สูงจะมี checkout rate ต่ำกว่า
- ผลต่อ Accessibility ผู้ใช้ที่ใช้ screen reader หรือคีย์บอร์ดได้รับผลกระทบมากกว่า
หากคุณต้องการพัฒนาเว็บไซต์ที่ผ่าน Core Web Vitals ทั้งหมดและให้บริการ SEO ที่ครบวงจร ทีมงานของเรามีบริการพัฒนาเว็บไซต์ที่เน้นเรื่อง Performance โดยเฉพาะ
สูตรคำนวณ CLS อย่างละเอียด
CLS ใช้สูตร:
Layout Shift Score = Impact Fraction × Distance Fraction
CLS = ผลรวมของทุก Layout Shift Score ใน session window
Impact Fraction (สัดส่วนพื้นที่ที่ได้รับผลกระทบ)
คำนวณจากพื้นที่ของ “Unstable Element” ทั้งก่อนและหลังเลื่อน เทียบกับขนาด viewport
ตัวอย่าง:
- Viewport สูง 1000px
- Element ที่ขยับครอบคลุม 50% ของ viewport ก่อนเลื่อน
- เลื่อนลงไป 25% แล้วกลายเป็นครอบคลุมถึง 75% (จาก 0-75%)
- Impact Fraction = 0.75 (พื้นที่รวม union ของก่อนและหลัง)
Distance Fraction (สัดส่วนระยะทางที่ขยับ)
คำนวณจากระยะที่ Unstable Element เคลื่อนที่ไป (ในหน่วย pixel) หารด้วยความกว้างหรือสูงสุดของ viewport (เลือกตัวที่ใหญ่กว่า)
ตัวอย่าง:
- Element ขยับลง 250px
- Viewport สูง 1000px กว้าง 600px
- Distance Fraction = 250 / 1000 = 0.25
ตัวอย่างการคำนวณจริง
Layout Shift Score = Impact Fraction (0.75) × Distance Fraction (0.25)
= 0.1875
หากในหน้าเดียวกันมี Layout Shift อีก 2 ครั้ง ค่า 0.05 และ 0.02 (รวมอยู่ใน session window เดียวกัน):
CLS = 0.1875 + 0.05 + 0.02 = 0.2575 (Poor)
Session Window — การเปลี่ยนแปลงปี 2021
ก่อนเดือนมิถุนายน 2021 CLS จะรวมทุก Shift ที่เกิดขึ้นตลอดอายุของหน้า (Cumulative แบบบวกตรง) แต่หลังการอัปเดต Google เปลี่ยนเป็น Session Window คือ:
- จัดกลุ่ม Layout Shift ที่เกิดห่างกันไม่เกิน 1 วินาที เป็น “Session”
- Session แต่ละกลุ่มจะไม่เกิน 5 วินาที
- เลือก Session ที่มีคะแนนสูงสุด เป็นค่า CLS ของหน้านั้น
วิธีนี้ยุติธรรมกว่าเดิม — เพราะเว็บที่ผู้ใช้ใช้นานหลายนาที (เช่น Single Page App) จะไม่ถูกลงโทษเพราะมี Shift เล็ก ๆ มากมาย
เกณฑ์ CLS ของ Google ปี 2026
| เกณฑ์ | คะแนน CLS | ความหมาย | ผลต่อ SEO |
|---|---|---|---|
| Good | < 0.1 | ดีเยี่ยม — UX นิ่ง ผู้ใช้ไม่กดผิด | ได้ Boost จาก Page Experience |
| Needs Improvement | 0.1 - 0.25 | พอใช้ — มี Shift เล็กน้อย ควรปรับ | ไม่ได้รับผลกระทบรุนแรง แต่ไม่ได้ Boost |
| Poor | > 0.25 | ไม่ดี — ผู้ใช้รู้สึกกระตุกชัดเจน | ลดอันดับใน SERP โดยเฉพาะมือถือ |
Google ใช้ค่า 75th Percentile ของผู้ใช้ทั่วโลก เป็นเกณฑ์การวัด หมายความว่าหาก 75% ของ Session มีค่า CLS < 0.1 หน้าเว็บคุณจะได้ Good
ในปี 2026 Google เริ่มให้ความสำคัญกับ Mobile CLS มากกว่า Desktop CLS เพราะ Traffic จาก Mobile-First Indexing ครองสัดส่วนมากกว่า 70% ของ search
8 สาเหตุที่ทำให้ CLS สูง
1. รูปภาพไม่ระบุ width / height attributes
นี่เป็นสาเหตุอันดับ 1 ที่พบในเว็บไซต์ส่วนใหญ่ เมื่อ Browser ไม่รู้ขนาดของรูป — มันจะ render เนื้อหาเสริมก่อน พอรูปโหลดเสร็จก็ดันเนื้อหาลง
ตัวอย่างผิด:
<img src="hero-banner.jpg" alt="โรงแรมสมุย">
Browser ทำอย่างไร: รอจน HTTP response มา → อ่าน header → คำนวณขนาด → render แบบ block หรือ inline ตาม CSS → ดันเนื้อหาลง = CLS เกิด
2. โฆษณา / Embed (YouTube, Twitter) ที่ inject เนื้อหา
iframe ของโฆษณา Google AdSense, Facebook Pixel หรือ YouTube embed มักมาในขนาดที่แตกต่างกันตามเนื้อหา — ทำให้ container เปลี่ยนขนาดหลังโหลด
ตัวอย่าง:
<div id="ad-slot-top">
<!-- Ad inject ที่นี่ -->
</div>
ถ้าไม่ reserve space ไว้ก่อน — เมื่อโฆษณามาในขนาด 300x250 จะดันทุกอย่างลง 250px = CLS สูง
3. Font Swap (FOUT / FOIT)
FOUT (Flash of Unstyled Text) — แสดง fallback font ก่อน แล้วเปลี่ยนเป็น custom font เมื่อโหลดเสร็จ FOIT (Flash of Invisible Text) — ซ่อนข้อความไว้จนกว่าฟอนต์จะโหลดเสร็จ
ทั้งสองกรณีทำให้ข้อความมีความสูงและกว้างเปลี่ยนไป เกิด Layout Shift
ตัวอย่าง: Inter (Custom Font) มี x-height ใหญ่กว่า Arial (Fallback) → เมื่อ swap ข้อความจะดันลง 5-10px
4. Dynamic Content Inject Above Viewport
Banner notification, Cookie consent, Promo bar ที่ inject ด้านบนของหน้าหลัง load — ดันทุกอย่างใต้มันลง
// ผิด — inject banner หลัง DOMContentLoaded
document.addEventListener('DOMContentLoaded', () => {
const banner = document.createElement('div');
banner.innerHTML = '<h3>โปรโมชั่นใหม่!</h3>';
document.body.prepend(banner); // ดันทุกอย่างลง = CLS
});
5. CSS โหลดช้า (Late-loading CSS)
หาก Critical CSS ไม่ inline ไว้ใน <head> — Browser จะ render ด้วย default styles ก่อน พอ CSS โหลดเสร็จ Layout จะถูกคำนวณใหม่ทั้งหมด
<head>
<!-- ผิด: CSS load จาก external และไม่มี inline critical -->
<link rel="stylesheet" href="/css/main.css">
</head>
6. Animation ที่ไม่ใช้ transform
การใช้ top, left, width, height, margin ใน animation ทำให้ Browser ต้อง re-layout ทั้งหน้า — ส่งผลให้เกิด Layout Shift
/* ผิด — เปลี่ยน top ทำให้เกิด layout reflow */
@keyframes slide-down {
from { top: -100px; }
to { top: 0; }
}
7. Web Component ที่ render ทีหลัง
Custom Element หรือ Web Component ที่โหลดด้วย JavaScript (เช่น <my-product-card>) — ตอนแรก Browser ไม่รู้ว่ามันคืออะไรและ render เป็น display: inline (height 0) จากนั้นพอ define เสร็จก็เปลี่ยนเป็น block และ render = CLS
8. Cookie Consent Banner ที่ไม่ Fix Position
GDPR Cookie Banner หรือ PDPA Banner ที่ผุดมาด้านบน ถ้าใช้ position: relative หรือ position: static จะดันเนื้อหาลง
ในประเทศไทย PDPA (Personal Data Protection Act) บังคับให้เว็บแสดง Cookie Banner — เพราะฉะนั้นต้องใส่ใจเรื่องนี้เป็นพิเศษ
8 วิธีลด CLS ให้ได้ < 0.1
วิธี 1: ระบุ width และ height attributes ในทุกรูป
Modern Browser ใช้ width/height เป็นการคำนวณ aspect ratio อัตโนมัติ — ไม่จำเป็นต้องกลัวว่าจะกระทบ responsive
ถูกต้อง:
<img
src="hero-banner.jpg"
width="1200"
height="630"
alt="โรงแรมสมุย วิวทะเล"
loading="lazy"
decoding="async"
>
CSS ที่ทำงานคู่กัน:
img {
max-width: 100%;
height: auto; /* Browser คำนวณตาม aspect ratio จาก width/height */
}
ผลลัพธ์: รูปจะสำรองพื้นที่ไว้ก่อนโหลด เนื้อหาที่อยู่ใต้รูปจะไม่ขยับ
วิธี 2: font-display: optional หรือ swap + preload
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-var.woff2') format('woff2-variations');
font-display: optional; /* หรือ swap ถ้าจำเป็นต้องใช้ */
font-weight: 100 900;
}
font-display: optional หมายความว่า: ถ้าฟอนต์ไม่โหลดเสร็จใน 100ms แรก — ใช้ fallback font ไปตลอดและไม่ swap = ไม่มี CLS
preload custom font ใน <head>:
<link
rel="preload"
href="/fonts/inter-var.woff2"
as="font"
type="font/woff2"
crossorigin
>
วิธี 3: Reserve Space สำหรับโฆษณา
/* กำหนดขนาดขั้นต่ำของ ad slot */
.ad-slot {
min-height: 250px;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #f5f5f5;
}
.ad-slot::before {
content: "Advertisement";
color: #999;
font-size: 12px;
}
<div class="ad-slot" data-ad-size="300x250">
<!-- โฆษณาจะมาเติมตรงนี้แต่ไม่เกิน 250px = ไม่มี CLS -->
</div>
วิธี 4: ใช้ CSS aspect-ratio
.video-embed {
aspect-ratio: 16 / 9;
width: 100%;
background: #000;
}
.product-card {
aspect-ratio: 4 / 5;
}
<div class="video-embed">
<iframe
src="https://www.youtube.com/embed/xxxxx"
loading="lazy"
title="วิดีโอสาธิต"
></iframe>
</div>
Browser support ของ aspect-ratio: 95%+ ตั้งแต่ปี 2022 — ใช้ได้ทุก Browser ที่ใช้งานหลัก
วิธี 5: Animation ใช้ transform / opacity เท่านั้น
transform และ opacity ใช้ GPU compositor — ไม่ trigger layout reflow
/* ถูกต้อง — ไม่เกิด CLS */
@keyframes slide-down {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
.notification {
animation: slide-down 300ms ease-out;
/* ใช้ position: fixed ถ้าต้องการให้ลอยเหนือเนื้อหา */
position: fixed;
top: 0;
z-index: 1000;
}
วิธี 6: Inline Critical CSS
<head>
<style>
/* Critical CSS ที่จำเป็นสำหรับ above-the-fold */
body { margin: 0; font-family: system-ui; }
.hero { min-height: 80vh; }
.nav { position: fixed; top: 0; height: 60px; }
main { padding-top: 60px; }
</style>
<!-- โหลด CSS ที่เหลือแบบ async -->
<link
rel="preload"
href="/css/main.css"
as="style"
onload="this.onload=null;this.rel='stylesheet'"
>
</head>
วิธี 7: content-visibility สำหรับ section ใต้ fold
.below-fold-section {
content-visibility: auto;
contain-intrinsic-size: 800px; /* คาดการณ์ขนาด */
}
Browser จะข้าม render section ที่ยังไม่อยู่ใน viewport — แต่ contain-intrinsic-size จะ reserve พื้นที่ไว้ก่อน ไม่ให้เกิด CLS
วิธี 8: Skeleton Screen สำหรับ Dynamic Content
<div class="card-grid">
<div class="card-skeleton" aria-hidden="true">
<div class="skeleton-image"></div>
<div class="skeleton-text"></div>
<div class="skeleton-text short"></div>
</div>
<!-- เนื้อหาจริงจะมาแทนที่ -->
</div>
.card-skeleton {
background: #fff;
padding: 16px;
border-radius: 8px;
}
.skeleton-image {
width: 100%;
aspect-ratio: 16 / 9;
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 4px;
margin-bottom: 12px;
}
.skeleton-text {
height: 16px;
background: #f0f0f0;
border-radius: 4px;
margin-bottom: 8px;
}
.skeleton-text.short {
width: 60%;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
เคสจริง: เว็บโรงแรมสมุย CLS 0.45 → 0.05
เว็บไซต์ของโรงแรมในสมุยที่เราดูแลมี CLS เริ่มต้นที่ 0.45 (Poor) ส่งผลให้ Bounce Rate สูงและจองห้องผ่านเว็บลดลง 30% ในช่วง 3 เดือน หลังจากตรวจสอบและแก้ไขโดยทีมบริการพัฒนาเว็บไซต์ ผลลัพธ์เปลี่ยนไปอย่างชัดเจน
Before vs After
| Metric | Before (มีนาคม) | After (เมษายน) | Improvement |
|---|---|---|---|
| CLS Score | 0.45 (Poor) | 0.05 (Good) | -89% |
| LCP | 4.2s | 2.1s | -50% |
| FID | 180ms | 60ms | -67% |
| Bounce Rate | 68% | 42% | -38% |
| Booking Conversion | 1.8% | 3.4% | +89% |
| Mobile Pageviews | 12,400/เดือน | 19,800/เดือน | +60% |
| Avg. Session Duration | 1:23 | 2:48 | +103% |
สิ่งที่แก้ไข
| ปัญหาที่พบ | วิธีแก้ | ผลต่อ CLS |
|---|---|---|
| Hero image 1920x1080 ไม่มี dimension | เพิ่ม width/height + aspect-ratio CSS | -0.15 |
| Booking widget inject ใต้ Hero | Reserve space ด้วย min-height: 480px | -0.12 |
| Google Font (Prompt) FOUT | ใช้ font-display: optional + preload | -0.08 |
| Cookie banner ดันเนื้อหา | เปลี่ยนเป็น position: fixed bottom | -0.04 |
| Image gallery lazy load แบบไม่ reserve | ใช้ aspect-ratio container | -0.03 |
| YouTube embed virtual tour | ใช้ aspect-ratio + facade pattern | -0.03 |
ใช้เวลารวมในการแก้ไขทั้งหมด 2 สัปดาห์ + รอ Google CrUX (Chrome User Experience Report) update อีก 28 วัน เพื่อให้เห็นผลใน Search Console
หากคุณต้องการบริการแก้ไข Performance แบบเดียวกัน หรือเสริมความสามารถด้วยปลั๊กอินที่เราพัฒนา สามารถติดต่อทีมงานได้ตลอดเวลา
เครื่องมือวัดและตรวจสอบ CLS
1. PageSpeed Insights (Lab + Field Data)
ไปที่ pagespeed.web.dev ใส่ URL ของหน้าที่ต้องการวัด — จะได้ทั้ง:
- Field Data จาก Chrome UX Report (CrUX) — ข้อมูลจริงของผู้ใช้
- Lab Data จาก Lighthouse — ทดสอบในสภาพแวดล้อมจำลอง
จุดเด่น: เห็น CLS แบบ 75th percentile ของผู้ใช้จริง + แนะนำหา Element ที่ทำให้เกิด Shift
2. Lighthouse (DevTools)
เปิด Chrome DevTools → แท็บ Lighthouse → Generate report
- เห็น CLS ปัจจุบัน
- ดู “Avoid large layout shifts” diagnostic
- เห็น Element ตัวร้ายที่ทำให้เกิด Shift
3. Performance Panel + Layout Shift Region
DevTools → Performance → Record → Reload
- ดู “Layout Shifts” track
- เห็น Score แต่ละครั้ง
- กดแล้วเห็น Element ที่ขยับและระยะที่เคลื่อนที่
4. web-vitals.js — เก็บข้อมูลใน Production
import { onCLS, onLCP, onINP, onTTFB, onFCP } from 'web-vitals';
function sendToAnalytics(metric) {
// ส่งไป Google Analytics 4
if (typeof gtag !== 'undefined') {
gtag('event', metric.name, {
value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
metric_id: metric.id,
metric_value: metric.value,
metric_delta: metric.delta,
metric_rating: metric.rating, // good / needs-improvement / poor
});
}
// หรือส่งไป custom endpoint
const body = JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating,
delta: metric.delta,
id: metric.id,
navigationType: metric.navigationType,
url: window.location.href,
});
if (navigator.sendBeacon) {
navigator.sendBeacon('/api/vitals', body);
} else {
fetch('/api/vitals', { body, method: 'POST', keepalive: true });
}
}
onCLS(sendToAnalytics);
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onTTFB(sendToAnalytics);
onFCP(sendToAnalytics);
5. Layoutshift.com / WebPageTest
- WebPageTest (webpagetest.org) — ทดสอบจากหลาย location ทั่วโลก + Video filmstrip
- Layoutshift.com — เครื่องมือเฉพาะทาง วิเคราะห์ Shift แต่ละช่วง
6. PerformanceObserver API (Custom Monitoring)
// เก็บ CLS ทีละ entry ใน console
let cls = 0;
const clsEntries = [];
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// ไม่นับ entry ที่มี hadRecentInput (User เพิ่งกด)
if (!entry.hadRecentInput) {
cls += entry.value;
clsEntries.push(entry);
console.log(`CLS: ${cls.toFixed(4)}`, entry);
}
}
});
observer.observe({ type: 'layout-shift', buffered: true });
// แสดง summary หลัง 5 วินาที
setTimeout(() => {
console.table(clsEntries.map(e => ({
score: e.value.toFixed(4),
sources: e.sources?.length || 0,
time: Math.round(e.startTime),
})));
console.log(`Total CLS: ${cls.toFixed(4)}`);
}, 5000);
5 ข้อผิดพลาดที่พบบ่อยเวลาลด CLS
1. ใช้ CSS height แทน width/height HTML attributes
นักพัฒนาหลายคนคิดว่า “ใส่ height ใน CSS ก็พอ” — ผิด! Browser ใช้ HTML width/height attributes เพื่อ calculate aspect-ratio ตั้งแต่ก่อนที่ CSS จะโหลด
<!-- ผิด -->
<img src="hero.jpg" style="width: 100%; height: auto;" alt="...">
<!-- ถูก -->
<img src="hero.jpg" width="1200" height="630" alt="..."
style="width: 100%; height: auto;">
2. ไม่ใส่ aspect-ratio บน iframe / video
iframe ของ YouTube หรือ Maps มักไม่มี aspect-ratio ในตัว ต้องเพิ่ม CSS เอง
iframe, video {
aspect-ratio: 16 / 9;
width: 100%;
}
3. ใส่ Cookie Consent ใน <body> ตำแหน่งบน
Cookie banner ที่ inject ก่อน main content จะดันทุกอย่างลง
// ผิด — inject banner หลัง DOMContentLoaded
document.body.prepend(banner);
// ถูก — ใช้ position: fixed
banner.style.position = 'fixed';
banner.style.bottom = '0';
banner.style.left = '0';
banner.style.right = '0';
banner.style.zIndex = '9999';
document.body.appendChild(banner);
4. Lazy Load รูปแบบ JavaScript โดยไม่ Reserve Space
<!-- ผิด -->
<img data-src="image.jpg" class="lazy" alt="...">
<!-- ถูก -->
<img
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 630'%3E%3C/svg%3E"
data-src="image.jpg"
width="1200"
height="630"
class="lazy"
alt="..."
>
หรือใช้ native lazy loading:
<img src="image.jpg" loading="lazy" width="1200" height="630" alt="...">
5. Test เฉพาะ Desktop ไม่ Test Mobile
CLS บน Mobile มักสูงกว่า Desktop เพราะ:
- Viewport เล็ก = Distance Fraction สูงกว่า
- Connection ช้ากว่า = Resources โหลดต่างกัน
- มี Touch interaction มากกว่า
ทุกครั้งที่ optimize CLS ต้องทดสอบบน mobile emulator + อุปกรณ์จริง
ถ้าคุณกำลังมองหา infrastructure ที่ช่วยให้รูปภาพและ assets โหลดเร็วทั่วโลก ลองอ่านคู่มือ Cloudflare ฉบับสมบูรณ์ที่เราเขียนไว้ — ช่วยลดทั้ง LCP และ TTFB ที่ส่งผลทางอ้อมต่อ CLS
คำถามที่พบบ่อย
Q1: CLS ของผม 0.12 ผ่าน SEO ไหม?
CLS 0.12 อยู่ในเกณฑ์ “Needs Improvement” — ผ่านแบบเฉียดฉิว แต่ไม่ได้รับ Boost จาก Page Experience Signal Google จะให้ Boost เฉพาะหน้าที่ Core Web Vitals ทุกตัว Pass (Good) เท่านั้น แนะนำให้ลดลงต่ำกว่า 0.1 เพื่อให้เห็นผลทาง SEO ชัดเจน
Q2: ทำไม CLS ใน Lab Data ดีแต่ Field Data แย่?
Lab Data ทดสอบในสภาพแวดล้อมจำลอง — เน็ตเร็ว เครื่องแรง Cache อยู่แล้ว ส่วน Field Data มาจากผู้ใช้จริงที่อาจอยู่บนเน็ตช้า เครื่องเก่า หรือเปิด session ยาวนาน
วิธีแก้: ใช้ web-vitals.js เก็บข้อมูลจริงและดูว่า Element ไหนทำให้เกิด Shift ในผู้ใช้จริง โดยเฉพาะกลุ่ม Mobile + Slow 3G
Q3: ใช้ Single Page App (SPA) มี CLS ไหม?
มี! SPA วัด CLS ตลอด lifetime ของหน้า (session window) แต่ Google วัด Soft Navigation แยกในปี 2024+ — เปลี่ยน route ใน SPA จะเริ่มนับ CLS ใหม่
วิธีทำให้ SPA มี CLS ต่ำ:
- ใช้ Skeleton screen ตอน fetch data
- Reserve space ก่อนเรียก API
- ใช้
<Suspense>(React) หรือ<Awaiting>(Vue) ที่มี fallback ขนาดเท่า content
Q4: Lazy Load รูปทำให้ CLS เพิ่มจริงไหม?
ไม่จริง — ถ้าใส่ width/height attributes ทุกรูป Lazy Loading จะไม่ทำให้ CLS เพิ่ม แต่ถ้าไม่มี dimension แล้วใช้ lazy load — CLS จะกระโดดเมื่อรูปโหลดเสร็จ
Rule: lazy + width/height = OK | lazy + no dimension = CLS
Q5: Animation transform เกิด CLS ไหม?
ไม่เกิด — transform, opacity, filter ทำงานบน Compositor Layer ไม่ trigger Layout Reflow
แต่ระวัง! transform: scale() ใหญ่ ๆ ที่ทำให้ Element “ดูเหมือน” ขยายไปดันเนื้อหา — ผู้ใช้รู้สึกว่ามี Shift แต่ Browser ไม่นับ ทดสอบให้ดีว่า UX ยังโอเค
Q6: CMS เช่น WordPress, Shopify มี CLS สูงเสมอ?
ไม่จำเป็น — ขึ้นอยู่กับ Theme และ Plugin
- WordPress + Twenty Twenty-Four theme = CLS ต่ำได้
- WordPress + Elementor + ad plugins = CLS มักจะสูง
- Shopify ใหม่ (Dawn theme) = ออกแบบมาเพื่อ Core Web Vitals
วิธีแก้: ใช้ theme ที่ optimize แล้ว + จำกัด plugin ที่ inject content และใช้ Critical CSS
Q7: ใส่ Loading Spinner ช่วยลด CLS ได้ไหม?
ช่วยได้ — แต่ต้องใช้ถูกวิธี Spinner ต้อง อยู่ใน container ที่มีขนาดเท่ากับ content จริง เพื่อ Reserve Space
<div class="data-container" style="min-height: 400px;">
<div class="spinner" aria-busy="true">Loading...</div>
<!-- content จริงจะมาแทนที่ -->
</div>
ถ้า spinner เล็กแต่ content จริงสูง 400px = ยังมี CLS
Q8: เปลี่ยน LCP / INP ส่งผลต่อ CLS ไหม?
ส่งผลทางอ้อม — ถ้า INP ช้า ผู้ใช้กดปุ่มแล้วต้องรอ ฟอนต์อาจโหลดเสร็จระหว่างรอ = swap = CLS เกิด
ในทำนองเดียวกัน หาก LCP ช้า เพราะรูป Hero ใหญ่ ระหว่างรอรูป Browser อาจ render ส่วนอื่นไปก่อน พอรูปมาก็ดันทุกอย่าง = CLS เกิด
วิธีแก้: optimize Core Web Vitals ทั้ง 3 ตัวพร้อมกัน — อย่าโฟกัสตัวเดียว
สรุป — CLS ที่ดีคือพื้นฐานของ UX และ SEO ที่ยั่งยืน
CLS เป็นเมตริกที่วัดคุณภาพของ “การออกแบบ” และ “การวางแผน” ของหน้าเว็บ — ไม่ใช่แค่เรื่องของความเร็ว เว็บที่โหลดเร็วแต่กระตุกตลอดเวลาก็ยังเป็น UX ที่แย่
จุดสำคัญที่ต้องจำ:
- เป้าหมาย < 0.1 เพื่อได้ Good และ Boost จาก Google
- ระบุ dimension ทุกรูป — สาเหตุอันดับ 1 ของ CLS
- Reserve space ทุกครั้งที่มี dynamic content — ads, embeds, banners
- font-display: optional + preload สำหรับ custom font
- ใช้ transform + opacity สำหรับ animation
- ทดสอบบน mobile เพราะ Mobile CLS มักสูงกว่า Desktop
- เก็บ Field Data ด้วย web-vitals.js เพื่อรู้ค่าจริงของผู้ใช้
- ปรับ Core Web Vitals ทั้ง 3 ตัวพร้อมกัน — CLS, LCP, INP ส่งผลถึงกัน
การลด CLS ต่ำกว่า 0.1 ไม่ใช่เรื่องยากหากเข้าใจสาเหตุและวิธีแก้ จากเคสจริงของเว็บโรงแรมที่เรานำเสนอ — แค่ 2 สัปดาห์ก็เปลี่ยน CLS จาก 0.45 (Poor) เป็น 0.05 (Good) และเพิ่ม Conversion 89%
หากคุณต้องการความช่วยเหลือในการ Optimize Core Web Vitals หรือพัฒนาเว็บไซต์ที่ผ่านมาตรฐาน SEO ทุกด้าน ทีมงาน Southern Whale พร้อมให้บริการผ่านบริการพัฒนาเว็บไซต์และปลั๊กอินสำหรับเพิ่มประสิทธิภาพ ที่เราพัฒนาขึ้นเอง ติดต่อเราวันนี้เพื่อรับ Performance Audit ฟรี
อย่าลืมอ่านบทความที่เกี่ยวข้อง:
- INP (Interaction to Next Paint) คืออะไร — Core Web Vital ใหม่ปี 2024+
- LCP (Largest Contentful Paint) — วิธี Optimize ให้ < 2.5s
- Cloudflare คู่มือฉบับสมบูรณ์ปี 2026 — CDN, DNS, Workers
ขอให้คุณสนุกกับการลด CLS และเห็นเว็บไซต์ของคุณติดอันดับสูงขึ้นใน Google!