Restaurant Menu Html Css Codepen File

/* header & hero section */ .hero text-align: center; margin-bottom: 3rem; border-bottom: 2px dashed #e6d5c0; padding-bottom: 2rem; .restaurant-name font-family: 'Playfair Display', serif; font-size: 3.2rem; font-weight: 600; letter-spacing: -0.5px; color: #3e2a1f; margin-bottom: 0.4rem; .restaurant-tagline font-size: 1rem; font-weight: 400; color: #8b6b4d; letter-spacing: 2px; text-transform: uppercase; background: #f3ede5; display: inline-block; padding: 0.3rem 1.2rem; border-radius: 40px; backdrop-filter: blur(2px); .menu-subhead margin-top: 1rem; font-size: 0.95rem; max-width: 580px; margin-left: auto; margin-right: auto; color: #5e4b34; font-weight: 400;

<script> // ---------- RESTAURANT MENU DATA (realistic, diverse) ---------- const menuData = [ // Appetizers id: 1, name: "Burrata Caprese", price: "$16", category: "Appetizers", desc: "Creamy burrata, heirloom tomatoes, aged balsamic, basil oil & grilled sourdough.", icon: "fa-seedling", img: "https://images.unsplash.com/photo-1601050690597-df0568f70950?w=500&auto=format", dietary: "veg" , id: 2, name: "Truffle Arancini", price: "$14", category: "Appetizers", desc: "Crispy risotto balls, wild mushroom ragu, truffle aioli & parmesan.", icon: "fa-mushroom", img: "https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=500&auto=format", dietary: "veg" , id: 3, name: "Lamb Keftedes", price: "$18", category: "Appetizers", desc: "Greek-style lamb meatballs, tzatziki, pickled red onion & fresh mint.", icon: "fa-drumstick-bite", img: "https://images.unsplash.com/photo-1559847844-5315695dadae?w=500&auto=format", dietary: "meat" , // Main Courses id: 4, name: "Seared Sea Bass", price: "$34", category: "Mains", desc: "Mediterranean sea bass, saffron orzo, citrus beurre blanc, fennel slaw.", icon: "fa-fish", img: "https://images.unsplash.com/photo-1519708227418-c8fd9a32b7a2?w=500&auto=format", dietary: "seafood" , id: 5, name: "Porcini Risotto", price: "$27", category: "Mains", desc: "Carnaroli rice, wild porcini, parmesan cream, truffle oil & crispy sage.", icon: "fa-bowl-food", img: "https://images.unsplash.com/photo-1476124369491-e7addf5db371?w=500&auto=format", dietary: "veg" , id: 6, name: "Braised Short Rib", price: "$39", category: "Mains", desc: "Red wine braised beef, creamy parsnip purée, roasted carrots & gremolata.", icon: "fa-utensils", img: "https://images.unsplash.com/photo-1600891964092-4316c288032e?w=500&auto=format", dietary: "meat" , id: 7, name: "Herb Chicken Paillard", price: "$28", category: "Mains", desc: "Free-range chicken, lemon-herb marinade, arugula, shaved fennel & aged parmesan.", icon: "fa-egg", img: "https://images.unsplash.com/photo-1604909052743-94ab495dffb9?w=500&auto=format", dietary: "meat" , // Pasta & Risotto section (additional) id: 8, name: "Lobster Ravioli", price: "$36", category: "Pasta", desc: "House-made ravioli, maine lobster, saffron cream, chervil & toasted breadcrumbs.", icon: "fa-lobster", img: "https://images.unsplash.com/photo-1563379926898-05f4575a45e8?w=500&auto=format", dietary: "seafood" , id: 9, name: "Cacio e Pepe", price: "$22", category: "Pasta", desc: "Roman classic, tonnarelli pasta, pecorino romano, toasted black pepper & butter.", icon: "fa-cheese", img: "https://images.unsplash.com/photo-1551183053-bf91a1d81141?w=500&auto=format", dietary: "veg" , // Desserts id: 10, name: "Salted Caramel Tart", price: "$12", category: "Desserts", desc: "Dark chocolate shell, salted caramel ganache, vanilla bean chantilly & fleur de sel.", icon: "fa-cake-candles", img: "https://images.unsplash.com/photo-1587314168485-3236d6710814?w=500&auto=format", dietary: "veg" , id: 11, name: "Lemon Ricotta Cake", price: "$11", category: "Desserts", desc: "Whipped ricotta, lemon curd, wild berries & honeycomb crumble.", icon: "fa-lemon", img: "https://images.unsplash.com/photo-1571115177098-24ec42ed204d?w=500&auto=format", dietary: "veg" , id: 12, name: "Affogato al Caffè", price: "$9", category: "Desserts", desc: "Vanilla gelato, espresso shot, amaretti cookie crumble & dark chocolate shavings.", icon: "fa-mug-hot", img: "https://images.unsplash.com/photo-1579954115545-a95591f28bfc?w=500&auto=format", dietary: "veg" , // Drinks / Cocktails id: 13, name: "Elderflower Spritz", price: "$13", category: "Drinks", desc: "Elderflower liqueur, prosecco, soda, fresh mint & cucumber ribbon.", icon: "fa-wine-glass", img: "https://images.unsplash.com/photo-1560512823-829485b8bf24?w=500&auto=format", dietary: "veg" , id: 14, name: "Smoked Old Fashioned", price: "$16", category: "Drinks", desc: "Bourbon, maple bitters, smoked with cherrywood & orange zest.", icon: "fa-whiskey-glass", img: "https://images.unsplash.com/photo-1470337458703-46ad1756a187?w=500&auto=format", dietary: "veg" , id: 15, name: "Rosemary Paloma", price: "$14", category: "Drinks", desc: "Tequila, grapefruit, rosemary syrup, lime & sparkling water.", icon: "fa-cocktail", img: "https://images.unsplash.com/photo-1551024709-8f23befc6f87?w=500&auto=format", dietary: "veg" ];

