7 คะแนน โดย GN⁺ 2025-05-15 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Critical CSS คือการดึงเฉพาะ CSS ขั้นต่ำที่จำเป็นต่อการเรนเดอร์ “ส่วนที่มองเห็นได้ทันทีเมื่อเปิดหน้าเว็บ (above the fold)” เท่านั้น และเมื่อนำไปใส่แบบ inline ใน HTML จะช่วยปรับปรุง Core Web Vitals เช่น FCP (First Contentful Paint) ได้
  • ใส่แบบ inline ใน <head> ของ HTML เพื่อให้เบราว์เซอร์เรนเดอร์คอนเทนต์ได้เร็วโดยไม่ต้องรอ stylesheet ทั้งหมด
  • มีข้อดี เช่น ความเร็วในการโหลดที่ผู้ใช้รับรู้ได้ดีขึ้น, คะแนน Lighthouse สูงขึ้น, และ SEO กับ UX ดีขึ้น
  • CSS ที่ไม่จำเป็นต่อการแสดงผลแรกสามารถโหลดด้วย <link> ที่ท้าย <body> หรือ โหลดแบบหน่วงเวลาด้วย JavaScript เพื่อเพิ่มประสิทธิภาพได้อีก
  • ควรทราบว่าผู้ใช้ต้องปรับพาธของลิงก์ CSS และการอ้างอิง asset ด้วยตนเอง

Critical CSS Generator

  • Critical CSS Generator เป็นเครื่องมือที่ช่วยดึงเฉพาะโค้ด CSS ขั้นต่ำที่จำเป็นจริง ๆ จากหน้าเว็บ ทำให้สามารถแยก CSS ได้อย่างเหมาะกับวัตถุประสงค์การใช้งาน
  • Critical CSS คือ กฎ CSS ขั้นต่ำที่จำเป็นสำหรับจัดสไตล์ส่วนที่มองเห็นได้ก่อนในหน้าเว็บ
  • วิธีนี้ช่วยให้เบราว์เซอร์แสดงคอนเทนต์หลักได้ทันทีโดยไม่ต้องรอโหลด stylesheet ทั้งหมด จึงช่วยด้านประสิทธิภาพและปรับปรุง Core Web Vitals (เช่น FCP)

ทำไมจึงควรใช้?

  • ความเร็วการโหลดเริ่มต้นที่รู้สึกได้ว่าเร็วขึ้น
  • คะแนน Lighthouse ดีขึ้น
  • ปรับปรุง SEO และประสบการณ์ผู้ใช้

🔧 วิธีนำไปใช้

Step 1: ทำ Critical CSS เป็น inline

  • แทรก Critical CSS ภายในแท็ก <style> และวางไว้ด้านบนสุดของ <head> ใน HTML
  • ต้องวางก่อน stylesheet หรือสคริปต์อื่น ๆ
  • พาธ asset ภายในอาจต้องแก้ไขตามความเหมาะสม
    <style>  
      /* Critical CSS for your page */  
      /* ... CSS content ... */  
    </style>  
    

Step 2: โหลด CSS ที่ไม่จำเป็นแบบหน่วงเวลา (วิธีพื้นฐาน)

  • นำแท็ก <link> เดิมออกจาก <head> แล้ว ย้ายไปไว้ก่อน </body> ทันที
  • วิธีนี้ทำให้การเรนเดอร์เริ่มต้นใช้เฉพาะ Critical CSS ส่วน CSS ที่ไม่จำเป็นจะโหลดภายหลัง
    <html>  
      ...  
      <body>  
        ...  
        <link rel="stylesheet" href="/css/vendors.min.css">  
        <link rel="stylesheet" href="/css/style.min.css">  
      </body>  
    </html>  
    

