
Slicing desain dari Figma ke HTML kelihatannya simpel — susun elemen, pasang teks, selesai.
Tapi saat ketemu detail kecil seperti spasi antar elemen dan struktur grid, baru terasa semakin kompleks.
Di artikel ini, kita bakal belajar bareng tentang slicing halaman pilih kursi pesawat dari Figma ke HTML menggunakan Tailwind CSS.
Layout-nya unik: dua sisi kursi dengan jalan kosong di tengah, jadi tidak bisa asal pakai grid standar.
Kita akan susun semua ini cukup dengan satu halaman sederhana, tanpa tambahan macam-macam.
Sebelum mulai slicing, ada baiknya kita pahami dulu struktur layout dari desain yang mau kita buat. Kita bisa download desain figma-nya melalui Shaynakit. Kalau asal langsung masuk bikin HTML, biasanya bakal kebingungan di tengah jalan — entah karena grid yang salah, spasi yang tidak pas, atau alignment yang mulai berantakan.
Dengan ngerti dulu pola layout-nya, kita bisa susun struktur dasar HTML dan CSS lebih tenang, tanpa harus bolak-balik revisi.
Memahami Layout dari Figma
Sebelum mulai slicing ke HTML, kita perlu pahami dulu pola layout yang ada di desain.

Ini penting supaya struktur yang kita buat nanti tidak asal tumpuk dan gampang diatur.
Kalau dilihat dari desain Figma-nya, layout halaman pilih kursi ini punya pola seperti ini:
- Ada dua sisi utama: sisi kiri dan sisi kanan pesawat.
- Masing-masing sisi punya dua kolom kursi.
- Di tengah-tengah ada spasi kosong yang berfungsi sebagai jalan antar kursi.
Kalau dihitung, satu baris akan terdiri dari empat kursi, tapi tidak sejajar penuh karena ada ruang kosong di tengah.
Artinya, kalau kita langsung pakai grid biasa (seperti grid-cols-4
), jarak antar kursi akan terlalu rapat dan jalan di tengah tidak akan terlihat. Juga, kalau kita pakai grid-cols-5
maka setiap kolom akan punya lebar yang sama dan akan terlihat kurang proporsional jika dibandingkan dengan desain figma.
Kita perlu bikin trik tambahan supaya ada "spacer" di antara dua sisi kursi ini.
Menyusun Struktur HTML Dasar
Setelah memahami pola layout dari desain, sekarang kita mulai susun struktur HTML dasarnya.
Untuk setup awal, kita sudah siapkan file index.html
sederhana dengan Tailwind CSS dan font Poppins dari Google Fonts.
Berikut struktur dasarnya:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<!-- font Poppins -->
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" />
</head>
<body class="font-['Poppins'] bg-[#dae1e9]">
<div id="Mobile-Layout-Container" class="w-full max-w-[640px] min-w-0 overflow-x-hidden mx-auto min-h-screen relative bg-[#FAFAFA]">
<!-- Content -->
</div>
</body>
</html>
Penjelasan singkat:
- Tailwind CSS kita load menggunakan CDN supaya lebih simple.
- Font Poppins langsung dipasang di
<head>
, dan dipakai lewat Tailwindfont-['Poppins']
. - Background warna abu-abu muda (
bg-[#dae1e9]
) untuk area luar. - Container utama (
#Mobile-Layout-Container
) dibuat responsif hanya di lebar tertentu, supaya desain tetap terpusat dan konsisten. - Konten halaman nantinya akan kita taruh di dalam
<div id="Mobile-Layout-Container">...</div>
ini.
Untuk saat ini, struktur ini cukup dan siap dipakai buat membangun layout kursi pesawat.
Membuat Bagian Judul dan Keterangan Status Kursi
Sebelum membangun layout kursi, kita tambahkan dulu elemen header di bagian atas. Header ini berfungsi untuk menampilkan judul halaman dan informasi status kursi yang tersedia.
Berikut struktur HTML yang akan kita gunakan:
<h1 class="font-semibold text-2xl text-[#1F1449] pt-[30px] mx-6">Select Your <br> Favorite Seat</h1>
<div class="flex items-center gap-[10px] mt-[30px] mx-6">
<div class="flex items-center gap-[6px]">
<div class="flex shrink-0 size-4 rounded-[6px] border border-[#5C40CC] bg-[#E0D9FF]"></div>
<span class="text-sm">Available</span>
</div>
<div class="flex items-center gap-[6px]">
<div class="flex shrink-0 size-4 rounded-[6px] border border-[#5C40CC] bg-[#5C40CC]"></div>
<span class="text-sm">Selected</span>
</div>
<div class="flex items-center gap-[6px]">
<div class="flex shrink-0 size-4 rounded-[6px] bg-[#EBECF1]"></div>
<span class="text-sm">Unavailable</span>
</div>
</div>
Penjelasan singkat:
- Judul halaman ditampilkan menggunakan elemen
<h1>
. - Keterangan status kursi menggunakan kombinasi
flex
untuk membuat item sejajar horizontal. - Setiap status memiliki:
- Kotak kecil berwarna (untuk indikator visual)
- Label teks di sebelahnya
Semua styling sudah menggunakan kelas bawaan Tailwind, jadi bisa langsung digunakan tanpa tambahan kustomisasi lagi.
Jika semua sudah benar, maka tampilan kita akan terlihat seperti ini

Membuat Seat Map (Tahap 1): Struktur Dasar dan Baris Pertama
Setelah bagian header beres, sekarang kita mulai bangun seat map.
Karena strukturnya unik (dua sisi dengan jalan di tengah), kita akan susun perlahan — dimulai dari container utama, label baris, dan satu baris kursi.
1. Container Seat Map
Pertama, kita butuh sebuah container untuk membungkus seluruh bagian seat map ini.
Kita akan pakai elemen <form>
karena nanti seat ini bisa dikaitkan ke proses submit (meskipun sekarang belum ada backend-nya).
<form action="" class="mt-[30px]">
<div class="flex flex-col mx-6 gap-[30px] w-auto h-fit rounded-[18px] bg-white py-[30px] px-[22px]">
<div class="flex flex-col gap-4">
<!-- Seat content di sini -->
</div>
<div class="flex flex-col gap-4">
<!-- Keterangan pilihan di sini -->
</div>
</div>
<!-- Button submit -->
</form>
2. Label Kolom Kursi (A, B, C, D)
Di dalam form, kita mulai dengan baris label yang menunjukkan kolom kursi: A, B (sisi kiri), dan C, D (sisi kanan).
Di tengah-tengah kita beri elemen kosong sebagai spacer, seolah-olah itu adalah lorong pesawat.
<div id="Seat-Column" class="row flex flex-row justify-evenly">
<div class="grid grid-cols-2 gap-4">
<div class="flex items-center justify-center h-6 w-12 shrink-0">
<span class="text-[#9698A9]">A</span>
</div>
<div class="flex items-center justify-center h-6 w-12 shrink-0">
<span class="text-[#9698A9]">B</span>
</div>
</div>
<div class="spacer w-12 flex shrink-0 text-[#9698A9] flex items-center justify-center"></div>
<div class="grid grid-cols-2 gap-4">
<div class="flex items-center justify-center h-6 w-12 shrink-0">
<span class="text-[#9698A9]">C</span>
</div>
<div class="flex items-center justify-center h-6 w-12 shrink-0">
<span class="text-[#9698A9]">D</span>
</div>
</div>
</div>

3. Satu Baris Kursi (Baris 1)
Setelah label kolom, kita buat satu baris kursi.
Strukturnya sama seperti sebelumnya — dua grid kiri dan kanan dengan spacer di tengah.
<div class="row flex flex-row justify-evenly">
<div class="grid grid-cols-2 gap-4">
<!-- Kursi A1 dan B1 -->
<label class="group relative flex items-center justify-center size-12 shrink-0 rounded-[15px] overflow-hidden bg-[#E0D9FF] border-2 border-[#5C40CC] has-[:checked]:border-0 has-[:checked]:bg-[#5C40CC] has-[:disabled]:border-0 has-[:disabled]:bg-[#EBECF1] transition-all duration-300">
<input type="checkbox" name="seat" class="absolute inset-0 opacity-0">
<span class="font-semibold text-sm text-white opacity-0 group-has-[:checked]:opacity-100 transition-all duration-300">YOU</span>
</label>
<label class="group relative flex items-center justify-center size-12 shrink-0 rounded-[15px] overflow-hidden bg-[#E0D9FF] border-2 border-[#5C40CC] has-[:checked]:border-0 has-[:checked]:bg-[#5C40CC] has-[:disabled]:border-0 has-[:disabled]:bg-[#EBECF1] transition-all duration-300">
<input type="checkbox" name="seat" class="absolute inset-0 opacity-0">
<span class="font-semibold text-sm text-white opacity-0 group-has-[:checked]:opacity-100 transition-all duration-300">YOU</span>
</label>
</div>
<div class="spacer w-12 flex shrink-0 text-[#9698A9] flex items-center justify-center">
1
</div>
<div class="grid grid-cols-2 gap-4">
<!-- Kursi C1 dan D1 -->
<label class="group relative flex items-center justify-center size-12 shrink-0 rounded-[15px] overflow-hidden bg-[#E0D9FF] border-2 border-[#5C40CC] has-[:checked]:border-0 has-[:checked]:bg-[#5C40CC] has-[:disabled]:border-0 has-[:disabled]:bg-[#EBECF1] transition-all duration-300">
<input type="checkbox" disabled name="seat" class="absolute inset-0 opacity-0">
<span class="font-semibold text-sm text-white opacity-0 group-has-[:checked]:opacity-100 transition-all duration-300">YOU</span>
</label>
<label class="group relative flex items-center justify-center size-12 shrink-0 rounded-[15px] overflow-hidden bg-[#E0D9FF] border-2 border-[#5C40CC] has-[:checked]:border-0 has-[:checked]:bg-[#5C40CC] has-[:disabled]:border-0 has-[:disabled]:bg-[#EBECF1] transition-all duration-300">
<input type="checkbox" name="seat" class="absolute inset-0 opacity-0">
<span class="font-semibold text-sm text-white opacity-0 group-has-[:checked]:opacity-100 transition-all duration-300">YOU</span>
</label>
</div>
</div>
4. Kenapa Pakai <label>
+ input type="checkbox"
?
Setiap kursi dibuat dengan struktur <label>
yang membungkus <input type="checkbox">
.
Kenapa? Karena:
- Dengan
<label>
, kita bisa klik elemen visual (kursi) dan otomatis aktifkan checkbox-nya. - Checkbox ini kita sembunyikan (
opacity-0
), dan hanya dipakai untuk nyimpan status “selected” secara visual. - Style akan berubah sesuai status
:checked
atau:disabled
.
5. Styling Dinamis: has-[:checked]
dan group-has-[]
Tailwind punya fitur CSS parent selector yang powerful. Di sini kita pakai dua hal:
✅ has-[:checked]
- Digunakan langsung di elemen label.
- Artinya: kalau input di dalamnya
checked
, ubah style si label. - Contoh:
has-[:checked]:bg-[#5C40CC]
✅ group
+ group-has-[:checked]
- Kita pakai ini untuk ubah style anak elemen (span teks “YOU”) kalau input di dalam label
checked
. group
ada di label,group-has-[]
ada di dalamnya.- Contoh:
<span class="group-has-[:checked]:opacity-100">YOU</span>
6. Kursi Unavailable
Kita juga tambahkan atribut disabled
ke input untuk kursi yang tidak tersedia.
Tailwind akan baca has-[:disabled]
dan ubah warnanya jadi abu-abu (seperti di desain).
7. Menambah bagian keterangan pilihan
Seat map sudah selesai kita buat, sekarang kita tambah bagian keterangan. bagian ini akan menunjukan nomor kursi yang dipilih dan juga total harga yang ahrus dibayar.
<div class="flex items-center justify-between">
<p class="font-light text-sm text-[#9698A9]">Your seat</p>
<p class="text-[#1F1449]">A1, D2</p>
</div>
<div class="flex items-center justify-between">
<p class="font-light text-sm text-[#9698A9]">Total</p>
<p class="font-semibold text-[#5C40CC]">$50,250</p>
</div>
Preview Layout

Menambahkan Tombol Submit di Bawah Layar
Setelah semua elemen kursi selesai ditampilkan, sekarang kita tambahkan tombol untuk mengonfirmasi pilihan kursi. Tapi bukan sembarang tombol — kita ingin tombol ini selalu terlihat di bagian bawah layar, tanpa harus scroll-scroll ke bawah lagi.
Untuk itu, kita gunakan position: fixed
dan menempatkan tombol dengan:
<div class="relative w-full mt-[30px] h-[101px] px-6">
<div class="fixed bottom-[46px] max-w-[640px] w-full transform -translate-x-1/2 left-1/2 px-6">
<button type="submit" class="w-full rounded-full text-center h-[55px] bg-[#5C40CC] text-white align-middle font-medium text-lg">Select Payment</button>
</div>
</div>
Cara ini bikin tombol selalu nempel di bagian bawah layar, pas di tengah, dan tetap berada di dalam lebar maksimal layout (640px
). Tombolnya dibungkus dengan <div>
yang punya relative
layout agar tetap konsisten kalau suatu saat kamu mau tambahkan elemen lain di bawahnya.
Dan jangan lupa: walau posisinya fixed, tombol ini masih di dalam tag <form>
supaya tetap bisa submit data nantinya.

Membuat Kursi Secara Dinamis dengan JavaScript
Setelah kita lihat struktur HTML awal untuk baris kursi, mungkin sudah mulai terasa satu hal: kalau kita harus tulis manual satu per satu, bakal makan waktu dan nyusahin banget.
Makanya, di bagian ini kita akan mulai pakai JavaScript untuk bikin seat map-nya secara dinamis.
Tapi supaya seat-nya bisa dirender lewat JS, kita perlu sediakan dulu tempat penampungnya di HTML.
Kita hapus dulu elemen <div class="row ...">
yang sebelumnya kita hardcode, dan ganti dengan elemen kosong seperti ini:
<div id="Seat-Wrapper" class="flex flex-col gap-4"></div>
Elemen ini akan kita jadikan target untuk inject baris-baris kursi nantinya. Jadi alur kerjanya, JavaScript akan melakukan looping berdasarkan data kursi, lalu menyusun elemen HTML kursinya, dan akhirnya menampilkannya ke dalam #Seat-Wrapper
.
Dengan pendekatan ini, kita bisa kontrol seat map lebih fleksibel — entah itu buat nambah jumlah kursi, menandai yang unavailable, atau nunjukin kursi yang dipilih.
Sekarang kita masuk ke tahap bikin looping untuk render kursi secara dinamis pakai JavaScript. Tujuannya jelas: biar kita tidak nulis <label>
seat satu-satu secara manual — repot dan rawan typo. Dengan data sederhana berupa array nested, kita bisa buat struktur kursi otomatis, lengkap dengan spacer di tengah.
Berikut paragraf penjelasan + contoh kodenya yang bisa kamu pakai:
Supaya lebih fleksibel dan tidak perlu nulis elemen satu per satu, sekarang kita akan membuat seat map-nya dengan JavaScript. Caranya: kita buat dulu struktur data yang mewakili posisi kursi, lalu render ke DOM pakai loop.
Sebagai contoh, kita bisa bikin array seperti ini:
const seatRows = [
['A1', 'B1', 'C1', 'D1'],
['A2', 'B2', 'C2', 'D2'],
['A3', 'B3', 'C3', 'D3'],
// Tambah terus sesuai jumlah baris
];
Lalu kita looping setiap baris dan bagi jadi dua sisi (kiri dan kanan), dengan spacer di tengah:
const seatContainer = document.querySelector('#Seat-Wrapper');
seatRows.forEach(row => {
const rowDiv = document.createElement('div');
rowDiv.className = 'row flex flex-row justify-evenly';
const leftSide = document.createElement('div');
leftSide.className = 'grid grid-cols-2 gap-4';
row.slice(0, 2).forEach(seat => {
leftSide.appendChild(createSeatElement(seat));
});
const spacer = document.createElement('div');
spacer.className = 'spacer w-12 flex shrink-0 text-[#9698A9] flex items-center justify-center';
spacer.textContent = row[0].replace(/\D/g, ''); // ambil angka baris dari seat (misal '1' dari 'A1')
const rightSide = document.createElement('div');
rightSide.className = 'grid grid-cols-2 gap-4';
row.slice(2).forEach(seat => {
rightSide.appendChild(createSeatElement(seat));
});
rowDiv.appendChild(leftSide);
rowDiv.appendChild(spacer);
rowDiv.appendChild(rightSide);
seatContainer.appendChild(rowDiv);
});
Fungsi createSeatElement ini bertugas bikin satu elemen <label> kursi sesuai style yang kita mau:
function createSeatElement(label, disabled = false) {
const wrapper = document.createElement('label');
wrapper.className = 'group relative flex items-center justify-center size-12 shrink-0 rounded-[15px] overflow-hidden bg-[#E0D9FF] border-2 border-[#5C40CC] has-[:checked]:border-0 has-[:checked]:bg-[#5C40CC] has-[:disabled]:border-0 has-[:disabled]:bg-[#EBECF1] transition-all duration-300';
const input = document.createElement('input');
input.type = 'checkbox';
input.name = 'seat';
input.className = 'absolute inset-0 opacity-0';
if (disabled) input.disabled = true;
const span = document.createElement('span');
span.className = 'font-semibold text-sm text-white opacity-0 group-has-[:checked]:opacity-100 transition-all duration-300';
span.textContent = 'YOU';
wrapper.appendChild(input);
wrapper.appendChild(span);
return wrapper;
}
Dengan cara ini, kamu bisa dengan mudah nambah atau ubah barisan kursi cukup dari array-nya aja. Bahkan bisa diambil dari API nanti kalau memang perlu.
Simpan kode JavaScript ini dalam file .js
terpisah atau masukkan langsung di dalam tag <script>
pada template HTML kita.
Jika javascript sudah benar, maka tampilannya akan seperti ini.

Dengan kode untuk looping kursi yang sudah selesai, kita hampir sampai pada bagian akhir proses slicing layout kursi pesawat sesuai desain Figma—dari struktur HTML, styling menggunakan Tailwind CSS, hingga interaksi dinamis menggunakan JavaScript. Untuk saat ini, kita memang hanya fokus pada bagian frontend statis, tanpa menyentuh responsif atau backend logic. Namun, dengan struktur ini, kita sudah punya dasar visual yang solid yang dapat dikembangkan lebih lanjut sesuai kebutuhan.
Penutup dan Saran
Proses slicing desain Figma ke dalam HTML menggunakan Tailwind CSS dan menambahkan interaksi dengan JavaScript ini memberikan kita banyak pelajaran penting. Mulai dari cara menyusun struktur HTML yang rapi, penggunaan Tailwind untuk styling secara efisien, hingga implementasi logika dinamis untuk memilih kursi—semua saling berinteraksi untuk membentuk tampilan yang lebih fungsional.
Dengan pendekatan ini, kita telah membangun dasar yang kokoh untuk antarmuka pemilihan kursi yang siap dikembangkan lebih lanjut, baik untuk tambahan fitur interaktif maupun pengembangan backend di tahap berikutnya.
Belajar membuat elemen dinamis ini memang menantang, dan mungkin ada saat-saat di mana kamu merasa stuck atau kesulitan. Tapi, jangan khawatir—setiap tantangan adalah kesempatan untuk mengasah kemampuan.
Jika kamu merasa butuh bantuan lebih lanjut atau ingin memperdalam materi, jangan ragu untuk mencari mentor yang berpengalaman di BuildWithAngga. Program mentoring mereka menawarkan berbagai keuntungan:
✅ Akses Materi Seumur Hidup – Belajar kapan pun, tanpa batas waktu.
✅ Sertifikat Resmi – Validasi skill yang kamu kuasai.
✅ Portfolio Nyata – Kerjakan project dengan standar industri.
✅ Akses Komunitas dan Mentor – Diskusi langsung dengan praktisi yang sudah berpengalaman.
Jangan takut untuk melangkah lebih jauh. Bangun fondasi yang kuat sekarang, dan siapkan dirimu menghadapi tantangan yang lebih besar di dunia web development. 🚀