/* no results message */ .no-results grid-column: 1 / -1; text-align: center; padding: 3rem; background: #faf6f0; border-radius: 48px; font-size: 1rem; color: #b18762;

// Extract unique categories and order (priority: Appetizers, Mains, Pasta, Desserts, Drinks) const categoryOrder = ["Appetizers", "Mains", "Pasta", "Desserts", "Drinks"]; let uniqueCategories = [...new Map(menuData.map(item => [item.category, item.category])).values()]; // sort according to preferred order, then alphabetically for any extra uniqueCategories.sort((a,b) => let indexA = categoryOrder.indexOf(a); let indexB = categoryOrder.indexOf(b); if (indexA !== -1 && indexB !== -1) return indexA - indexB; if (indexA !== -1) return -1; if (indexB !== -1) return 1; return a.localeCompare(b); ); restaurant menu html css codepen

/* responsive touches */ @media (max-width: 680px) .menu-container padding: 1.5rem 1rem; margin: 1rem; .restaurant-name font-size: 2.2rem; .filter-btn padding: 0.4rem 1rem; font-size: 0.8rem; .menu-grid gap: 1.3rem; </style> </head> <body> <div class="menu-container"> <div class="hero"> <h1 class="restaurant-name">LE BISTRO</h1> <div class="restaurant-tagline">✨ Artisanal Flavors · Rustic Elegance ✨</div> <div class="menu-subhead"> <i class="fas fa-utensils"></i> Seasonal ingredients · Handcrafted dishes · Soulful dining </div> </div>

/* category filter (optional interactive tabs) */ .filter-tabs display: flex; flex-wrap: wrap; justify-content: center; gap: 0.8rem; margin-bottom: 2.8rem; .filter-btn background: transparent; border: 1.5px solid #e2cfb5; padding: 0.6rem 1.6rem; font-family: 'Inter', sans-serif; font-weight: 500; font-size: 0.9rem; border-radius: 60px; cursor: pointer; transition: all 0.2s ease; color: #4f3a28; background: white; .filter-btn i margin-right: 6px; font-size: 0.85rem; .filter-btn.active background: #c17b4c; border-color: #c17b4c; color: white; box-shadow: 0 6px 12px -8px rgba(193,123,76,0.4); .filter-btn:hover:not(.active) background: #f2e6db; border-color: #cb9e78;

// simple XSS prevention function escapeHtml(str) return str.replace(/[&<>]/g, function(m) if (m === '&') return '&'; if (m === '<') return '<'; if (m === '>') return '>'; return m; ).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, function(c) return c; ); /* header & hero section */

body background: #f9f6ef; font-family: 'Inter', sans-serif; color: #2c2418; line-height: 1.4; scroll-behavior: smooth;

<!-- Menu grid: items rendered dynamically --> <div id="menuGrid" class="menu-grid"></div>

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> <title>Le Bistro | Elegant Restaurant Menu</title> <!-- Google Fonts for refined typography --> <link href="https://fonts.googleapis.com/css2?family=Inter:opsz,wght@14..32,300;14..32,400;14..32,500;14..32,600;14..32,700&family=Playfair+Display:ital,wght@0,400;0,500;0,600;1,400&display=swap" rel="stylesheet"> <!-- Font Awesome 6 (free icons) --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"> <style> * margin: 0; padding: 0; box-sizing: border-box; border-bottom: 2px dashed #e6d5c0

/* footer / signature */ .footer-note text-align: center; margin-top: 3rem; padding-top: 2rem; border-top: 1px solid #ecdccb; font-size: 0.8rem; color: #a08162; display: flex; justify-content: center; gap: 2rem; flex-wrap: wrap; .footer-note span i margin-right: 6px;

<div class="footer-note"> <span><i class="fas fa-leaf"></i> Locally sourced</span> <span><i class="fas fa-wine-bottle"></i> Wine pairing available</span> <span><i class="fas fa-clock"></i> Tue–Sun 5PM – 11PM</span> </div> </div>

/* main container */ .menu-container max-width: 1280px; margin: 2rem auto; padding: 2rem 1.5rem 3rem; background: #fffdf9; border-radius: 32px; box-shadow: 0 20px 35px -12px rgba(0, 0, 0, 0.08);

/* menu grid layout */ .menu-grid display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 2rem;

<!-- Dynamic category filters (JS powered) --> <div class="filter-tabs" id="filterTabs"> <!-- will be populated from js --> </div>