Step 3 (ตัวเลือก): โหลดสไตล์แบบอะซิงโครนัสด้วย JavaScript

  • หลังหน้าเว็บโหลดเสร็จ ให้ใช้ JavaScript เพื่อ โหลด CSS ที่ไม่จำเป็นแบบไดนามิก
  • อาจช่วยเพิ่มประสิทธิภาพได้เมื่อความเร็วเครือข่ายต่ำ
  • ต้องลบ <link> ของ CSS ที่ไม่จำเป็นทั้งหมดออกจาก <head> เดิม
    window.addEventListener("DOMContentLoaded", function () {  
      console.log("✅ Page loaded, now loading non-critical stylesheets...");  
      let stylesheets = [  
        // "/css/vendors.min.css",  
        // "/css/style.min.css",  
      ];  
      let loadedCount = 0;  
      function checkAllStylesLoaded() {  
        loadedCount++;  
        if (loadedCount === stylesheets.length) {  
          console.log("✅ All non-critical stylesheets loaded...");  
        }  
      }  
      stylesheets.forEach(function (href) {  
        var link = document.createElement("link");  
        link.rel = "stylesheet";  
        link.href = href;  
        link.onload = checkAllStylesLoaded;  
        link.onerror = () => console.warn(`Failed to load stylesheet: ${href}`);  
        document.head.appendChild(link);  
      });  
    });  
    

