Dari Nol Sampai Pro: Bikin Kalkulator dan Page Builder Interaktif Pakai HTML, CSS, JS!

ikramlink Maret 24, 2026
Dari Nol Sampai Pro: Bikin Kalkulator dan Page Builder Interaktif Pakai HTML, CSS, JS!

Halo, bro dan sist para pejuang frontend! Balik lagi nih sama gue, si tukang ngoding yang hobinya ngopi dan ngulik teknologi web. Gimana kabarnya? Semoga semangat ngodingnya makin membara ya! Hari ini kita akan ngobrolin sesuatu yang fundamental tapi super powerfull buat ningkatin skill HTML, CSS, dan JavaScript kita: membangun aplikasi web kalkulator dan page builder sederhana.

Mungkin ada yang mikir, "Ah, kalkulator? Udah sering banget, bro." Atau "Page builder? Kayaknya berat banget, deh!" Eits, tunggu dulu. Dua proyek ini, meskipun kelihatannya beda level, sebenarnya adalah ladang emas buat kita belajar interaksi DOM, event handling, dan manipulasi elemen secara dinamis. Ibaratnya, ini kayak kita belajar abjad dan merangkai kata, sebelum akhirnya bisa nulis novel sendiri. Jadi, yuk kita bedah tuntas!

Kenapa dua proyek ini penting? Dengan bikin kalkulator, kita akan memperkuat pemahaman tentang event listener, manipulasi string, dan logika dasar matematika di JavaScript. Sementara page builder, ini nih yang bikin seru! Kita akan main-main dengan konsep drag-and-drop, manipulasi elemen HTML secara dinamis, dan mungkin sedikit tentang state management sederhana. Ini skill-skill yang wajib banget dikuasai kalau kamu pengen jadi frontend developer yang jago, apalagi kalau mau terjun ke dunia framework kayak React, Vue, atau Angular.

Oke, siapin kopi atau teh kamu, buka VS Code, dan mari kita mulai petualangan koding kita!

Membuat Kalkulator Web Interaktif: Dasar yang Kokoh

Kalkulator adalah salah satu proyek "Hello World" yang lebih kompleks di dunia JavaScript. Tapi jangan salah, di balik kesederhanaannya, banyak banget pelajaran yang bisa kita ambil. Ini adalah kesempatan emas buat melatih otot logika kita.

Struktur HTML untuk Kalkulator

Pertama, kita siapkan fondasi kalkulator kita dengan HTML. Kita butuh sebuah layar untuk menampilkan angka dan hasil, serta tombol-tombol untuk angka (0-9), operator (+, -, *, /), clear (C), dan sama dengan (=). Gue biasanya suka pakai struktur <div> dengan class yang jelas biar gampang di-styling dan di-akses pakai JS nanti.


<div class="calculator">
    <input type="text" class="calculator-screen" value="0" disabled />

    <div class="calculator-keys">
        <button type="button" class="operator" value="+">+</button>
        <button type="button" class="operator" value="-">-</button>
        <button type="button" class="operator" value="*">&times;</button>
        <button type="button" class="operator" value="/">&divide;</button>

        <button type="button" value="7">7</button>
        <button type="button" value="8">8</button>
        <button type="button" value="9">9</button>

        <button type="button" value="4">4</button>
        <button type="button" value="5">5</button>
        <button type="button" value="6">6</button>

        <button type="button" value="1">1</button>
        <button type="button" value="2">2</button>
        <button type="button" value="3">3</button>

        <button type="button" class="decimal" value=".">.</button>
        <button type="button" value="0">0</button>
        <button type="button" class="all-clear" value="clear">AC</button>

        <button type="button" class="equal-sign operator" value="=">=</button>
    </div>
</div>

Perhatikan atribut value di setiap tombol. Ini penting banget karena nanti kita akan pakai nilai ini di JavaScript untuk menentukan tombol apa yang ditekan.

Sentuhan CSS: Biar Gak Polos-polos Amat

