Hampir setiap produk perangkat lunak menempatkan dokumentasi tepat di belakang halaman utamanya: pengunjung yang mulai serius memakai produk langsung mencari cara memasang, daftar fitur, dan jawaban atas pertanyaan teknis. Format halaman dokumentasi pun khas dan mudah dikenali — bilah samping berisi daftar topik, artikel panjang di sebelahnya, breadcrumb di bagian atas, dan kolom pencarian yang menyaring daftar topik. Proyek ini membangun satu halaman dokumentasi utuh untuk aplikasi fiktif CatatKu, aplikasi pencatat ringan dari Komunitas Belajar Web.

Hasil Akhir yang Dibangun #

Target akhirnya adalah satu halaman dokumentasi CatatKu dengan fitur berikut:

  • Kerangka valid berisi header identitas, main dua kolom konsep (nav sidebar dan article konten), serta footer.
  • Navigasi lengkap: daftar topik dengan tautan fragment #id, breadcrumb ol, dan daftar “Di halaman ini”.
  • Tabel pintasan keyboard dengan caption dan sel th beratribut scope.
  • Tampilan dari styles/style.css: grid dua kolom, sidebar sticky, tipografi pre/code, dan palet konsisten.
  • Pencarian sederhana: kolom saring yang menyembunyikan topik tak cocok lewat atribut hidden.

Prasyarat #

Proyek ini merangkai konsep dari section sebelumnya; baca dahulu bila materinya masih asing:

  • Section Struktur Dokumen dan Semantic HTML: kerangka dokumen serta elemen nav, article, dan address.
  • Section Lists dan Tables: daftar navigasi ul dan tabel pintasan.
  • Section Links dan Navigasi: tautan fragment menuju elemen ber-id.
  • Section HTML dan CSS: custom properties, grid, dan posisi sticky.
  • Section HTML dan JavaScript: querySelector dan event listener.

Empat Bagian Proyek #

Kerjakan keempat bagian berurutan; setiap bagian memakai hasil bagian sebelumnya:

BagianFokus
Bagian 1: Menyusun Struktur DokumentasiKerangka valid: header, main dua kolom konsep, footer
Bagian 2: Navigasi DokumentasiDaftar topik, breadcrumb, dan daftar “Di halaman ini”
Bagian 3: Styling DasarStylesheet: grid, sidebar sticky, tipografi kode
Bagian 4: Pencarian SederhanaKolom saring topik dengan JavaScript

Memakai File Pendukung #

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

text
halaman-dokumentasi/
├── assets/
│   └── logo-docs.svg
├── styles/
│   └── style.css
├── tests/
│   └── cek-struktur.html
├── part-1-struktur-dokumentasi/
│   └── dokumentasi.html
├── part-2-navigasi-dokumentasi/
│   └── dokumentasi-navigasi.html
├── part-3-styling-dasar/
│   └── dokumentasi-styling.html
└── part-4-pencarian-sederhana/
    ├── dokumentasi-pencarian.html
    └── pencarian.js
  • assets/logo-docs.svg: ikon dokumen 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 dan ../assets/logo-docs.svg 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 Dokumentasi - ditulis pada Bagian 3, dipakai Bagian 3 dan 4 */
:root {
  --warna-utama: #1d4ed8;
  --warna-teks: #1f2937;
  --warna-latar: #f8fafc;
  --warna-putih: #ffffff;
  --warna-border: #cbd5e1;
  --warna-kode: #eef2ff;
  --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;
  gap: var(--jarak);
  padding: var(--jarak) calc(var(--jarak) * 2);
  background-color: var(--warna-utama);
  color: var(--warna-putih);
}

header h1 {
  margin: 0;
  font-size: 1.25rem;
}

header p {
  margin: 0;
  font-size: 0.9rem;
}

main {
  display: grid;
  grid-template-columns: 240px minmax(0, 1fr);
  gap: calc(var(--jarak) * 2);
  max-width: 1024px;
  margin: 0 auto;
  padding: calc(var(--jarak) * 2);
}

