Selama section ini kita membedah mesin di balik halaman: parsing, DOM, dan alur pengiriman form. Chapter penutup ini berangkat dari pertanyaan yang lebih besar: bagaimana memastikan halaman yang kita bangun tetap bekerja untuk semua pengunjung, di perangkat apa pun, dalam kondisi jaringan apa pun. Jawabannya adalah prinsip yang selama ini diam-diam kita terapkan di contoh course: progressive enhancement.
Definisi Progressive Enhancement #
Progressive enhancement adalah strategi menyusun halaman berlapis: fondasi HTML dibangun agar berfungsi untuk semua browser dan semua kondisi, lalu lapisan CSS dan JavaScript ditambahkan untuk memperkaya pengalaman bila tersedia. Fitur inti — membaca konten, mengirim form, membuka tautan — tidak boleh bergantung pada lapisan tambahan tersebut. Bila lapisan itu gagal dimuat atau tidak didukung, halaman tetap bekerja dengan fungsi dasarnya.
Lapisan CSS dan JavaScript dipandang sebagai penambah (enhancement), bukan syarat berjalannya fitur; karena itu pekerjaan dimulai dari HTML yang berdiri sendiri.
Praktik yang Kita Terapkan Sejak Awal #
Beberapa kebiasaan dari section sebelumnya ternyata progressive enhancement dalam bentuk paling murni:
- Form tetap terkirim tanpa JavaScript: setiap form contoh kita memakai
actiondanmethoddengan validasi native; tanpa JavaScript, data tetap sampai dan pemeriksaan server tetap menjaga keabsahannya. detailstanpa satu baris skrip: element dari section Interactive Elements membuka dan menutup konten murni dengan HTML.- Link sungguhan, bukan
divdenganonclick:a hrefdapat dibuka di tab baru, dibookmark, dibaca crawler, dan diumumkan screen reader dengan benar. - Validasi native sebelum skrip custom: pemeriksaan bawaan browser bekerja bahkan sebelum JavaScript selesai diunduh.
Tiga Lapis pada Satu Fitur #
Ambil fitur langganan kabar buku yang dikelola Budi. Lapisan pertamanya adalah file contoh pada chapter ini — halaman yang berdiri sendiri tanpa CSS dan JavaScript:
<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Langganan Kabar Buku Baru</title>
</head>
<body>
<h1>Langganan Kabar Buku Baru</h1>
<form action="/langganan" method="post">
<p>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</p>
<p>
<input type="submit" value="Langganan">
</p>
</form>
<details>
<summary>Kenapa kami meminta email?</summary>
<p>Email dipakai untuk mengirim kabar buku baru satu kali per pekan.</p>
</details>
</body>
</html>Output yang Dihasilkan:
Jendela browser menampilkan:
- Form langganan yang berfungsi penuh: kolom email wajib diisi,
submit mengirim data ke /langganan
- Butir "Kenapa kami meminta email?" yang membuka penjelasan saat diklik,
tanpa satu baris JavaScript punBerikut peran setiap bagian fondasi tersebut:
- Baris 10 (
<form action="/langganan" method="post">): jalur pengiriman bawaan; bila JavaScript gagal dimuat, data tetap terkirim melalui navigasi biasa. - Baris 13 (
required): validasi native menjaga kolom email tanpa skrip apa pun. - Baris 16 (tombol submit): satu-satunya kontrol pengiriman; jalurnya diatur platform, bukan skrip.
- Baris 19-22 (
details): interaksi buka-tutup yang diurus browser; konten di dalamnya tetap terbaca screen reader dan crawler. - Baris 21 (penjelasan email): konten bantuan tetap tersedia di fondasi, bukan disembunyikan di balik skrip.
Lapisan kedua, CSS, mengurus tampilan tanpa mengubah perilaku sama sekali:
form { max-width: 24rem; }
input:invalid { border: 2px solid #b91c1c; }Lapisan ketiga, JavaScript, menambah kenyamanan: mencegat submit, mengirim data dengan fetch, lalu menampilkan pesan tanpa navigasi:
const form = document.querySelector("form");
if (form) {
form.addEventListener("submit", async (event) => {
event.preventDefault();
const response = await fetch(form.action, {
method: "POST",
body: new FormData(form)
});
if (response.ok) {
form.textContent = "Terima kasih, langganan tercatat.";
}
});
}Perhatikan dua penjaga pada skrip tersebut: pemeriksaan if (form) membuat skrip berhenti dengan aman bila element form tidak ada, dan form.action dibaca dari markup alih-alih ditulis ulang, sehingga sumber kebenaran tetap pada HTML. Bila skrip gagal dimuat, form kembali ke jalur bawaan: submit penuh dengan navigasi. Itulah pola progressive enhancement — JavaScript memperkaya jalur yang telah bekerja, bukan menggantikannya.
Kontras dengan Graceful Degradation #
Istilah yang perlu dibedakan adalah graceful degradation: arah kerjanya kebalikan — pengalaman penuh dibangun dahulu untuk browser modern, lalu jalur penurunan disiapkan untuk yang lawas. Progressive enhancement bergerak dari dasar ke atas; graceful degradation bergerak dari atas ke dasar. Keduanya dapat berujung pada halaman yang serupa, tetapi titik awal perencanaannya berbeda.
Manfaat yang Nyata #
Strategi ini bukan sekadar kerapian teori; manfaatnya terasa langsung:
- Aksesibilitas: screen reader dan navigasi keyboard bekerja pada fondasi HTML semantik, tanpa menunggu skrip.
- SEO: crawler membaca HTML; konten di fondasi terindeks tanpa perlu mengeksekusi JavaScript.
- Perangkat dan browser lawas: fitur inti tetap hidup di lingkungan yang tidak mendukung API terbaru.
- Jaringan buruk: HTML yang tiba lebih dulu langsung dapat dipakai, tanpa menunggu CSS dan JavaScript selesai.
- Pemeliharaan: lapisan yang terpisah membuat sumber masalah lebih mudah dilacak.
Dengan chapter ini, section Browser dan Web Platform tertutup utuh: dari byte yang tiba, token, DOM, alat pemeriksaan, hingga prinsip yang menjaga semuanya tetap bekerja. Bekal tersebut membawa kita ke urutan berikutnya — section Performance dan Optimasi — yang kini dapat berfokus pada sisa pertanyaan: bagaimana membuat halaman yang bekerja itu tampil dengan cepat.
Referensi resmi untuk pendalaman:
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
contoh-progressive.html
Unduh berkas<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Langganan Kabar Buku Baru</title>
</head>
<body>
<h1>Langganan Kabar Buku Baru</h1>
<form action="/langganan" method="post">
<p>
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</p>
<p>
<input type="submit" value="Langganan">
</p>
</form>
<details>
<summary>Kenapa kami meminta email?</summary>
<p>Email dipakai untuk mengirim kabar buku baru satu kali per pekan.</p>
</details>
</body>
</html>