Tentu saja, kalkulator kita gak mungkin cuma kotak putih polos. Kita butuh CSS untuk membuatnya terlihat modern dan mudah digunakan. Gaya bebas, bro! Mau pakai flexbox atau grid untuk layout tombolnya? Bebas! Yang penting rapi dan responsive. Gue biasanya suka pakai CSS Grid buat layout kalkulator, soalnya lebih gampang atur baris dan kolomnya. Contoh singkatnya:


.calculator {
    border: 1px solid #ccc;
    border-radius: 5px;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 300px;
    box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
}

.calculator-screen {
    width: 100%;
    font-size: 5rem;
    height: 80px;
    border: none;
    background-color: #252525;
    color: #fff;
    text-align: right;
    padding-right: 20px;
    padding-left: 10px;
    border-radius: 5px 5px 0 0;
}

.calculator-keys {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-gap: 1px;
    background-color: #d3d3d3;
    padding: 1px;
}

.calculator-keys button {
    height: 60px;
    background-color: #fff;
    border: 1px solid #c4c4c4;
    font-size: 2rem;
    color: #333;
    cursor: pointer;
}

.calculator-keys button:hover {
    background-color: #eaeaea;
}

.operator {
    background-color: #f7950c;
    color: #fff;
}

.operator:hover {
    background-color: #ffa22c;
}

.equal-sign {
    background-color: #2e86c1;
    color: #fff;
    grid-column: -2 / -1; /* Ini biar tombol sama dengan ngambil dua kolom */
    grid-row: 2 / span 4; /* Ini biar dia ngambil beberapa baris */
}

.equal-sign:hover {
    background-color: #4da6e7;
}

.all-clear {
    background-color: #d9534f;
    color: #fff;
}

.all-clear:hover {
    background-color: #e36a66;
}

Nah, dengan sedikit CSS Grid dan Flexbox, kalkulator kita sudah mulai terbentuk. Keren, kan? Inilah kenapa CSS itu penting banget, bro. Kodingan sebagus apapun kalau tampilan user-nya berantakan, ya percuma juga.

Logika JavaScript: Otak di Balik Kalkulator

Bagian ini adalah intinya. Kita akan menggunakan JavaScript untuk menghidupkan kalkulator kita. Kita butuh beberapa variabel untuk menyimpan status kalkulator, seperti angka yang sedang ditampilkan, operator yang dipilih, dan angka sebelumnya. Jangan lupa, kita harus menangani setiap klik tombol!


const calculator = document.querySelector('.calculator');
const keys = calculator.querySelector('.calculator-keys');
const display = document.querySelector('.calculator-screen');

let firstValue = null;
let operator = null;
let waitingForSecondValue = false; // Flag untuk menentukan apakah input selanjutnya adalah angka kedua

keys.addEventListener('click', e => {
    if (!e.target.matches('button')) return;

    const key = e.target;
    const action = key.dataset.action; // Kalau mau pake data-action di HTML
    const keyContent = key.value;
    const displayedNum = display.value;

    if (key.classList.contains('number')) { // Asumsi ada class "number"
        if (displayedNum === '0' || waitingForSecondValue) {
            display.value = keyContent;
            waitingForSecondValue = false;
        } else {
            display.value = displayedNum + keyContent;
        }
    }

    if (key.classList.contains('operator')) {
        firstValue = parseFloat(displayedNum);
        operator = keyContent;
        waitingForSecondValue = true;
    }

    if (key.classList.contains('decimal')) {
        if (!displayedNum.includes('.')) {
            display.value = displayedNum + '.';
        }
        if (waitingForSecondValue) { // Handle decimal setelah operator
            display.value = '0.';
            waitingForSecondValue = false;
        }
    }

    if (key.classList.contains('all-clear')) {
        display.value = '0';
        firstValue = null;
        operator = null;
        waitingForSecondValue = false;
    }

    if (key.classList.contains('equal-sign')) {
        if (firstValue === null || operator === null || waitingForSecondValue) return;

        const secondValue = parseFloat(displayedNum);
        let result = 0;

        if (operator === '+') {
            result = firstValue + secondValue;
        } else if (operator === '-') {
            result = firstValue - secondValue;
        } else if (operator === '*') {
            result = firstValue * secondValue;
        } else if (operator === '/') {
            result = firstValue / secondValue;
        }

        display.value = result;
        firstValue = result; // Hasil bisa jadi angka pertama untuk kalkulasi selanjutnya
        operator = null;
        waitingForSecondValue = true; // Siap untuk angka kedua baru
    }
});

