Project HTML CSS JavaScript: Product Filter dan Search (Lengkap dengan Code & Gambar Online)
Membuat sistem filter dan pencarian produk adalah komponen penting untuk e-commerce atau website katalog produk. Dalam panduan ini, kita akan membangun:
✅ Tampilan produk dengan gambar online
✅ Fitur pencarian real-time
✅ Filter berdasarkan kategori & harga
✅ Tampilan responsive
✅ Animasi interaktif
Kita akan menggunakan API dummy untuk gambar produk agar tidak perlu mendownload gambar secara manual.
Struktur Proyek
/product-filter │── index.html │── style.css │── script.js
1. File HTML (index.html)
<!DOCTYPE html> <html lang="id"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Filter & Pencarian Produk - Azroi</title> <link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> </head> <body> <div class="container"> <header> <h1><i class="fas fa-filter"></i> Filter Produk</h1> <div class="search-container"> <input type="text" id="searchInput" placeholder="Cari produk..."> <i class="fas fa-search"></i> </div> </header> <div class="filter-container"> <div class="filter-section"> <h3>Kategori</h3> <div class="filter-options"> <label><input type="checkbox" name="category" value="elektronik" checked> Elektronik</label> <label><input type="checkbox" name="category" value="fashion"> Fashion</label> <label><input type="checkbox" name="category" value="makanan"> Makanan</label> <label><input type="checkbox" name="category" value="perabotan"> Perabotan</label> </div> </div> <div class="filter-section"> <h3>Harga</h3> <div class="price-range"> <input type="range" id="priceRange" min="0" max="5000000" value="5000000"> <span id="priceValue">Rp 5.000.000+</span> </div> </div> <button id="resetFilters">Reset Filter</button> </div> <main class="products-container" id="productsContainer"> <!-- Produk akan dimuat via JavaScript --> </main> <footer> <p>© 2025 Product Filter | Azroi</p> </footer> </div> <script src="script.js"></script> </body> </html>
2. File CSS (style.css)
/* Reset & Base Styles */ * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background-color: #f5f5f7; color: #333; line-height: 1.6; } .container { max-width: 1200px; margin: 0 auto; padding: 20px; } /* Header Styles */ header { text-align: center; margin-bottom: 30px; padding: 20px; background: white; border-radius: 10px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); } header h1 { font-size: 2rem; margin-bottom: 15px; color: #2c3e50; display: flex; align-items: center; justify-content: center; gap: 10px; } .search-container { position: relative; max-width: 500px; margin: 0 auto; } .search-container input { width: 100%; padding: 12px 20px; padding-left: 45px; border: 1px solid #ddd; border-radius: 50px; font-size: 1rem; outline: none; transition: all 0.3s; } .search-container input:focus { border-color: #3498db; box-shadow: 0 0 10px rgba(52, 152, 219, 0.2); } .search-container i { position: absolute; left: 15px; top: 50%; transform: translateY(-50%); color: #7f8c8d; } /* Filter Container */ .filter-container { background: white; padding: 20px; border-radius: 10px; margin-bottom: 30px; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); } .filter-section { margin-bottom: 20px; } .filter-section h3 { margin-bottom: 15px; color: #2c3e50; font-size: 1.1rem; } .filter-options { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; } .filter-options label { display: flex; align-items: center; gap: 8px; cursor: pointer; padding: 8px; border-radius: 5px; transition: background 0.3s; } .filter-options label:hover { background: #f1f1f1; } .price-range { padding: 0 10px; } .price-range input[type="range"] { width: 100%; margin: 15px 0; -webkit-appearance: none; height: 8px; border-radius: 5px; background: #ddd; outline: none; } .price-range input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; border-radius: 50%; background: #3498db; cursor: pointer; } #priceValue { display: block; text-align: center; font-weight: bold; color: #3498db; } #resetFilters { background: #e74c3c; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; font-weight: 500; transition: all 0.3s; display: block; margin: 20px auto 0; } #resetFilters:hover { background: #c0392b; transform: translateY(-2px); } /* Products Container */ .products-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 25px; } .product-card { background: white; border-radius: 10px; overflow: hidden; box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05); transition: all 0.3s; } .product-card:hover { transform: translateY(-5px); box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); } .product-image { width: 100%; height: 200px; object-fit: cover; } .product-info { padding: 15px; } .product-title { font-size: 1.1rem; margin-bottom: 8px; color: #2c3e50; font-weight: 600; } .product-category { display: inline-block; background: #ecf0f1; color: #7f8c8d; padding: 3px 8px; border-radius: 5px; font-size: 0.8rem; margin-bottom: 10px; } .product-price { font-size: 1.2rem; font-weight: 700; color: #27ae60; } .no-products { grid-column: 1 / -1; text-align: center; padding: 50px; color: #7f8c8d; } /* Footer */ footer { text-align: center; margin-top: 50px; padding: 20px; color: #7f8c8d; font-size: 0.9rem; } footer a { color: #3498db; text-decoration: none; } /* Responsive Design */ @media (max-width: 768px) { .products-container { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); } } @media (max-width: 480px) { .filter-options { grid-template-columns: 1fr 1fr; } .products-container { grid-template-columns: 1fr; } } /* Animations */ @keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .product-card { animation: fadeIn 0.5s ease forwards; opacity: 0; } .product-card:nth-child(1) { animation-delay: 0.1s; } .product-card:nth-child(2) { animation-delay: 0.2s; } .product-card:nth-child(3) { animation-delay: 0.3s; } .product-card:nth-child(4) { animation-delay: 0.4s; } .product-card:nth-child(5) { animation-delay: 0.5s; } .product-card:nth-child(6) { animation-delay: 0.6s; }
3. File JavaScript (script.js)
document.addEventListener('DOMContentLoaded', function() { // DOM Elements const productsContainer = document.getElementById('productsContainer'); const searchInput = document.getElementById('searchInput'); const categoryCheckboxes = document.querySelectorAll('input[name="category"]'); const priceRange = document.getElementById('priceRange'); const priceValue = document.getElementById('priceValue'); const resetBtn = document.getElementById('resetFilters'); // Product Data (dengan gambar online dari Lorem Picsum) const products = [ { id: 1, title: "Smartphone X", category: "elektronik", price: 4999000, image: "https://picsum.photos/id/20/500/300" }, { id: 2, title: "Laptop Pro", category: "elektronik", price: 12999000, image: "https://picsum.photos/id/48/500/300" }, { id: 3, title: "Kemeja Flanel", category: "fashion", price: 299000, image: "https://picsum.photos/id/21/500/300" }, { id: 4, title: "Sepatu Sneakers", category: "fashion", price: 599000, image: "https://picsum.photos/id/203/500/300" }, { id: 5, title: "Kopi Premium", category: "makanan", price: 99000, image: "https://picsum.photos/id/30/500/300" }, { id: 6, title: "Coklat Belgia", category: "makanan", price: 129000, image: "https://picsum.photos/id/312/500/300" }, { id: 7, title: "Meja Kerja", category: "perabotan", price: 1499000, image: "https://picsum.photos/id/31/500/300" }, { id: 8, title: "Kursi Ergonomis", category: "perabotan", price: 899000, image: "https://picsum.photos/id/33/500/300" } ]; // Initialize displayProducts(products); setupEventListeners(); // Functions function displayProducts(productsToDisplay) { productsContainer.innerHTML = ''; if (productsToDisplay.length === 0) { productsContainer.innerHTML = ` <div class="no-products"> <i class="fas fa-search" style="font-size: 3rem; margin-bottom: 15px;"></i> <h3>Tidak ada produk yang sesuai</h3> <p>Coba ubah filter pencarian Anda</p> </div> `; return; } productsToDisplay.forEach(product => { const productCard = document.createElement('div'); productCard.className = 'product-card'; productCard.innerHTML = ` <img src="${product.image}" alt="${product.title}" class="product-image"> <div class="product-info"> <h3 class="product-title">${product.title}</h3> <span class="product-category">${product.category}</span> <p class="product-price">Rp ${product.price.toLocaleString('id-ID')}</p> </div> `; productsContainer.appendChild(productCard); }); } function filterProducts() { const searchTerm = searchInput.value.toLowerCase(); const selectedCategories = Array.from(categoryCheckboxes) .filter(checkbox => checkbox.checked) .map(checkbox => checkbox.value); const maxPrice = parseInt(priceRange.value); const filteredProducts = products.filter(product => { // Filter by search term const matchesSearch = product.title.toLowerCase().includes(searchTerm); // Filter by category const matchesCategory = selectedCategories.length === 0 || selectedCategories.includes(product.category); // Filter by price const matchesPrice = product.price <= maxPrice; return matchesSearch && matchesCategory && matchesPrice; }); displayProducts(filteredProducts); } function setupEventListeners() { // Search input searchInput.addEventListener('input', filterProducts); // Category checkboxes categoryCheckboxes.forEach(checkbox => { checkbox.addEventListener('change', filterProducts); }); // Price range priceRange.addEventListener('input', function() { const value = parseInt(this.value); priceValue.textContent = value === 5000000 ? 'Rp 5.000.000+' : `Rp ${value.toLocaleString('id-ID')}`; filterProducts(); }); // Reset button resetBtn.addEventListener('click', function() { searchInput.value = ''; categoryCheckboxes.forEach(checkbox => { checkbox.checked = true; }); priceRange.value = 5000000; priceValue.textContent = 'Rp 5.000.000+'; filterProducts(); }); } });
Cara Menggunakan
-
Buka file
index.html
di browser -
Gunakan fitur:
-
🔍 Kotak pencarian untuk cari produk
-
✔️ Centang kategori untuk filter
-
💰 Geser slider untuk filter harga
-
🔄 Tombol reset untuk menghapus semua filter
-
Kesimpulan
-
Pencarian Real-time
-
Cari produk berdasarkan kata kunci
-
Pencarian langsung saat mengetik
-
-
Filter Multi-Kategori
-
Pilih satu atau beberapa kategori sekaligus
-
Elektronik, Fashion, Makanan, Perabotan
-
-
Filter Harga
-
Slider range harga
-
Tampilan nilai harga yang user-friendly
-
-
Tampilan Produk
-
Grid layout responsif
-
Animasi saat muncul
-
Gambar produk dari API online
-
-
Reset Filter
-
Tombol reset untuk mengembalikan semua filter
-