Proyek pamungkas kursus ini merakit situs portofolio satu halaman untuk Lina Kartika, seorang desainer produk fiktif dari Yogyakarta. Satu halaman semacam ini adalah etalase karier: pengunjung harus langsung memahami siapa pemiliknya, melihat karya terbaik dalam sekejap, dan menemukan cara menghubungi tanpa tersesat. Untuk mencapai itu, kita memakai hampir seluruh bekal dari kursus: design token dari materi custom properties, galeri karya bertata letak CSS Grid, header dan strip keahlian dengan flexbox, navigasi yang runtuh rapi di layar sempit, transisi dan keyframes, sampai lapisan aksesibilitas berupa skip link, :focus-visible, dan prefers-reduced-motion. Karena materinya paling padat, proyek ini dibagi menjadi sembilan bagian; setiap bagian menyimpan snapshot berkasnya sendiri, sehingga kalian bisa mengikuti stylesheet tumbuh dari 54 baris menjadi 333 baris lengkap dengan JavaScript navigasi.
Perilaku yang Diharapkan #
Halaman akhirnya berisi header lengket dengan logo dan tiga tautan navigasi, seksi hero berisi perkenalan singkat, galeri enam kartu proyek, strip tentang-saya dengan chip keahlian, panel ajakan kontak, dan footer. Perilaku yang bisa dicoba langsung:
- Galeri karya menyusun grid
repeat(auto-fit, minmax(280px, 1fr)), sehingga jumlah kolom menyesuaikan lebar layar tanpa media query tambahan. - Sampul tiap kartu adalah
linear-gradientdengan huruf inisial besar, jadi halaman tetap hidup tanpa satu pun berkas gambar. - Pada layar sempit, tiga tautan navigasi berpindah ke balik tombol hamburger; tombol itu melaporkan statusnya lewat
aria-expanded, dan tautan yang terakhir dipilih mendapat warna aksen. - Kartu proyek terangkat empat piksel saat diarahkan kursor, hero memainkan animasi masuk bertingkat, dan seluruh gerak itu dimatikan otomatis bila pengguna memilih pengurangan gerak di sistemnya.
Cuplikan berikut meniru hero dan dua kartu galeri versi final — perhatikan garis aksen di bawah judul seksi dan sampul gradien dengan huruf inisial:
Struktur Folder #
portofolio-desainer/
├── _index.md
├── beranda.html # salinan src/index.html untuk diunduh
├── styles.css # salinan src/css/styles.css
├── main.js # salinan src/js/main.js
├── src/
│ ├── index.html
│ ├── css/
│ │ └── styles.css
│ ├── js/
│ │ └── main.js
│ └── assets/
│ └── logo.svg
├── part-1-design-system/
│ ├── index.md
│ └── styles.css
├── part-2-hero-dan-introduction/
│ ├── index.md
│ ├── styles.css
│ └── beranda.html
├── part-3-project-showcase/
│ ├── index.md
│ ├── styles.css
│ └── beranda.html
├── part-4-layout-dengan-flexbox-dan-grid/
│ ├── index.md
│ ├── styles.css
│ └── beranda.html
├── part-5-responsive-navigation/
│ ├── index.md
│ ├── styles.css
│ ├── beranda.html
│ └── main.js
├── part-6-typography-dan-color-system/
│ ├── index.md
│ └── styles.css
├── part-7-animation-dan-interaction-states/
│ ├── index.md
│ └── styles.css
├── part-8-accessibility/
│ ├── index.md
│ ├── styles.css
│ └── beranda.html
└── part-9-final-responsive-refinement/
├── index.md
├── styles.css
├── beranda.html
└── main.jsTahapan Pengerjaan #
- Bagian 1: Design System — token warna rose-teal, skala spasi, radius, bayangan, dan base reset sebagai fondasi seluruh halaman.
- Bagian 2: Hero dan Introduction — kerangka halaman, tombol, hero perkenalan, seksi pengantar, serta berkas HTML pertama.
- Bagian 3: Project Showcase — galeri enam kartu proyek dengan sampul gradien, huruf inisial, dan label peran.
- Bagian 4: Layout dengan Flexbox dan Grid — komposisi header, strip tentang-saya berisi bio dan chip keahlian, panel kontak, dan footer.
- Bagian 5: Responsive Navigation
— tombol hamburger, menu yang runtuh di layar sempit, dan
main.jspenggerakaria-expanded. - Bagian 6: Typography dan Color System — token tipografi serif untuk judul, garis aksen di bawah judul seksi, dan penyelarasan warna label.
- Bagian 7: Animation dan Interaction States — transisi tombol, kartu, dan chip serta animasi masuk hero bertingkat.
- Bagian 8: Accessibility
— skip link,
:focus-visible, kontras teks yang lolos audit, dan penghormatanprefers-reduced-motion. - Bagian 9: Final Responsive Refinement
— perapihan breakpoint, tautan navigasi aktif, dan snapshot akhir yang identik dengan
src/.
Ikuti urutannya, karena setiap bagian membangun di atas snapshot bagian sebelumnya.
Berkas Sumber Lengkap #
Tiga berkas berikut adalah kondisi akhir proyek, identik dengan snapshot Bagian 9. Gunakan tombol unduh pada header tiap code block untuk menyimpannya, lalu susun folder sesuai struktur di atas. Snapshot halaman ditampilkan dengan label beranda.html; saat dipraktikkan, simpan isinya sebagai index.html di dalam folder src/:
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lina Kartika — Portofolio Desainer</title>
<link rel="icon" href="assets/logo.svg" type="image/svg+xml">
<link rel="stylesheet" href="css/styles.css">
<script src="js/main.js" defer></script>
</head>
<body>
<a class="tautan-lompat" href="#konten-utama">Lompat ke konten utama</a>
<header class="laman-kepala">
<div class="pembungkus kepala-baris">
<div class="brand">
<img src="assets/logo.svg" alt="Logo Lina Kartika" width="34" height="34">
<span class="brand-nama">Lina Kartika</span>
</div>
<button class="tombol-nav" id="tombol-nav" type="button" aria-expanded="false" aria-controls="nav-utama">
<span class="sr-only">Buka atau tutup menu navigasi</span>
<span class="tombol-nav-garis" aria-hidden="true"></span>
</button>
<nav class="nav-utama" id="nav-utama" aria-label="Navigasi utama">
<a href="#karya">Karya</a>
<a href="#tentang">Tentang</a>
<a href="#kontak">Kontak</a>
</nav>
</div>
</header>
<main id="konten-utama">
<div class="pembungkus">
<section class="hero" aria-labelledby="judul-hero">
<p class="hero-pembuka">Portofolio Desainer Produk</p>
<h1 class="judul-halaman" id="judul-hero">Saya Lina — saya merancang produk digital yang nyaman dipakai.</h1>
<p class="pengantar">Enam tahun terakhir saya membantu startup dan UMKM mengubah ide menjadi antarmuka yang jelas: mulai dari riset pengguna, wireframe, sistem desain, sampai dukungan implementasi bersama programmer.</p>
<div class="hero-aksi">
<a class="tombol" href="#karya">Lihat karya terpilih</a>
<a class="tombol tombol--garis" href="#kontak">Hubungi saya</a>
</div>
</section>
<section class="perkenalan" aria-labelledby="judul-perkenalan">
<h2 class="section-judul" id="judul-perkenalan">Perkenalan</h2>
<p>Saya desainer produk yang berbasis di Yogyakarta. Latar belakang saya di desain komunikasi visual membuat saya peka pada hierarki, tipografi, dan ruang kosong — tiga hal yang menentukan apakah sebuah halaman nyaman dibaca atau tidak.</p>
<p>Di luar pekerjaan klien, saya menulis catatan praktik desain dan menggambar pola batik digital. Halaman portofolio ini sendiri saya bangun dari nol memakai HTML dan CSS murni sebagai latihan menyatukan seluruh materi kursus.</p>
</section>
<section class="seksi-karya" id="karya" aria-labelledby="judul-karya">
<h2 class="section-judul" id="judul-karya">Karya Terpilih</h2>
<div class="galeri-proyek">
<article class="kartu-proyek">
<div class="sampul sampul--kopi" aria-hidden="true"><span class="sampul-huruf">K</span></div>
<div class="kartu-isi">
<h3 class="kartu-nama">Kopi Relung</h3>
<p class="kartu-peran">Identitas Visual</p>
<p class="kartu-catatan">Merek kedai kopi rakyat: logotype, kemasan, dan menu papan dari satu sistem warna hangat.</p>
</div>
</article>
<article class="kartu-proyek">
<div class="sampul sampul--setor" aria-hidden="true"><span class="sampul-huruf">S</span></div>
<div class="kartu-isi">
<h3 class="kartu-nama">Setor</h3>
<p class="kartu-peran">Desain UI Mobile</p>
<p class="kartu-catatan">Aplikasi pencatat tabungan harian dengan alur setor dan tarik tiga langkah.</p>
</div>
</article>
<article class="kartu-proyek">
<div class="sampul sampul--katalog" aria-hidden="true"><span class="sampul-huruf">W</span></div>
<div class="kartu-isi">
<h3 class="kartu-nama">Warnai Katalog</h3>
<p class="kartu-peran">Desain Web</p>
<p class="kartu-catatan">Katalog produk kerajinan dengan kartu responsif dan halaman detail yang ringan.</p>
</div>
</article>
<article class="kartu-proyek">
<div class="sampul sampul--lumbung" aria-hidden="true"><span class="sampul-huruf">L</span></div>
<div class="kartu-isi">
<h3 class="kartu-nama">Lumbung Data</h3>
<p class="kartu-peran">Desain Produk</p>
<p class="kartu-catatan">Dasbor panen untuk kelompok tani: tabel, grafik, dan mode gelap yang bisa diandalkan.</p>
</div>
</article>
<article class="kartu-proyek">
<div class="sampul sampul--senja" aria-hidden="true"><span class="sampul-huruf">A</span></div>
<div class="kartu-isi">
<h3 class="kartu-nama">Senja Literasi</h3>
<p class="kartu-peran">Tipografi Editorial</p>
<p class="kartu-catatan">Majalah daring sastra muda dengan skala huruf besar dan kolom baca 65 karakter.</p>
</div>
</article>
<article class="kartu-proyek">
<div class="sampul sampul--rupa" aria-hidden="true"><span class="sampul-huruf">R</span></div>
<div class="kartu-isi">
<h3 class="kartu-nama">Ruang Rupa</h3>
<p class="kartu-peran">Desain Interaksi</p>
<p class="kartu-catatan">Galeri digital karya seni grafis dengan turun pandu dan kartu karya yang bisa dibandingkan.</p>
</div>
</article>
</div>
</section>
<section class="seksi-tentang" id="tentang" aria-labelledby="judul-tentang">
<h2 class="section-judul" id="judul-tentang">Tentang Saya</h2>
<div class="tentang-grid">
<div class="tentang-bio">
<p>Saya memulai karier sebagai desainer grafis di percetakan, lalu pindah ke produk digital karena tertarik pada sisi perilaku pengguna. Sejak itu saya bergabung dengan dua studio dan satu tim produk, menangani riset, desain antarmuka, dan sistem desain.</p>
<p>Cara kerja saya sederhana: pahami dulu masalahnya, gambar solusi serendah mungkin, uji dengan pengguna nyata, lalu rawat bersama programmer. Desain yang baik menurut saya adalah yang diam-diam membuat tugas pengguna selesai lebih cepat.</p>
</div>
<div class="tentang-keahlian">
<h3 class="tentang-label">Keahlian</h3>
<ul class="daftar-chip">
<li class="chip">Riset Pengguna</li>
<li class="chip">Wireframe</li>
<li class="chip">Figma</li>
<li class="chip">Sistem Desain</li>
<li class="chip">Desain Antarmuka</li>
<li class="chip">Tipografi</li>
<li class="chip">Prototype</li>
<li class="chip">HTML & CSS</li>
</ul>
</div>
</div>
</section>
<section class="seksi-kontak" id="kontak" aria-labelledby="judul-kontak">
<div class="panel-kontak">
<h2 class="section-judul" id="judul-kontak">Mari Berkolaborasi</h2>
<p>Saya membuka slot proyek untuk kuartal berikutnya, terutama pada bidang produk keuangan dan pendidikan. Ceritakan kebutuhan Anda, dan saya akan membalas dalam dua hari kerja.</p>
<a class="tombol" href="mailto:[email protected]">Kirim surel ke saya</a>
</div>
</section>
</div>
</main>
<footer class="laman-kaki">
<div class="pembungkus kaki-baris">
<span>Lina Kartika — proyek latihan CSS</span>
<span>Desain produk, antarmuka, dan identitas visual</span>
</div>
</footer>
</body>
</html>/* ============================================================
Portofolio Desainer — stylesheet utama
Kondisi: versi akhir proyek (selelah Bagian 9)
Urutan seksi: token, base, kerangka, tombol, hero,
galeri proyek, tentang, kontak, footer, navigasi responsif,
responsif, tipografi seksi, keadaan interaksi, aksesibilitas
============================================================ */
/* ---------- 1. Design token ---------- */
:root {
/* Warna semantik, tema terang */
--warna-latar: #faf7f2; --warna-permukaan: #ffffff;
--warna-teks: #1c1917; --warna-teks-lembut: #57534e;
--warna-garis: #e7e5e4; --warna-utama: #be123c;
--warna-utama-pekat: #9f1239; --warna-utama-kontras: #ffffff;
--warna-utama-lembut: #ffe4e6; --warna-utama-tinta: #881337;
--warna-aksen: #0f766e; --warna-aksen-lembut: #ccfbf1;
/* Skala spasi, basis empat dan delapan piksel */
--jarak-1: 4px; --jarak-2: 8px;
--jarak-3: 12px; --jarak-4: 16px;
--jarak-5: 24px; --jarak-6: 32px;
--jarak-7: 48px; --jarak-8: 64px;
/* Radius sudut */
--radius-kecil: 8px; --radius: 14px;
--radius-penuh: 999px;
/* Elevasi bayangan */
--bayangan-1: 0 1px 2px rgba(28, 25, 23, 0.06);
--bayangan-2: 0 8px 20px rgba(28, 25, 23, 0.10);
--bayangan-3: 0 16px 32px rgba(190, 18, 60, 0.16);
/* Tipografi dan gerak */
--font-dasar: system-ui, "Segoe UI", sans-serif;
--tinggi-baris: 1.65;
--font-judul: Georgia, "Times New Roman", serif;
--ukuran-display: clamp(2.2rem, 5vw, 3.2rem);
--ukuran-seksi: clamp(1.45rem, 3vw, 1.85rem);
--durasi: 200ms; --pelunakan: ease-out;
/* Kerangka halaman */
--lebar-isi: 1020px;
}
/* ---------- 2. Base dan reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
body {
margin: 0; font-family: var(--font-dasar); line-height: var(--tinggi-baris);
background-color: var(--warna-latar); color: var(--warna-teks);
}
h1, h2, h3, p, ul { margin: 0; }
img { display: block; max-width: 100%; }
/* ---------- 3. Kerangka halaman ---------- */
.pembungkus {
max-width: var(--lebar-isi);
margin-inline: auto; padding-inline: var(--jarak-4);
}
.laman-kepala {
position: sticky; top: 0; z-index: 20;
padding-block: var(--jarak-3);
background-color: var(--warna-permukaan);
border-bottom: 1px solid var(--warna-garis);
}
.kepala-baris {
display: flex; align-items: center;
justify-content: space-between;
gap: var(--jarak-3); flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: var(--jarak-2); }
.brand img { width: 34px; height: 34px; }
.brand-nama { font-size: 18px; font-weight: 800; letter-spacing: -0.01em; }
.nav-utama { display: flex; gap: var(--jarak-4); }
.nav-utama a { color: var(--warna-teks-lembut); font-size: 15px; font-weight: 600; text-decoration: none; }
.nav-utama a:hover { color: var(--warna-utama); }
/* ---------- 4. Tombol ---------- */
.tombol {
display: inline-block;
padding: 10px 20px; border: none;
border-radius: var(--radius-kecil);
background-color: var(--warna-utama); color: var(--warna-utama-kontras);
font: inherit; font-size: 15px; font-weight: 600;
text-decoration: none; cursor: pointer;
}
.tombol--garis {
border: 1px solid var(--warna-utama);
background-color: transparent; color: var(--warna-utama);
}
/* ---------- 5. Hero dan perkenalan ---------- */
.hero { padding-block: var(--jarak-8) var(--jarak-7); max-width: 680px; }
.hero-pembuka {
font-size: 14px; font-weight: 700;
letter-spacing: 0.14em; text-transform: uppercase;
color: var(--warna-utama);
}
.judul-halaman {
margin-top: var(--jarak-3);
font-family: var(--font-judul);
font-size: var(--ukuran-display);
line-height: 1.15; letter-spacing: -0.02em;
}
.pengantar { margin-top: var(--jarak-4); max-width: 52ch; font-size: 17px; color: var(--warna-teks-lembut); }
.hero-aksi { display: flex; flex-wrap: wrap; gap: var(--jarak-3); margin-top: var(--jarak-5); }
.section-judul { font-size: 24px; font-weight: 800; letter-spacing: -0.01em; }
.perkenalan {
max-width: 62ch; padding-block: var(--jarak-6);
border-top: 1px solid var(--warna-garis);
}
.perkenalan p + p { margin-top: var(--jarak-3); }
/* ---------- 6. Galeri proyek ---------- */
.seksi-karya { margin-top: var(--jarak-7); }
.galeri-proyek {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: var(--jarak-5); margin-top: var(--jarak-5);
}
.kartu-proyek {
overflow: hidden;
background-color: var(--warna-permukaan); border: 1px solid var(--warna-garis);
border-radius: var(--radius); box-shadow: var(--bayangan-1);
}
.sampul { display: grid; place-items: center; aspect-ratio: 16 / 10; }
.sampul--kopi { background: linear-gradient(135deg, #7c2d12, #ea580c); }
.sampul--setor { background: linear-gradient(135deg, #1e3a8a, #3b82f6); }
.sampul--katalog { background: linear-gradient(135deg, #831843, #ec4899); }
.sampul--lumbung { background: linear-gradient(135deg, #134e4a, #14b8a6); }
.sampul--senja { background: linear-gradient(135deg, #312e81, #6366f1); }
.sampul--rupa { background: linear-gradient(135deg, #18181b, #71717a); }
.sampul-huruf { font-size: 64px; font-weight: 800; color: rgba(255, 255, 255, 0.92); }
.kartu-isi { padding: var(--jarak-4) var(--jarak-4) var(--jarak-5); }
.kartu-nama { font-size: 18px; font-weight: 800; }
.kartu-peran { margin-top: 2px; font-size: 13px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--warna-aksen); }
.kartu-catatan { margin-top: var(--jarak-2); font-size: 14.5px; color: var(--warna-teks-lembut); }
/* ---------- 7. Tentang dan keahlian ---------- */
.seksi-tentang { margin-top: var(--jarak-7); }
.tentang-grid {
display: grid; grid-template-columns: 1.4fr 1fr;
gap: var(--jarak-6); margin-top: var(--jarak-4);
}
.tentang-bio p + p { margin-top: var(--jarak-3); }
.tentang-bio p { color: var(--warna-teks-lembut); }
.tentang-label {
font-size: 13px; font-weight: 700;
letter-spacing: 0.1em; text-transform: uppercase;
color: var(--warna-aksen);
}
.daftar-chip {
display: flex; flex-wrap: wrap;
gap: var(--jarak-2); margin-top: var(--jarak-3);
padding: 0; list-style: none;
}
.chip {
padding: 6px 14px;
border: 1px solid var(--warna-garis);
border-radius: var(--radius-penuh);
background-color: var(--warna-permukaan);
font-size: 14px; font-weight: 600;
color: var(--warna-teks-lembut);
}
/* ---------- 8. Kontak ---------- */
.seksi-kontak { margin-top: var(--jarak-7); }
.panel-kontak {
display: grid; justify-items: start;
gap: var(--jarak-3); padding: var(--jarak-7) var(--jarak-6);
border-radius: var(--radius);
background: linear-gradient(135deg, var(--warna-utama-tinta), var(--warna-utama));
color: var(--warna-utama-kontras);
}
.panel-kontak p { max-width: 46ch; color: #ffe4e6; }
.panel-kontak .tombol { background-color: var(--warna-permukaan); color: var(--warna-utama-tinta); }
/* ---------- 9. Footer ---------- */
.laman-kaki {
margin-top: var(--jarak-8); padding-block: var(--jarak-6);
background-color: var(--warna-permukaan);
border-top: 1px solid var(--warna-garis);
}
.kaki-baris {
display: flex; align-items: center;
justify-content: space-between;
gap: var(--jarak-3); flex-wrap: wrap;
font-size: 14px; color: var(--warna-teks-lembut);
}
/* ---------- 10. Navigasi responsif ---------- */
.tombol-nav {
display: none; flex-direction: column;
align-items: center; justify-content: center;
width: 44px; height: 44px; padding: 0;
border: 1px solid var(--warna-garis);
border-radius: var(--radius-kecil);
background-color: var(--warna-permukaan); cursor: pointer;
}
.tombol-nav-garis { position: relative; display: block; width: 20px; height: 2px; background-color: var(--warna-teks); }
.tombol-nav-garis::before, .tombol-nav-garis::after {
content: ""; position: absolute; left: 0;
width: 20px; height: 2px; background-color: var(--warna-teks);
}
.tombol-nav-garis::before { top: -6px; }
.tombol-nav-garis::after { top: 6px; }
.nav-utama a.aktif { color: var(--warna-utama); font-weight: 700; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
/* ---------- 11. Responsif ---------- */
@media (max-width: 720px) {
.tombol-nav { display: flex; }
.nav-utama {
display: none;
flex-direction: column;
gap: var(--jarak-2);
width: 100%;
padding-block: var(--jarak-3);
}
.nav-utama.terbuka { display: flex; }
.hero { padding-block: var(--jarak-7) var(--jarak-6); }
.tentang-grid { grid-template-columns: 1fr; }
.panel-kontak { padding: var(--jarak-6) var(--jarak-4); }
.kaki-baris { justify-content: center; text-align: center; }
}
@media (max-width: 480px) {
.hero-aksi .tombol { width: 100%; text-align: center; }
.kartu-isi { padding: var(--jarak-3) var(--jarak-3) var(--jarak-4); }
.sampul-huruf { font-size: 48px; }
}
/* ---------- 12. Tipografi seksi ---------- */
.section-judul {
font-family: var(--font-judul);
font-size: var(--ukuran-seksi); line-height: 1.25;
}
.section-judul::after {
content: ""; display: block; width: 56px; height: 3px;
margin-top: var(--jarak-2); border-radius: var(--radius-penuh);
background-color: var(--warna-utama);
}
.panel-kontak .section-judul::after { background-color: var(--warna-utama-kontras); }
/* ---------- 13. Keadaan interaksi ---------- */
.tombol { transition: background-color var(--durasi) var(--pelunakan), transform var(--durasi) var(--pelunakan); }
.tombol:hover { background-color: var(--warna-utama-pekat); }
.tombol:active { transform: translateY(1px); }
.tombol--garis:hover { background-color: var(--warna-utama-lembut); }
.panel-kontak .tombol:hover { background-color: var(--warna-utama-lembut); }
.kartu-proyek { transition: box-shadow var(--durasi) var(--pelunakan), transform var(--durasi) var(--pelunakan); }
.kartu-proyek:hover { transform: translateY(-4px); box-shadow: var(--bayangan-3); }
.chip { transition: border-color var(--durasi) var(--pelunakan), background-color var(--durasi) var(--pelunakan); }
.chip:hover { border-color: var(--warna-aksen); background-color: var(--warna-aksen-lembut); }
@keyframes naik-halus {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
.hero > * { animation: naik-halus 640ms var(--pelunakan) backwards; }
.hero > *:nth-child(2) { animation-delay: 90ms; }
.hero > *:nth-child(3) { animation-delay: 180ms; }
.hero > *:nth-child(4) { animation-delay: 270ms; }
/* ---------- 14. Aksesibilitas ---------- */
.tautan-lompat {
position: absolute; top: var(--jarak-3); left: var(--jarak-4); z-index: 30;
padding: var(--jarak-2) var(--jarak-4); border-radius: var(--radius-kecil);
background-color: var(--warna-utama-tinta); color: var(--warna-utama-kontras);
font-weight: 600; text-decoration: none;
transform: translateY(-300%);
}
.tautan-lompat:focus { transform: translateY(0); }
:focus-visible { outline: 3px solid var(--warna-utama-pekat); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
.tombol, .kartu-proyek, .chip { transition: none; }
.hero > * { animation: none; }
.kartu-proyek:hover, .tombol:active { transform: none; }
}/* ============================================================
main.js — navigasi Portofolio Desainer.
Skrip ini membuka dan menutup menu navigasi pada layar sempit,
menyelaraskan aria-expanded pada tombol, dan (mulai Bagian 9)
menandai tautan navigasi yang terakhir dipilih. Tidak ada data
yang disimpan di sisi browser.
============================================================ */
(function () {
"use strict";
var tombolNav = document.getElementById("tombol-nav");
var navUtama = document.getElementById("nav-utama");
/* Buka atau tutup menu, lalu laporkan statusnya ke aria-expanded. */
function aturMenu(terbuka) {
navUtama.classList.toggle("terbuka", terbuka);
tombolNav.setAttribute("aria-expanded", terbuka ? "true" : "false");
}
if (tombolNav && navUtama) {
tombolNav.addEventListener("click", function () {
aturMenu(!navUtama.classList.contains("terbuka"));
});
/* Menu ikut tertutup setelah salah satu tautan dipilih. */
navUtama.addEventListener("click", function (acara) {
if (acara.target.tagName === "A") {
aturMenu(false);
}
});
}
/* Tandai tautan navigasi yang terakhir dipilih. */
var tautanNav = navUtama ? navUtama.querySelectorAll("a") : [];
tautanNav.forEach(function (tautan) {
tautan.addEventListener("click", function () {
tautanNav.forEach(function (item) {
item.classList.remove("aktif");
item.removeAttribute("aria-current");
});
tautan.classList.add("aktif");
tautan.setAttribute("aria-current", "true");
});
});
})();Meletakkan fondasi portofolio: token warna rose-teal, skala spasi basis empat piksel, radius, tiga tingkat bayangan, token gerak, dan base reset minimal.
Buka → # Bagian 2: Hero dan IntroductionMembangun kerangka halaman, tombol, seksi hero perkenalan, dan seksi pengantar, disertai berkas HTML pertama proyek yang tampil sebagai snapshot beranda.html.
Buka → # Bagian 3: Project ShowcaseMembangun galeri enam kartu proyek dengan grid adaptif, sampul gradien berhuruf inisial, label peran, dan kartu yang tetap rapi tanpa satu pun berkas gambar.
Buka → # Bagian 4: Layout dengan Flexbox dan GridMenyusun komposisi halaman dengan dua alat tata letak: grid dua kolom untuk strip tentang-saya, flexbox untuk baris footer, dan panel kontak bergradien sebagai penutup yang mengajak bertindak.
Buka → # Bagian 5: Responsive NavigationMeruntuhkan navigasi ke balik tombol hamburger pada layar sempit, membangun ikonnya dari pseudo-element, dan menulis main.js pertama yang mengelola aria-expanded.
Buka → # Bagian 6: Typography dan Color SystemMenyempurnakan sistem tipografi dengan token skala judul dan huruf serif untuk display, menambah garis aksen di bawah judul seksi, dan menyelaraskan warna label peran.
Buka → # Bagian 7: Animation dan Interaction StatesMemberi umpan balik pada interaksi lewat transisi tombol, kartu, dan chip, lalu menambah animasi masuk hero yang bertingkat dengan keyframes.
Buka → # Bagian 8: AccessibilityMenambah skip link, gaya fokus :focus-visible yang jelas, menaikkan kontras teks lembut agar lolos rasio 4.5:1, dan menghormati preferensi prefers-reduced-motion.
Buka →