Oke, kodingan di atas itu contoh sederhana banget ya. Kamu harus tambahin class number di tombol angka dan perbaiki sedikit bagian key.classList.contains('number') agar sesuai dengan HTML di atas yang pakai value. Intinya adalah bagaimana kita menangani input, menyimpan state, dan melakukan operasi matematika. Tantangan di sini biasanya muncul saat kita berurusan dengan floating point numbers (angka desimal) atau operator precedence (mana yang dihitung duluan kalau ada perkalian dan penjumlahan). Dulu, gue pernah pusing tujuh keliling cuma gara-gara angka desimal di JavaScript jadi aneh, contohnya 0.1 + 0.2 kok bisa jadi 0.30000000000000004. Untungnya ada trik pembulatan atau pakai library khusus kalau butuh presisi tinggi.

Membangun Page Builder Sederhana: Interaksi Tingkat Lanjut

Nah, kalau kalkulator sudah beres, sekarang kita naik level! Kita akan coba bikin page builder sederhana. Ini bukan page builder kayak Elementor atau Beaver Builder ya, tapi konsep dasarnya, yaitu drag-and-drop elemen dan manipulasi konten secara dinamis.

Konsep Dasar Page Builder

Page builder yang akan kita buat ini akan memiliki tiga bagian utama:

  1. Toolbox/Palette: Tempat elemen-elemen yang bisa di-drag (misal: Text Block, Image Block, Button).
  2. Canvas: Area tempat kita meletakkan dan mengatur elemen-elemen dari toolbox. Ini adalah area dropzone kita.
  3. Property Panel (Opsional): Panel untuk mengedit properti elemen yang terpilih di canvas (misal: warna teks, ukuran font, URL gambar). Untuk artikel ini, kita fokus ke drag-and-drop dan menambahkan elemen dulu ya biar gak terlalu panjang.

Struktur HTML untuk Page Builder

Sama seperti kalkulator, kita mulai dengan fondasi HTML. Kali ini, strukturnya akan sedikit lebih kompleks karena ada beberapa area interaktif.


<div class="page-builder-container">
    <div class="toolbox">
        <h3>Elemen</h3>
        <div class="draggable-item" draggable="true" data-type="text">Text Block</div>
        <div class="draggable-item" draggable="true" data-type="image">Image Block</div>
        <div class="draggable-item" draggable="true" data-type="button">Button Block</div>
    </div>

    <div class="canvas" id="drop-zone">
        <h3>Seret Elemen ke Sini</h3>
    </div>
</div>

Perhatikan atribut draggable="true" pada setiap elemen di toolbox. Ini yang akan memungkinkan kita untuk menyeret elemen-elemen tersebut. Atribut data-type juga penting untuk mengidentifikasi jenis elemen saat kita menambahkannya ke canvas.

Sentuhan CSS untuk Page Builder

CSS untuk page builder ini fokus pada layout toolbox dan canvas, serta memberikan visual feedback saat elemen di-drag atau saat masuk ke area dropzone. Ini kunci banget buat user experience. Gue biasanya pakai border atau box-shadow biar keliatan mana yang bisa di-drop.


.page-builder-container {
    display: flex;
    margin-top: 50px;
    width: 100%;
    max-width: 1200px;
    margin-left: auto;
    margin-right: auto;
    border: 1px solid #eee;
    min-height: 700px;
    box-shadow: 0 0 15px rgba(0,0,0,0.05);
}

.toolbox {
    width: 250px;
    background-color: #f8f8f8;
    padding: 20px;
    border-right: 1px solid #eee;
}

.toolbox h3 {
    margin-top: 0;
    color: #333;
}

.draggable-item {
    padding: 10px 15px;
    margin-bottom: 10px;
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 4px;
    cursor: grab;
    transition: all 0.2s ease;
}

.draggable-item:hover {
    background-color: #eef;
    border-color: #bbd;
}

