Setiap pengembang web membutuhkan satu halaman yang memperkenalkan dirinya: nama, bidang kerja, keahlian, dan cara menghubungi. Halaman profil terlihat sederhana, tetapi menyentuh hampir seluruh materi Course HTML ini: kerangka dokumen, elemen semantik, tata letak, hingga interaksi ringan dengan JavaScript. Proyek pertama ini mengubah materi tersebut menjadi satu produk utuh yang siap dibagikan.
Hasil Akhir yang Dibangun #
Target akhirnya adalah satu halaman profil untuk tokoh fiktif Budi Santoso, pengembang web pemula dari Bandung. Fitur yang kita bangun secara bertahap:
- Dokumen valid dengan metadata lengkap (charset, viewport, title, description).
- Kerangka semantik header, main, dan footer, plus logo SVG.
- Tiga section ber-id: tentang-saya, keahlian (ul), dan kontak (address).
- Tampilan profesional dari styles/style.css: custom properties dan flexbox.
- Dialog kontak yang terbuka lewat tombol dan tertutup lewat mouse atau keyboard.
Prasyarat #
Proyek ini merangkai konsep dari section sebelumnya; baca dahulu bila materinya masih asing:
- Section Struktur Dokumen: doctype, head, dan elemen dasar dokumen.
- Section Semantic HTML dan Lists: header, main, footer, section, serta daftar ul/li.
- Section HTML dan CSS: selector, warna, spacing, penghubungan stylesheet.
- Section HTML dan JavaScript serta Interactive Elements: event click dan elemen dialog.
Empat Bagian Proyek #
Kerjakan keempat bagian berurutan; setiap bagian memakai hasil bagian sebelumnya:
| Bagian | Fokus |
|---|---|
| Bagian 1: Menyiapkan Struktur Dokumen | Kerangka valid: head lengkap, header, main, footer |
| Bagian 2: Menambahkan Konten Profil | Section tentang-saya, keahlian, dan kontak |
| Bagian 3: Styling Dasar | Stylesheet: custom properties dan flexbox |
| Bagian 4: Interaksi Sederhana | Dialog kontak via JavaScript |
Memakai File Pendukung #
Tiga folder proyek menyimpan berkas pendukung. Susun salinan lokalnya mengikuti pohon berikut:
halaman-profil/
├── assets/
│ └── logo.svg
├── styles/
│ └── style.css
├── tests/
│ └── cek-struktur.html
├── part-1-struktur-dokumen/
│ └── profil.html
└── part-2-menambahkan-konten/
└── profil-konten.html- assets/logo.svg: logo monogram “BS” untuk header setiap tahap.
- 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 tetap benar.
Referensi resmi untuk pendalaman:
Tahap 1 dari proyek Halaman Profil.
Buka → # Bagian 2: Menambahkan Konten ProfilTahap 2 dari proyek Halaman Profil.
Buka → # Bagian 3: Styling DasarTahap 3 dari proyek Halaman Profil.
Buka → # Bagian 4: Interaksi SederhanaTahap 4 dari proyek Halaman Profil.
Buka →Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
styles/style.css
Unduh berkas/* Stylesheet proyek Halaman Profil - ditulis pada Bagian 3, dipakai Bagian 3 dan 4 */
:root {
--warna-utama: #1a6b54;
--warna-teks: #1f2937;
--warna-latar: #f3f4f6;
--warna-putih: #ffffff;
--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,
footer {
background-color: var(--warna-utama);
color: var(--warna-putih);
}
header {
display: flex;
align-items: center;
gap: var(--jarak);
padding: var(--jarak);
}
img {
max-width: 100%;
height: auto;
}
header img {
width: 56px;
border-radius: 50%;
}
main {
max-width: 720px;
margin: 0 auto;
padding: var(--jarak);
}
section {
margin-bottom: var(--jarak);
padding: var(--jarak);
background-color: var(--warna-putih);
border-radius: 8px;
}
h2 {
margin-top: 0;
color: var(--warna-utama);
}
footer p {
margin: 0;
padding: var(--jarak);
text-align: center;
}
button {
padding: 10px 20px;
border: none;
border-radius: 6px;
font-size: 1rem;
background-color: var(--warna-utama);
color: var(--warna-putih);
cursor: pointer;
}
dialog {
max-width: 360px;
padding: var(--jarak);
border: none;
border-radius: 8px;
}
dialog::backdrop {
background-color: rgba(31, 41, 55, 0.5);
}
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 Halaman Profil</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/logo.svg" alt="Logo monogram BS" width="48" height="48">
<h1>Checklist Pemeriksaan Halaman Profil</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, main, dan footer membentuk kerangka halaman</label></li>
<li><label><input type="checkbox" data-cek="4"> Logo memakai <code>img</code> dengan teks <code>alt</code> yang menjelaskan gambar</label></li>
<li><label><input type="checkbox" data-cek="5"> Section tentang-saya, keahlian, dan kontak ber-id unik</label></li>
<li><label><input type="checkbox" data-cek="6"> Daftar keahlian menyusun butirnya dengan <code>ul</code> dan <code>li</code></label></li>
<li><label><input type="checkbox" data-cek="7"> Alamat kontak dibungkus <code>address</code> dan memuat tautan mailto</label></li>
<li><label><input type="checkbox" data-cek="8"> Halaman terhubung ke stylesheet <code>styles/style.css</code></label></li>
<li><label><input type="checkbox" data-cek="9"> Tombol memakai elemen <code>button</code> dengan <code>type="button"</code></label></li>
<li><label><input type="checkbox" data-cek="10"> Dialog kontak terbuka lewat tombol dan tertutup tanpa menghalangi keyboard</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-halaman-profil";
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>