Critical CSS adalah CSS paling sedikit yang dibutuhkan untuk menggambar bagian halaman yang langsung kelihatan waktu dibuka, disebut above the fold (di atas "lipatan", batas bawah layar pertama). CSS itu ditulis langsung di <style> di dalam HTML, dan sisanya dimuat belakangan tanpa menahan render. Bayangin pindahan rumah. Barang untuk malam pertama, seperti sikat gigi dan baju ganti, kamu bawa sendiri di koper kecil. Sisanya diangkut truk yang baru datang besok. Kamu bisa langsung tidur malam itu tanpa menunggu truk. Koper kecil itu CSS kritis, truknya styles.css.
🧪 Tebakan cepat: di halaman contoh,
styles.css(120 KB) menahan render sampai 1.200 ms. Kalau kamu meng-inline CSS header dan hero ke<style>, tapi<link rel="stylesheet">-nya masih biasa, first paint jadi berapa: 350 ms, 800 ms, atau tetap 1.250 ms? Jawabannya ada di bagian "Dua langkah, bukan satu".
Kenapa CSS menahan render
Di pelajaran Critical Rendering Path kamu sudah tahu: <link rel="stylesheet"> itu render-blocking. Browser gak mau menggambar halaman sebelum semua CSS-nya datang, supaya halaman gak tampil polos lalu tiba-tiba berubah bentuk. Masalahnya, styles.css biasanya berisi style untuk seluruh situs: footer, modal, halaman lain. Layar pertama cuma butuh sebagian kecilnya.
Halaman contoh di Lab, toko kopi dengan header, hero, dan daftar produk (angka simulasi, jaringan HP yang lambat):
index.html8 KB, selesai di 300 ms.styles.css120 KB, di-download dari 100 ms sampai 1.200 ms.- CSS yang dibutuhkan header dan hero cuma 6 KB: header 2 KB, hero 4 KB.
- Setelah semua yang ditunggu siap, browser butuh 50 ms untuk menggambar.
Dua langkah, bukan satu
| Cara | First paint | Header dan hero di first paint |
|---|---|---|
| link biasa, tanpa CSS kritis | 1.250 ms | rapi |
CSS kritis di <style>, link masih biasa |
1.250 ms | rapi |
| link ditunda, tanpa CSS kritis | 350 ms | polos, lalu loncat di 1.250 ms |
CSS kritis di <style> dan link ditunda |
350 ms | rapi |
Itu jawaban tebakannya: tetap 1.250 ms. Selama <link rel="stylesheet"> masih biasa, browser tetap menunggu styles.css, berapa pun CSS yang sudah di-inline. Sebaliknya, menunda link tanpa CSS kritis bikin halaman tampil polos lalu meloncat waktu styles.css datang. Loncatan ini disebut FOUC (flash of unstyled content), dan pergeserannya dihitung CLS. Critical CSS butuh dua langkah sekaligus: inline yang kritis, lalu tunda sisanya.
Kode: CSS kritis, lalu sisanya ditunda
<head>
<style>
/* CSS kritis: cuma header dan hero, 6 KB */
body { margin: 0; font-family: system-ui, sans-serif; }
.header { display: flex; height: 56px; padding: 0 16px; background: #1e293b; color: #fff; }
.hero { padding: 48px 16px; text-align: center; background: #fef3c7; }
</style>
<!-- Sisanya: di-download tanpa menahan render -->
<link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
</head>
<style>di<head>berisi aturan untuk elemen di layar pertama saja. Browser bisa langsung memakainya, gak perlu request tambahan.media="print"bilang stylesheet ini untuk dicetak, jadi gak menahan tampilan di layar. Begitu selesai di-download,onload="this.media='all'"mengubahnya jadialldan style-nya berlaku.<noscript>adalah cadangan untuk pengunjung yang mematikan JavaScript. Tanpa JavaScript,onloadgak pernah jalan, jadi tanpa<noscript>CSS-nya gak pernah berlaku di layar.
Cara kedua yang sama-sama non-blocking, pakai salah satu saja:
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>
rel="preload" as="style"men-download CSS dengan prioritas tinggi tanpa memakainya.onloadmengubahnya jadirel='stylesheet'begitu selesai.this.onload=nullmencegahonloadjalan dua kali, karena di beberapa browser menggantirelmemicuonloadlagi.<link>gak punya atributasyncataudefer. Kalau ditulis, browser mengabaikannya dan CSS-nya tetap menahan render.
Apa yang masuk CSS kritis
- Semua yang terlihat di layar pertama: header, navigasi, hero (judul, gambar, tombol), banner cookie yang langsung muncul, dan
@font-facefont yang dipakai di situ. - Bukan untuk: footer, modal yang baru muncul setelah diklik, bagian di bawah lipatan, halaman lain.
- Lipatannya beda di HP dan laptop. Ambil CSS kritis untuk beberapa ukuran layar sekaligus.
Jangan memilihnya dengan tangan. Tool critical (npm) membuka halaman di browser tanpa tampilan (headless) pada ukuran layar tertentu, lalu mengambil CSS yang dipakai elemen di atas lipatan. Beasties (penerus Critters) bekerja saat build: membaca HTML hasil build, meng-inline CSS yang dipakai HTML itu, dan memuat sisanya tanpa menahan render.
Untung ruginya
- Untung: first paint jauh lebih cepat. Di contoh ini dari 1.250 ms jadi 350 ms.
- Jaga di bawah sekitar 14 KB. Kiriman pertama server biasanya cuma sekitar 14 KB. HTML 8 KB + CSS kritis 6 KB = 14 KB, pas. Kalau CSS produk (30 KB) ikut di-inline, HTML jadi 44 KB, butuh kiriman tambahan, dan di Lab first paint mundur ke 650 ms.
- Gak di-cache terpisah. CSS inline ikut di setiap halaman HTML, jadi di-download ulang tiap pindah halaman.
styles.csscukup sekali, lalu diambil dari cache. - Aturannya dobel. Aturan header dan hero ada di
<style>dan distyles.css. Biarkan tool build yang menyalinnya, supaya keduanya gak beda.
⚠️ Jebakan yang sering ketemu
- Inline CSS kritis tapi link masih biasa. First paint gak berubah sama sekali, karena link biasa tetap menahan render.
- Ada elemen di layar pertama yang kelupaan. Elemen itu tampil polos lalu loncat (FOUC), dan pergeserannya menambah CLS.
- Meng-inline semua CSS. HTML membengkak lewat 14 KB, gak bisa di-cache, dan first paint malah lebih lambat.
- Menulis
asyncataudeferdi<link>. Atribut itu gak ada untuk<link>. Pakaimedia="print"denganonload, ataurel="preload" as="style"denganonload.
TL;DR: Critical CSS adalah CSS minimum untuk menggambar konten above the fold. Taruh CSS itu di <style> di <head>, lalu muat sisanya tanpa menahan render: <link rel="stylesheet" media="print" onload="this.media='all'"> atau <link rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">, ditambah <noscript> sebagai cadangan. Dua langkah itu harus bareng: inline saja gak mengubah first paint (tetap 1.250 ms), tunda saja bikin FOUC. Di contoh ini keduanya menurunkan first paint dari 1.250 ms ke 350 ms. Jaga CSS kritis kecil, HTML plus CSS kritis sekitar 14 KB, dan ekstrak pakai tool seperti critical atau Beasties.