.canvas {
    flex-grow: 1;
    background-color: #fff;
    padding: 20px;
    border: 2px dashed transparent; /* Awalnya transparan */
    transition: border-color 0.2s ease;
}

.canvas.drag-over {
    border-color: #007bff; /* Warna border saat ada elemen di atasnya */
    background-color: #f0f8ff;
}

/* Styling untuk elemen yang sudah di-drop di canvas */
.canvas .dropped-element {
    background-color: #f9f9f9;
    border: 1px solid #ccc;
    padding: 15px;
    margin-bottom: 10px;
    position: relative;
    min-height: 50px;
    cursor: move;
}

.canvas .dropped-element.text-block::before {
    content: "Text Block";
    font-size: 0.8em;
    color: #888;
    position: absolute;
    top: 5px;
    right: 5px;
}

.canvas .dropped-element.image-block::before {
    content: "Image Block";
    font-size: 0.8em;
    color: #888;
    position: absolute;
    top: 5px;
    right: 5px;
}

.canvas .dropped-element.button-block::before {
    content: "Button Block";
    font-size: 0.8em;
    color: #888;
    position: absolute;
    top: 5px;
    right: 5px;
}

CSS di atas memberi kita visual yang lumayan bagus. Kita juga menambahkan kelas .drag-over yang nanti akan di-toggle oleh JavaScript untuk memberikan indikasi visual saat elemen siap di-drop. Ingat, UX itu penting banget, bro! Pengguna harus tahu kapan mereka bisa melakukan aksi.

Logika JavaScript: Menghidupkan Drag-and-Drop

Nah, ini bagian paling seru! Kita akan pakai Drag and Drop API bawaan browser untuk membuat elemen bisa diseret dan diletakkan. Ada beberapa event yang perlu kita tangani:

  • dragstart: Saat elemen mulai diseret. Kita akan menyimpan data elemen yang diseret.
  • dragover: Saat elemen diseret di atas area dropzone. Ini untuk mencegah browser melakukan default action (biasanya membuka file yang di-drag).
  • dragleave: Saat elemen meninggalkan area dropzone.
  • drop: Saat elemen dijatuhkan di area dropzone. Di sini kita akan menambahkan elemen ke canvas.

const draggables = document.querySelectorAll('.draggable-item');
const dropZone = document.getElementById('drop-zone');

let draggedItem = null; // Untuk menyimpan elemen yang sedang di-drag

draggables.forEach(item => {
    item.addEventListener('dragstart', (e) => {
        draggedItem = e.target;
        e.dataTransfer.setData('text/plain', e.target.dataset.type); // Kirim data type elemen
        console.log('Drag started for:', draggedItem.dataset.type);
    });
});

dropZone.addEventListener('dragover', (e) => {
    e.preventDefault(); // Penting! Mencegah default action (misal: membuka link)
    dropZone.classList.add('drag-over'); // Beri visual feedback
});

dropZone.addEventListener('dragleave', () => {
    dropZone.classList.remove('drag-over'); // Hilangkan visual feedback
});

dropZone.addEventListener('drop', (e) => {
    e.preventDefault(); // Mencegah default action
    dropZone.classList.remove('drag-over');

    const dataType = e.dataTransfer.getData('text/plain');
    console.log('Dropped item type:', dataType);

    // Buat elemen baru berdasarkan dataType
    let newElement;
    if (dataType === 'text') {
        newElement = document.createElement('p');
        newElement.textContent = 'Ini adalah blok teks. Klik untuk mengedit.';
        newElement.classList.add('dropped-element', 'text-block');
        newElement.contentEditable = true; // Bisa diedit langsung
    } else if (dataType === 'image') {
        newElement = document.createElement('img');
        newElement.src = 'https://via.placeholder.com/150'; // Placeholder image
        newElement.alt = 'Image Placeholder';
        newElement.classList.add('dropped-element', 'image-block');
        newElement.style.maxWidth = '100%';
        newElement.style.height = 'auto';
    } else if (dataType === 'button') {
        newElement = document.createElement('button');
        newElement.textContent = 'Klik Saya';
        newElement.classList.add('dropped-element', 'button-block');
        newElement.contentEditable = true;
        newElement.style.padding = '10px 20px';
        newElement.style.backgroundColor = '#007bff';
        newElement.style.color = '#fff';
        newElement.style.border = 'none';
        newElement.style.borderRadius = '5px';
        newElement.style.cursor = 'pointer';
    }

    if (newElement) {
        dropZone.appendChild(newElement);
    }
});

