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:

BagianFokus
Bagian 1: Menyiapkan Struktur DokumenKerangka valid: head lengkap, header, main, footer
Bagian 2: Menambahkan Konten ProfilSection tentang-saya, keahlian, dan kontak
Bagian 3: Styling DasarStylesheet: custom properties dan flexbox
Bagian 4: Interaksi SederhanaDialog kontak via JavaScript

Memakai File Pendukung #

Tiga folder proyek menyimpan berkas pendukung. Susun salinan lokalnya mengikuti pohon berikut:

text
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:

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

styles/style.css

Unduh berkas
css
/* 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
html
<!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>