Landing page punya satu pekerjaan yang berbeda dari halaman web lain: mengarahkan pengunjung pada satu tindakan, misalnya mendaftar kelas, mengunduh aplikasi, atau berlangganan kabar. Karena itu strukturnya khas — hero yang menyampaikan tawaran dalam satu pandangan, daftar fitur yang singkat, testimoni yang membangun kepercayaan, dan call-to-action yang berulang di sepanjang halaman. Proyek terakhir Course HTML ini membangun landing page untuk kelas daring fiktif Kelas Web Dasar milik Komunitas Belajar Web, dari kerangka konten hingga interaksi pendaftarannya.
Hasil Akhir yang Dibangun #
Target akhirnya adalah satu halaman landing page dengan fitur berikut:
- Kerangka valid berisi header dengan nav CTA, hero bergambar, section fitur, section testimoni, dan footer.
- Call-to-action yang berulang: tautan CTA di header dan hero, form langganan email, lalu CTA lagi di footer.
- Form pendaftaran dengan
label,input type="email", dan atributrequired. - Tampilan dari styles/style.css: hero bergradien, tombol menonjol, custom properties, dan jarak seragam.
- Interaksi ringan: FAQ
details, dialog terima kasih lewatpreventDefault(), tanpa perlu server.
Prasyarat #
Proyek ini merangkai konsep dari section sebelumnya; baca dahulu bila materinya masih asing:
- Section Semantic HTML: kerangka header, main, section, dan footer.
- Section Teks dan Formatting: kutipan testimoni dengan
blockquote. - Section Forms: label, kontrol email, dan tombol submit.
- Section HTML dan CSS: custom properties, gradien, dan flexbox.
- Section HTML dan JavaScript serta Interactive Elements: event,
details, dandialog.
Empat Bagian Proyek #
Kerjakan keempat bagian berurutan; setiap bagian memakai hasil bagian sebelumnya:
| Bagian | Fokus |
|---|---|
| Bagian 1: Menyusun Struktur Konten | Kerangka: header CTA, hero, fitur, testimoni, footer |
| Bagian 2: Call-to-Action | Link vs button, form langganan email, CTA berulang |
| Bagian 3: Styling Dasar | Stylesheet: hero gradien, tombol menonjol, custom properties |
| Bagian 4: Interaksi Sederhana | FAQ details dan dialog terima kasih |
Memakai File Pendukung #
Tiga folder proyek menyimpan berkas pendukung. Susun salinan lokalnya mengikuti pohon berikut:
landing-page/
├── assets/
│ └── ilustrasi-hero.svg
├── styles/
│ └── style.css
├── tests/
│ └── cek-struktur.html
├── part-1-struktur-konten/
│ └── landing.html
├── part-2-call-to-action/
│ └── landing-cta.html
├── part-3-styling-dasar/
│ └── landing-styling.html
└── part-4-interaksi-sederhana/
├── landing-interaksi.html
└── interaksi.js- assets/ilustrasi-hero.svg: ilustrasi jendela browser untuk sisi kanan hero.
- styles/style.css: stylesheet final, ditulis pada Bagian 3 dan dipakai Bagian 4.
- tests/cek-struktur.html: checklist sepuluh butir pemeriksaan; kemajuannya tersimpan di localStorage.
Unduh contoh tiap bagian lewat tautan pada header code block, lalu letakkan sesuai pohon di atas agar jalur relatif seperti ../styles/style.css dan ../assets/ilustrasi-hero.svg tetap benar.
Referensi resmi untuk pendalaman:
Tahap 1 dari proyek Landing Page.
Buka → # Bagian 2: Call-to-ActionTahap 2 dari proyek Landing Page.
Buka → # Bagian 3: Styling DasarTahap 3 dari proyek Landing Page.
Buka → # Bagian 4: Interaksi SederhanaTahap 4 dari proyek Landing Page.
Buka →Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
styles/style.css
Unduh berkas/* Stylesheet proyek Landing Page - ditulis pada Bagian 3, dipakai Bagian 3 dan 4 */
:root {
--warna-utama: #0e7490;
--warna-aksen: #155e75;
--warna-teks: #1f2937;
--warna-latar: #f8fafc;
--warna-putih: #ffffff;
--warna-border: #cbd5e1;
--jarak: 16px;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: var(--warna-teks);
background-color: var(--warna-latar);
}
header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--jarak) calc(var(--jarak) * 2);
background-color: var(--warna-putih);
border-bottom: 1px solid var(--warna-border);
}
.logo {
margin: 0;
font-weight: 800;
color: var(--warna-utama);
}
.tombol {
display: inline-block;
padding: 10px 24px;
background-color: var(--warna-utama);
color: var(--warna-putih);
border-radius: 999px;
font-weight: 700;
text-decoration: none;
}
.tombol:hover {
background-color: var(--warna-aksen);
}
.hero {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: calc(var(--jarak) * 2);
padding: calc(var(--jarak) * 3) calc(var(--jarak) * 2);
background-image: linear-gradient(135deg, #cffafe, var(--warna-latar));
}
.hero div {
max-width: 480px;
}
.hero h1 {
margin: 0 0 var(--jarak);
font-size: 2rem;
line-height: 1.25;
}
.hero img {
max-width: 100%;
height: auto;
}
#daftar,
#fitur,
#testimoni {
max-width: 960px;
margin: 0 auto;
padding: calc(var(--jarak) * 2);
}
#fitur {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: var(--jarak);
}
#fitur h2 {
grid-column: 1 / -1;
margin: 0 0 var(--jarak);
}
#fitur > div {
padding: var(--jarak);
background-color: var(--warna-putih);
border: 1px solid var(--warna-border);
border-radius: 8px;
}
#fitur h3 {
margin: 0 0 8px;
}
#testimoni blockquote {
margin: 0 0 var(--jarak);
padding: var(--jarak);
background-color: var(--warna-putih);
border-left: 4px solid var(--warna-utama);
border-radius: 0 8px 8px 0;
}
#testimoni blockquote p {
margin: 0 0 8px;
}
#testimoni blockquote footer {
font-size: 0.9rem;
color: #475569;
}
#daftar h2 {
margin-top: 0;
}
form {
max-width: 420px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 700;
}
input[type="email"] {
width: 100%;
margin-bottom: var(--jarak);
padding: 10px;
font: inherit;
border: 1px solid var(--warna-border);
border-radius: 6px;
}
.catatan {
font-size: 0.9rem;
color: #475569;
}
button {
padding: 10px 24px;
border: none;
border-radius: 999px;
background-color: var(--warna-utama);
color: var(--warna-putih);
font-size: 1rem;
font-weight: 700;
cursor: pointer;
}
button:hover {
background-color: var(--warna-aksen);
}
/* FAQ dan dialog terima kasih (Bagian 4) */
details {
margin-bottom: 8px;
padding: var(--jarak);
background-color: var(--warna-putih);
border: 1px solid var(--warna-border);
border-radius: 8px;
}
details summary {
font-weight: 700;
cursor: pointer;
}
dialog {
max-width: 360px;
padding: calc(var(--jarak) * 1.5);
border: none;
border-radius: 8px;
}
dialog h2 {
margin-top: 0;
color: var(--warna-utama);
}
dialog::backdrop {
background-color: rgba(15, 23, 42, 0.5);
}
body > footer {
padding: calc(var(--jarak) * 2);
text-align: center;
color: var(--warna-putih);
background-color: #0f172a;
}
body > footer .tombol {
background-color: var(--warna-putih);
color: var(--warna-teks);
}
body > footer p {
margin: 8px 0 0;
}
tests/cek-struktur.html
Unduh berkas<!doctype html>
<html lang="id">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Checklist Pemeriksaan Landing Page</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 720px;
margin: 0 auto;
padding: 16px;
line-height: 1.6;
color: #1f2937;
}
h1 {
font-size: 1.4rem;
}
ul {
padding-left: 20px;
}
li {
margin-bottom: 8px;
}
#progres {
width: 100%;
height: 16px;
}
</style>
</head>
<body>
<header>
<img src="../assets/ilustrasi-hero.svg" alt="Ilustrasi jendela browser dengan halaman web yang sedang disusun" width="96" height="72">
<h1>Checklist Pemeriksaan Landing Page</h1>
</header>
<p>Gunakan halaman ini untuk memeriksa hasil setiap Bagian proyek. Centang butir yang telah dipenuhi; kemajuan tersimpan otomatis di browser.</p>
<p id="ringkasan" aria-live="polite">0 dari 10 butir terpenuhi.</p>
<progress id="progres" value="0" max="10"></progress>
<ul>
<li><label><input type="checkbox" data-cek="1"> Dokumen dimulai dengan <code>doctype</code> dan <code>html lang="id"</code></label></li>
<li><label><input type="checkbox" data-cek="2"> Head memuat <code>meta charset</code>, <code>viewport</code>, <code>title</code>, dan <code>description</code></label></li>
<li><label><input type="checkbox" data-cek="3"> Header memuat nama produk dan <code>nav</code> berisi tautan CTA menuju <code>#daftar</code></label></li>
<li><label><input type="checkbox" data-cek="4"> Hero memuat <code>h1</code>, paragraf manfaat, CTA, dan <code>img</code> ber<code>alt</code> deskriptif</label></li>
<li><label><input type="checkbox" data-cek="5"> Section <code>#daftar</code> memuat <code>form</code> dengan <code>action</code> dan <code>method="post"</code></label></li>
<li><label><input type="checkbox" data-cek="6"> Kolom email berlabel <code>for</code>/<code>id</code>, memakai <code>type="email"</code>, dan membawa <code>required</code></label></li>
<li><label><input type="checkbox" data-cek="7"> Pengirim form memakai <code>button</code> dengan <code>type="submit"</code></label></li>
<li><label><input type="checkbox" data-cek="8"> CTA berulang: tautan tombol tampil di hero dan di footer</label></li>
<li><label><input type="checkbox" data-cek="9"> Halaman terhubung ke stylesheet <code>styles/style.css</code></label></li>
<li><label><input type="checkbox" data-cek="10"> FAQ memakai <code>details</code>/<code>summary</code> dan dialog terima kasih terbuka lewat submit</label></li>
</ul>
<p>Sintaks seluruh file proyek juga dapat diperiksa dengan Nu Html Checker di <a href="https://validator.w3.org/nu/">validator.w3.org/nu</a>.</p>
<script>
const daftar = document.querySelectorAll("input[type='checkbox']");
const progres = document.querySelector("#progres");
const ringkasan = document.querySelector("#ringkasan");
const KUNCI = "cek-landing-page";
function simpan() {
const status = [];
daftar.forEach(function (butir) {
status.push(butir.checked);
});
try {
localStorage.setItem(KUNCI, JSON.stringify(status));
} catch (galat) {
// penyimpanan tidak tersedia; status tetap berlaku selama halaman terbuka
}
}
function muat() {
try {
const status = JSON.parse(localStorage.getItem(KUNCI));
if (Array.isArray(status)) {
daftar.forEach(function (butir, indeks) {
butir.checked = status[indeks] === true;
});
}
} catch (galat) {
// biarkan semua butir pada keadaan awalnya
}
}
function perbarui() {
let terisi = 0;
daftar.forEach(function (butir) {
if (butir.checked) {
terisi += 1;
}
});
progres.value = terisi;
ringkasan.textContent = terisi + " dari " + daftar.length + " butir terpenuhi.";
}
muat();
perbarui();
daftar.forEach(function (butir) {
butir.addEventListener("change", function () {
perbarui();
simpan();
});
});
</script>
</body>
</html>