Dengan kode di atas, kita sudah punya page builder sederhana yang bisa drag-and-drop elemen dari toolbox ke canvas. Elemen teks bahkan bisa langsung diedit di tempat karena kita pakai contentEditable="true". Keren, kan? Ini baru dasarnya, bro. Kita bisa tambahin fitur resize, delete, move di dalam canvas, atau bahkan menyimpan layout ke Local Storage atau server. Dunia frontend itu luas banget!

Dulu pas gue pertama kali ngulik drag-and-drop, rasanya kayak lagi sulap. "Kok bisa ya elemen pindah-pindah gini?!" Tapi setelah paham event dragstart, dragover, dan drop, ternyata logika dasarnya cukup straightforward. Yang bikin rumit itu kalau kita mau bikin interaksi yang super smooth dan responsif, apalagi kalau elemennya kompleks atau ada banyak. Di situlah kita akan mulai mikirin performance optimization dan mungkin pakai library khusus seperti Draggable.js atau Dnd-kit di React.

Menggabungkan Kekuatan: Belajar dari Keduanya

Mungkin kamu mikir, "Apa hubungannya kalkulator sama page builder, bro?" Eits, jangan salah. Kedua proyek ini mengasah fundamental yang sama: interaksi DOM, event handling, dan manipulasi data di JavaScript. Dari kalkulator, kita belajar bagaimana mengelola state (angka pertama, operator, dll) dan melakukan logika perhitungan. Dari page builder, kita belajar bagaimana memanipulasi struktur DOM secara dinamis (menambah, menghapus, mengedit elemen) dan menangani interaksi yang lebih kompleks seperti drag-and-drop.

Bayangkan kalau kamu bisa gabungin keduanya: bikin komponen kalkulator di page builder kamu! Atau bahkan bikin page builder yang elemennya itu form builder, di mana ada kalkulasi di dalamnya. Keren banget, kan? Kemungkinan kreatifnya tanpa batas!

Tips Tambahan buat Kamu

  • Jangan takut error: Error itu teman terbaik saat ngoding. Dia ngasih tahu di mana letak masalahnya. Baca pesan error-nya baik-baik, jangan cuma panik.
  • Debugging itu seni: Gunakan console.log() secara bijak untuk melacak nilai variabel. Pakai juga fitur Developer Tools di browser, breakpoint itu penyelamat!
  • Iterasi kecil: Jangan coba bikin semuanya sekaligus. Bikin fitur kecil dulu, pastikan jalan, baru tambahin fitur lain. Ini prinsip penting dalam pengembangan software.
  • Refactor, refactor, refactor: Setelah kodinganmu jalan, luangkan waktu untuk merapikan dan menyederhanakan kode. Ini bikin kode lebih mudah dibaca dan di-maintain.

Penutup: Terus Berkarya, Terus Belajar!

Gimana, bro dan sist? Semoga artikel ini bisa jadi inspirasi buat kamu yang lagi belajar frontend development. Dengan HTML, CSS, dan JavaScript saja, kita sudah bisa bikin aplikasi yang interaktif dan cukup kompleks. Ini bukti bahwa dasar-dasar itu penting banget!

Proyek kalkulator dan page builder ini cuma permulaan. Setelah ini, kamu bisa eksplorasi lebih jauh. Mungkin tambahin fitur undo/redo di page builder, atau bikin kalkulator yang bisa menyimpan riwayat perhitungan. Ingat, perjalanan belajar ngoding itu maraton, bukan sprint. Yang penting konsisten, terus ngulik, dan jangan pernah berhenti mencoba. Kalau ada pertanyaan atau mau curhat pengalaman ngoding, jangan sungkan tinggalkan komentar di bawah ya!

Sampai jumpa di artikel selanjutnya, ya! Tetap semangat ngoding dan jangan lupa ngopi!