Selamat Datang
di
WebLab
Kursus interaktif untuk memahami HTML, CSS, dan JavaScript di level menengah — cocok untuk kamu yang sudah tahu dasarnya, tapi belum paham kenapa-nya.
Elemen Semantik
Tag HTML bukan sekadar pembungkus teks. Tiap tag memberi makna pada konten — kepada browser, mesin pencari, dan screen reader.
Apa itu Semantik?
"Semantik" artinya makna. HTML semantik berarti kita memilih tag yang tepat secara makna, bukan hanya yang "kelihatannya benar".
Contoh:
<div>
tidak punya makna — dia hanya kotak. Tapi
<nav>
jelas menunjukkan: "ini area navigasi."
Bayangkan gedung kantor. Semua ruangan bisa disebut "ruang". Tapi ada yang namanya Lobby, Ruang Rapat, Dapur, Toilet. Nama-nama itu bukan dekorasi — mereka memberi tahu fungsi ruangan. HTML semantik seperti itu.
<!-- ❌ Tidak Semantik --> <div class="header"> <div class="nav"> <div>Beranda</div> </div> </div> <!-- ✅ Semantik --> <header> <nav> <a href="/">Beranda</a> </nav> </header>
Tag Semantik yang Wajib Kamu Tahu
<header> — Kepala halaman atau seksi.
<nav> — Menu navigasi.
<main> — Konten utama halaman (hanya satu
per halaman).
<article> — Konten independen (artikel,
posting).
<section> — Pengelompokan konten bertema.
<aside> — Konten sampingan (sidebar,
catatan).
<footer> — Kaki halaman.
🧪 Coba Sendiri
Ubah struktur HTML di bawah ini. Coba ganti
<div>
menjadi tag semantik yang tepat, lalu klik
Jalankan.
⚡ Tantangan
Buat struktur halaman lengkap yang berisi:
- Header dengan navigasi (3 link)
- Main dengan satu article berisi judul & 2 paragraf
- Aside dengan teks "Artikel Terkait"
- Footer dengan nama kamu
Form & Input
Form adalah cara pengguna berkomunikasi dengan website. Membuatnya dengan benar bukan hanya soal tampilan, tapi juga aksesibilitas dan pengalaman pengguna.
Anatomi Form HTML
Setiap form yang baik terdiri dari:
<form> sebagai wadah,
<label> sebagai keterangan input, dan
<input> atau elemen input lainnya. Label
yang terhubung ke input (via atribut
for
dan
id) membuat form bisa diklik dan mudah digunakan di screen reader.
<form action="/kirim" method="post"> <!-- Label + Input harus terhubung via for & id --> <label for="nama">Nama Lengkap</label> <input type="text" id="nama" name="nama" placeholder="Masukkan nama..." required> <label for="pesan">Pesan</label> <textarea id="pesan" name="pesan" rows="4"></textarea> <button type="submit">Kirim</button> </form>
Tipe Input yang Sering Dipakai
type="text" — Teks bebas.
type="email" — Email (otomatis validasi format).
type="number" — Angka saja.
type="date" — Tanggal dengan date picker.
type="checkbox" — Pilihan on/off.
type="radio" — Pilihan satu dari banyak.
type="range" — Slider angka.
type="file" — Upload file.
Form HTML seperti formulir kertas.
<label> adalah tulisan di sebelah kolom isian.
<input> adalah kotak tempat menulis.
required adalah tanda bintang merah (*) yang artinya
wajib diisi.
🧪 Coba Sendiri — Buat Form Pendaftaran
Edit kode ini dan tambahkan field yang dibutuhkan.
⚡ Tantangan
Buat form "Pesan Tiket" yang berisi:
- Nama (text, required)
- Email (email, required)
- Jumlah tiket (number, min=1, max=10)
- Tanggal keberangkatan (date)
- Kelas: Ekonomi / Bisnis (radio)
- Tombol "Pesan Sekarang"
Data Attribute
Simpan data langsung di elemen HTML dengan atribut
data-*
— cara elegan untuk menghubungkan HTML dan JavaScript tanpa kode
yang berantakan.
Apa itu data-*?
Atribut
data-*
memungkinkan kita menyimpan informasi tambahan di dalam elemen
HTML. Bagian setelah data- bisa apa saja yang kita
inginkan.
<!-- Simpan data di elemen --> <button data-produk-id="42" data-harga="150000" data-nama="Buku HTML" >Tambah ke Keranjang</button> <!-- Ambil di JavaScript --> <script> const btn = document.querySelector("button"); btn.addEventListener("click", () => { const id = btn.dataset.produkId; // "42" const harga = btn.dataset.harga; // "150000" console.log(`Beli ${btn.dataset.nama}`); }); </script>
data-* seperti label harga di produk toko. Produknya (elemen HTML) sudah terlihat di rak, tapi di balik label ada info tambahan: kode produk, harga, stok. JavaScript bisa "membaca label" kapanpun diperlukan.
🧪 Coba Sendiri — Menu Produk Interaktif
Box Model
Setiap elemen HTML adalah sebuah kotak. Memahami Box Model adalah kunci untuk mengontrol ukuran, jarak, dan tata letak elemen di halaman.
Lapisan-lapisan Box Model
Setiap elemen terdiri dari 4 lapisan kotak dari dalam ke luar: Content (isi), Padding (jarak dalam), Border (garis tepi), dan Margin (jarak luar).
.kartu { width: 300px; /* lebar content */ padding: 20px; /* jarak dalam, 4 sisi */ border: 2px solid #ccc; /* garis tepi */ margin: 16px; /* jarak dari elemen lain */ /* ⚠️ PENTING: box-sizing */ box-sizing: border-box; /* width 300px TERMASUK padding + border */ }
💡 box-sizing: border-box — Selalu Pakai Ini!
Secara default, width: 300px hanya mengukur konten.
Padding dan border ditambahkan di luar, sehingga total bisa
menjadi 340px+. Dengan box-sizing: border-box, ukuran
300px sudah mencakup semuanya — lebih mudah diprediksi.
Tambahkan ini di atas CSS kamu:
*, *::before, *::after { box-sizing: border-box;
}
🧪 Eksplorasi Box Model
Flexbox
Flexbox adalah sistem tata letak satu dimensi di CSS. Dengan beberapa properti sederhana, kamu bisa menyusun elemen secara horizontal atau vertikal dengan kontrol penuh.
Container & Item
Flexbox bekerja pada dua level: Container (elemen
induk, diberi
display: flex) dan Item (elemen anak di dalamnya). Properti
di container mengontrol semua anak sekaligus.
.container { display: flex; /* Arah susunan */ flex-direction: row; /* row | column */ /* Jarak antar item */ gap: 16px; /* Perataan horizontal (sumbu utama) */ justify-content: center; /* flex-start | flex-end | space-between | space-around */ /* Perataan vertikal (sumbu silang) */ align-items: center; /* flex-start | flex-end | stretch */ /* Agar item bisa pindah baris jika tidak muat */ flex-wrap: wrap; }
Container adalah rak toko. Item adalah produk di rak.
justify-content mengatur produk kiri-kanan di rak.
align-items mengatur produk atas-bawah.
gap adalah jarak antar produk.
🧪 Flexbox Playground
Ubah nilai justify-content dan
align-items untuk melihat efeknya.
⚡ Tantangan — Kartu Profil
Buat 3 kartu profil berdampingan dengan Flexbox. Setiap kartu
berisi foto (pakai emoji), nama, dan jabatan. Di layar kecil
(pakai flex-wrap: wrap), kartu harus bisa turun ke
baris baru.
CSS Variables & Animasi
CSS Variables membuat kode lebih terorganisir dan mudah diubah. Animasi memberi nyawa pada halaman web tanpa perlu JavaScript.
CSS Custom Properties (Variables)
Definisikan variabel sekali, gunakan di mana saja. Jika ingin
ganti warna utama, cukup ubah di satu tempat. Variabel CSS
dideklarasikan dengan
--nama-variabel
dan dipanggil dengan
var(--nama-variabel).
:root { --warna-utama: #c8702a; --warna-teks: #1a1410; --radius: 10px; } .tombol { background: var(--warna-utama); color: white; border-radius: var(--radius); transition: transform 0.2s, box-shadow 0.2s; } .tombol:hover { transform: translateY(-3px); box-shadow: 0 8px 20px rgba(0,0,0,0.15); } /* Keyframe animation */ @keyframes muncul { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .kartu { animation: muncul 0.4s ease; }
🧪 Tema Gelap/Terang dengan CSS Variables
DOM & Event
DOM (Document Object Model) adalah representasi HTML sebagai objek yang bisa dimanipulasi JavaScript. Event adalah cara JavaScript merespons aksi pengguna.
Memilih & Mengubah Elemen
JavaScript bisa menemukan elemen HTML menggunakan
querySelector
(satu elemen) atau
querySelectorAll
(semua yang cocok). Setelah ditemukan, kita bisa mengubah teks,
gaya, kelas, dan atributnya.
// Pilih elemen const judul = document.querySelector("h1"); const semua = document.querySelectorAll(".kartu"); // Ubah konten judul.textContent = "Judul Baru"; judul.innerHTML = "Judul <em>Baru</em>"; // Ubah style judul.style.color = "#c8702a"; // Tambah / hapus kelas CSS judul.classList.add("aktif"); judul.classList.remove("aktif"); judul.classList.toggle("aktif"); // Dengarkan event judul.addEventListener("click", (event) => { console.log("Diklik!", event.target); });
DOM seperti remote TV. HTML adalah televisinya (yang terlihat).
JavaScript adalah tanganmu yang memegang remote.
querySelector adalah tombol untuk memilih
channel/elemen. addEventListener adalah tombol yang
diprogram untuk bereaksi saat ditekan.
🧪 To-Do List Interaktif
Fetch API
Fetch API memungkinkan JavaScript mengambil data dari server (API) tanpa me-reload halaman. Inilah yang membuat aplikasi web terasa cepat dan dinamis.
Cara Kerja Fetch
Bayangkan kamu memesan makanan via aplikasi. Kamu tidak perlu pergi ke restoran — kamu kirim permintaan, tunggu sebentar, dan makanan datang. Fetch bekerja persis seperti itu: kamu minta data ke server, tunggu respons, lalu tampilkan hasilnya.
Karena membutuhkan waktu tunggu, kita menggunakan
async/await
agar kode tidak "membekukan" halaman.
async function ambilData() { try { // 1. Kirim permintaan const respons = await fetch("https://api.contoh.com/data"); // 2. Periksa apakah berhasil if (!respons.ok) throw new Error("Gagal!"); // 3. Parse JSON const data = await respons.json(); // 4. Gunakan data tampilkan(data); } catch (error) { console.error("Error:", error); } }
🧪 Fetch Data Pengguna dari API
localStorage
localStorage
memungkinkan kamu menyimpan data di browser pengguna secara
permanen — data tetap ada meski halaman di-refresh atau browser
ditutup.
Simpan, Baca, Hapus
localStorage bekerja seperti kamus/dictionary: setiap data punya kunci dan nilai. Data disimpan sebagai teks, jadi objek JS perlu dikonversi ke JSON terlebih dahulu.
// Simpan (hanya string!) localStorage.setItem("nama", "Budi"); // Baca const nama = localStorage.getItem("nama"); // "Budi" // Hapus satu kunci localStorage.removeItem("nama"); // Hapus semua localStorage.clear(); // Simpan objek (harus JSON.stringify) const profil = { nama: "Budi", usia: 25 }; localStorage.setItem("profil", JSON.stringify(profil)); // Baca objek (harus JSON.parse) const p = JSON.parse(localStorage.getItem("profil"));
localStorage seperti buku catatan kecil yang ada di laci browser kamu. Setiap website punya lacinya sendiri. Kamu bisa tulis catatan, laci tetap ada bahkan setelah tutup browser, tapi kalau browser-nya uninstall, laci itu hilang juga.
🧪 Catatan Persisten
🎉 Tantangan Akhir — Gabungkan Semuanya!
Buat aplikasi "Daftar Belanja" yang menggunakan localStorage agar data tidak hilang saat di-refresh:
- Form input nama item + tombol tambah
- Tampilkan daftar item yang ditambahkan
- Tombol ✓ (centang selesai) dan ✕ (hapus) di setiap item
- Simpan dan muat ulang dari localStorage