1 ความคิดเห็น

 
GN⁺ 2025-05-15
ความคิดเห็นบน Hacker News
  • ถ้ารองรับ responsive ได้ด้วยก็น่าจะยอดเยี่ยม เพราะที่ผ่านมา dedupe สไตล์แบบ critical สำหรับ responsive ทำได้ยาก เลยสุดท้ายต้องมานั่งแก้ stylesheet เองอยู่เรื่อย ๆ และในเมื่อขนาดของ critical CSS สำคัญ ก็น่าจะดีถ้ามีตัวเลือก down-compile ของอย่าง CSS variables ด้วย อีกอย่างไม่แนะนำคำแนะนำที่ให้วางแท็ก <link> ของ non-critical CSS ไว้ก่อน </body> เพราะ CSS ควรถูกดึงมาให้เร็ว การทำแบบนี้จะทำให้การค้นพบ CSS ช้าลงและดาวน์โหลดช้าตามไปด้วย แนะนำให้ใช้วิธีผสมระหว่าง preload กับ noscript แทน <link rel="preload" href="styles.css" as="style" onload="this.rel='stylesheet'"> <noscript><link rel="stylesheet" href="styles.css"></noscript>

    • สงสัยว่าวิธีใช้โค้ด JS ใน preload แบบนี้จะโดนบล็อกไหม ถ้า CSP ไม่อนุญาต unsafe-inline

    • ไม่อยากใช้วิธีโหลด CSS ด้วย JS hack เพราะตอนนำ stylesheet ไปใช้ อาจเกิดการคำนวณ layout/style ใหม่ทั้งหน้าได้ เบราว์เซอร์เองก็ดึง stylesheet ได้เร็วอยู่แล้วแม้อยู่ล่างหน้า

    • ใช้แค่ prefetch attribute, HTTP header hints และ CDN ก็ได้ผลใกล้เคียงกันแล้ว ไม่จำเป็นต้อง rebuild critical CSS อยู่ตลอด ถ้าใช้ CDN อย่าง CF ให้ถูกต้องก็เร็วมาก

    • น่าจะพูดถูก มีแผนจะใส่ตัวเลือกนี้เหมือนกัน แทนที่จะใช้แบบ 'before body' เคยลองตัวเลือก 'DOMCONTENTLOADED' แล้ว พบว่าแม้บนมือถือเก่า ๆ หรือเครือข่ายช้า ก็ยังทำงานได้ดีพอทั้งต่อ UX และ Lighthouse

    • เห็นด้วยอย่างมากเรื่องรองรับ responsive

  • สำหรับผม นี่ดูเป็นการ optimize เร็วเกินไปหน่อย น่าจะมีคุณค่าก็ต่อเมื่อ CSS ซับซ้อนมากหรือมี resource ที่ต้องโหลดเยอะ แต่ในสถานการณ์ส่วนใหญ่ การเขียน CSS, HTML, JS ให้สะอาดน่าจะมีประสิทธิภาพกว่า และวิธีนี้อาจไม่จำเป็นหรืออาจให้ผลเสียด้วยซ้ำ

    • มีประโยชน์มาก ผมทำเว็บ WordPress แบบฟรีแลนซ์บ่อย และมักเจอเคสที่ CSS/JS เละเทะมากเพราะผ่านมือนักพัฒนาหรือเอเจนซีหลายเจ้า อยากลองใช้เครื่องมือแบบนี้จริง ๆ

    • ยิ่ง CSS ซับซ้อนหรือมี resource เยอะ ผลบวกสุทธิของ optimization แบบนี้กลับยิ่งน้อยลง เพราะสิ่งที่เล็งแก้คือ RTT latency แต่ยิ่ง critical CSS ใหญ่ ต้นทุนของ optimization ก็ยิ่งสูง ทำให้ประโยชน์สุทธิลดลง

    • ถ้าเป็นเมื่อ 12 ปีก่อน ผมน่าจะยอมจ่ายเงินให้เครื่องมือแบบนี้ เพราะตอนนั้นมี CSS ปริมาณมหาศาลที่สะสมมาหลายปี และยากมากที่จะรู้ว่ากฎไหนเป็น critical

    • หลายเว็บไซต์อาจถือว่าเป็นการ optimize เร็วเกินไปจริง แต่สำหรับเว็บประเภทข่าว/สื่อที่ไวต่อจำนวนคลิก การโหลดหน้าแบบ “ทันที” สำคัญมาก แค่เกิน 1 วินาที อัตราการหลุดออกและรายได้โฆษณาก็ลดลงแล้ว HuffPost เองก็เคยลอง optimization แบบนี้ตั้งแต่ 10 ปีก่อน

    • พอมองสภาพปัจจุบันของการพัฒนา frontend แล้วรู้สึกว่ามันเกินไปจริง ๆ เครื่องมืออย่าง Lighthouse ทำให้คนหมกมุ่นกับการ optimize เพื่อคะแนนที่ไม่มีความหมาย ผลคือความซับซ้อนของ build เพิ่มขึ้น แต่ผู้ใช้จริงแทบไม่รู้สึกอะไร แถมพัฒนายากขึ้นอีก ทั้งที่ระหว่างนั้นก็ยังเห็นเว็บที่พลาดเรื่องพื้นฐานอย่าง UI/การจัดการ state อยู่เต็มไปหมด น่าอึดอัดมาก

    • CSS, HTML, JS ที่สะอาดคือคำตอบจริง แต่บางทีก็ต้องรับช่วงโปรเจกต์ที่เละหรือใช้เทมเพลต และต่อให้พัฒนาเอง บางครั้งสถาปัตยกรรมก็อาจพันกันได้

    • สำหรับผม วิธีโหลด CSS เป็นสิ่งที่ต้องคิดตั้งแต่ขั้นแรกของการพัฒนา เราเคยเสียลูกค้าไปเยอะเพราะเว็บมี page speed test score ต่ำ ประสิทธิภาพมีผลกับ SEO เลยสำคัญมาก ผมถึงกับออกแบบ optimization ของหน้าใหม่ทั้งหมดเพื่อให้ Google Lighthouse ได้ 100 คะแนน ต้องวางแผนตั้งแต่ต้นทั้งลำดับและวิธีโหลด CSS/JS เพื่อจะได้ไม่ต้องมานั่งแก้ทีหลัง เราแยก CSS ส่วนเหนือ/ใต้ fold แล้ว inline ให้ตรงจุด และ JS ใต้ fold จะไม่ถูก evaluate เลยจนกว่าจะมีการ scroll เราทำตามทุกอย่างที่ Lighthouse แนะนำ ระบบก่อนหน้านี้ใส่ CSS ทั้งเว็บทุกหน้า (3~4MB) ส่วน JS หนักกว่านั้นอีก เพราะไม่ได้วางแผน optimization ตั้งแต่แรก ตอนนี้ยังใช้ระบบนั้นอยู่เลยบอกชื่อไม่ได้ แต่ภายในก็ยังเป็นปัญหาอยู่เรื่อย ๆ ถ้าเป้าหมายคือ performance ผมไม่คิดว่ามีคำว่า optimize เร็วเกินไป ต้องคิดทุกอย่างตั้งแต่แรก ผลลัพธ์คือได้ performance 100 คะแนนกับทุก client รวมถึงมือถือ และยังเหนือกว่าคู่แข่ง พอลองใช้เครื่องมือนี้กับเว็บตัวเองก็แทบไม่มีอะไรให้ optimize เพิ่มแล้ว เลยไม่เห็นผล

  • สำหรับหน้าเว็บที่ผมทำด้วย Astro, HTML มี 27.52KB (บีบอัดแล้ว 6.1KB), JS ต่ำกว่า 10KB, critical CSS 57KB (บีบอัดแล้ว 7KB) ส่วนเว็บคล้ายกันบางแห่งอยู่ที่ 100KB~1MB ถ้าทำให้สะอาด resource hints อย่างเดียวก็เร็วพอโดยไม่ต้อง inline css/js ถ้าใช้ nginx+HTTP/2+edge cache ก็ทำ performance 100/100 ได้โดยไม่ต้องมี critical CSS/inline js ผมสงสัยว่าการเพิ่ม 7KB ทุกหน้ามันไม่ค่อยคุ้ม ในเชิง implementation แล้ว SPA/edge caching เป็นมิตรต่อสิ่งแวดล้อมกว่าและเร็วกว่า ไม่จำเป็นต้องส่ง HTML ที่หนักมากแบบ Elementor โดยเฉพาะเมื่อแบตมือถือมีจำกัด ก็ไม่มีเหตุผลจะต้องส่งข้อมูลที่ไม่จำเป็นด้วย

    • เป็นทริกที่ดี แต่ในสถานการณ์ที่ CDN และ HTTP/2 แพร่หลายอยู่แล้ว optimization แบบนี้สุดท้ายก็เปลืองแค่ bandwidth ปรับตัวเลข benchmark ได้นิดหน่อย และในโลกจริงก็เร็วขึ้นแค่ราว 10~20ms เท่านั้น

    • การใส่ critical CSS ในทุกหน้าไม่ใช่คำตอบเสมอไป วิธีเลี่ยง data bloat ที่ไม่จำเป็นคือใช้แบบ selective เฉพาะ first visit (ตอนยังไม่มี cache) หรือหน้าเริ่มต้นของ session เท่านั้น

  • เพราะลูกค้าร้องขอเลยไปหาเครื่องมือสำหรับ extract critical CSS แต่ไม่เจอฟังก์ชันที่ต้องการ สุดท้ายเลยมาแชร์โซลูชันที่ทำเองด้วย Puppeteer และเครื่องมือของตัวเอง สามารถกำหนดได้ว่าจะรอหลังโหลดหน้าเท่าไร เคยใช้บริการเสียเงินด้วยแต่ไม่ถูกใจเลยขอคืนเงิน ตอนนี้เปิดให้ใช้ฟรีและยินดีรับ feedback

    • สงสัยว่ามีปัญหากับเครื่องมือเดิมอย่างแพ็กเกจ penthouse หรือเปล่า

    • ถ้าใส่เว็บไซต์ที่ไม่มี CSS จะเกิด error

    • โค้ดเปิดให้ดูหรือเปล่า อยากใช้เป็นปลั๊กอิน Vite/Astro ด้วย

    • อยากถามว่านี่คือเวอร์ชัน UI ของ penthouse หรือเปล่า เพราะค่าตั้งหลายอย่างคล้ายกันมาก

  • วิธีนี้กลับให้ผลตรงข้ามมากกว่า เพราะทำให้เกิด FOUC (หน้าแวบแบบยังไม่ลงสไตล์) อย่างสม่ำเสมอ ถ้า layout เปลี่ยนกลางคัน ผู้ใช้ที่กำลังกดอะไรอยู่แล้วอาจเจอปัญหาใหญ่ นี่ไม่ใช่แค่เรื่องความสวยงาม แต่เป็นปัญหาด้าน usability จริง ๆ

    • ผมเองก็ปรับสไตล์บางส่วนหลังใช้วิธีนี้ แต่สุดท้ายก็ optimize ให้ CLS (cumulative layout shift) เป็น 0 ได้อยู่ดี ถ้างบน้อยและใช้เทมเพลตที่มีไลบรารีเยอะ มันมีประโยชน์มาก

    • เป้าหมายตั้งแต่แรกไม่ใช่การหลีกเลี่ยง FOUC โดยไม่ block CSS network request หรอกหรือ

  • วิธีนี้มีความหมายมากขึ้นเมื่อสมมติว่าการเปิดดูหน้าครั้งแรกไม่มี CSS cache เลย แต่ในความเป็นจริงก็มี trade-off จากหลายปัจจัย เช่น สัดส่วนผู้ใช้ใหม่/ผู้ใช้กลับมา, การตั้งค่า CSS cache, CDN, 103 early hints, critical css/initial congestion window เป็นต้น

    • ใช่ ใช้เฉพาะตอนเข้าครั้งแรก และไม่ถึงกับเป็นวิธีที่แนะนำอย่างจริงจังนัก มันคือ trade-off มากกว่า วิธีที่ดีที่สุดคือเขียนโค้ดและสไตล์ทุกอย่างเอง และลดการใช้ไลบรารี
  • ตอนวัด performance บน localhost แทบไม่เห็นผลของ CSS เลย ต่อให้เอา CSS ออกทั้งหมดก็เร็วขึ้นไม่ถึง 7ms และยังอยู่ในช่วงความคลาดเคลื่อนของการวัดด้วย

    • optimization ด้าน client-server latency ย่อมไม่มีความหมายอยู่แล้วในสภาพแวดล้อม latency ต่ำอย่าง localhost ผมไม่ได้บอกว่าต้องทำ optimization นี้เสมอไป แต่การทดสอบบน localhost ก็ไม่ใช่ benchmark ที่ดีนัก
  • พอใช้เครื่องมือนี้กับเว็บผม ก็พบว่ามัน extract แม้กระทั่งองค์ประกอบสำหรับ debugging ที่ไม่จำเป็นจริง ๆ ลงไปใน CSS ด้วย เช่น body::after สำหรับ grid overlay ของเว็บก็ถูกใส่มาด้วยเฉย ๆ (ลืมไปแล้วด้วยซ้ำว่าเคยมี เลยมาพบเพราะอันนี้)

  • ผมชอบแนวทางเขียน HTML ที่สื่อความหมายได้ดีแม้ไม่มี CSS เพราะแบบนี้จะช่วยป้องกันไม่ให้โครงสร้างเอกสารซับซ้อนเกินไปตั้งแต่ต้น

    • แต่ก็ใช้ไม่ได้กับทุกเว็บไซต์ เช่น UI หลายแบบไม่ได้มีการอ่านจากซ้าย→ขวา บน→ล่างเป็นพื้นฐาน
  • ไอเดียสดใหม่ดี เลยลองใช้กับเว็บไซต์ส่วนตัว แต่เจอ error ว่า CSS ตกหล่นจากไลบรารี penthouse {"error":true,"name":"Error","message":"css should not be empty" ...}

    • เคสนี้จะลองตรวจสอบดูเหมือนกัน ขอบคุณ