main > nav {
  position: sticky;
  top: var(--jarak);
  align-self: start;
  padding: var(--jarak);
  background-color: var(--warna-putih);
  border: 1px solid var(--warna-border);
  border-radius: 8px;
}

main > nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

main > nav li {
  margin-bottom: 8px;
}

main > nav a {
  color: var(--warna-utama);
  text-decoration: none;
}

main > nav a:hover {
  text-decoration: underline;
}

/* Kolom saring topik (Bagian 4) */
main > nav label {
  display: block;
  margin-bottom: 8px;
  font-weight: 700;
}

main > nav input {
  width: 100%;
  margin-bottom: var(--jarak);
  padding: 8px;
  font: inherit;
  border: 1px solid var(--warna-border);
  border-radius: 6px;
}

article {
  padding: calc(var(--jarak) * 1.5);
  background-color: var(--warna-putih);
  border: 1px solid var(--warna-border);
  border-radius: 8px;
}

article h2 {
  margin-top: 0;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--warna-border);
  color: var(--warna-utama);
}

.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 var(--jarak);
  padding: 0;
  list-style: none;
  font-size: 0.9rem;
}

.breadcrumb li + li::before {
  content: "›";
  margin-right: 8px;
}

.breadcrumb a {
  color: var(--warna-utama);
}

.toc {
  margin-bottom: calc(var(--jarak) * 1.5);
  padding: var(--jarak);
  background-color: var(--warna-latar);
  border: 1px solid var(--warna-border);
  border-radius: 8px;
}

.toc-label {
  margin: 0 0 8px;
  font-weight: 700;
}

.toc ol {
  margin: 0;
  padding-left: 20px;
}

table {
  width: 100%;
  margin: var(--jarak) 0;
  border-collapse: collapse;
}

caption {
  padding-bottom: 8px;
  font-weight: 700;
  text-align: left;
}

th,
td {
  padding: 8px var(--jarak);
  border: 1px solid var(--warna-border);
  text-align: left;
}

kbd {
  padding: 2px 6px;
  font-family: monospace;
  font-size: 0.9em;
  background-color: var(--warna-latar);
  border: 1px solid var(--warna-border);
  border-radius: 4px;
}

code {
  padding: 2px 4px;
  font-family: monospace;
  background-color: var(--warna-kode);
  border-radius: 4px;
}

pre {
  padding: var(--jarak);
  overflow-x: auto;
  background-color: var(--warna-kode);
  border-radius: 8px;
}

pre code {
  padding: 0;
  background-color: transparent;
}

address {
  font-style: normal;
}

footer {
  padding: var(--jarak) calc(var(--jarak) * 2);
  text-align: center;
  background-color: var(--warna-putih);
  border-top: 1px solid var(--warna-border);
}

footer p {
  margin: 0;
}

@media (max-width: 700px) {
  main {
    display: block;
  }

  main > nav {
    position: static;
    margin-bottom: var(--jarak);
  }
}

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 Dokumentasi</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-docs.svg" alt="Logo Dokumentasi CatatKu" width="48" height="48">
    <h1>Checklist Pemeriksaan Halaman Dokumentasi</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 logo ber<code>alt</code> deskriptif serta <code>h1</code> nama dokumentasi</label></li>
    <li><label><input type="checkbox" data-cek="4"> Main terbagi dua wilayah: <code>nav</code> daftar topik dan <code>article</code> konten</label></li>
    <li><label><input type="checkbox" data-cek="5"> Setiap topik artikel dibuka <code>h2</code> dengan <code>id</code> unik (pengenalan hingga dukungan)</label></li>
    <li><label><input type="checkbox" data-cek="6"> Tautan sidebar menunjuk fragment <code>#id</code> yang cocok dengan id bagian</label></li>
    <li><label><input type="checkbox" data-cek="7"> Breadcrumb memakai <code>ol</code> dengan <code>aria-current="page"</code> pada posisi terkini</label></li>
    <li><label><input type="checkbox" data-cek="8"> Daftar "Di halaman ini" tersedia di awal <code>article</code></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"> Kolom saring berlabel <code>for</code>/<code>id</code>; butir tak cocok disembunyikan lewat <code>hidden</code></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-dokumentasi";

    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>