This is a submission for Frontend Challenge - Comfort Food Edition, Perfect Landing
What I Built
For this challenge, I created "Cantina de Casa", a landing page focused on classic home-cooked comfort food dishes. When I started building this page, the idea wasn't to create something overly complex, but rather to leverage concepts that make navigation organized and intuitive, with a clean interface where users can find information without having to hunt around for where to click. All classes and variables were structured using the dm_ prefix to keep the code scope isolated and standardized.
Demo
Live Demo:
https://es-d-64362832320260731-019fb003-ca65-7e4e-8c71-9937a6046590.codepen.dev/
Below I'm sharing the full codebase for anyone who wants to analyze the structure or run it locally.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cantina de Casa - Comfort Food</title>
<link rel="stylesheet" href="style.css">
</head>
<body class="dm_body">
<header class="dm_header">
<div class="dm_header_content">
<div class="dm_logo">🍲 Cantina de Casa</div>
<div class="dm_search_container">
<input type="text" class="dm_search_input" placeholder="Search comfort food...">
</div>
<nav class="dm_nav">
<ul class="dm_nav_list">
<li class="dm_nav_item"><a href="#" class="dm_nav_link">Home</a></li>
<li class="dm_nav_item"><a href="#" class="dm_nav_link">Menu</a></li>
</ul>
</nav>
</div>
</header>
<main class="dm_main_content">
<section class="dm_hero_section">
<h1 class="dm_hero_title">Food That Feels Like Home</h1>
<p class="dm_hero_subtitle">Family recipes prepared with love and fresh ingredients.</p>
</section>
<section class="dm_menu_section">
<h2 class="dm_section_title">Pot Highlights</h2>
<div class="dm_grid_container" id="dm_products_grid">
<!-- Card 1 -->
<article class="dm_card">
<div class="dm_card_img_wrapper">
<img src="<a href="https://images.unsplash.com/photo-1604908176997-125f25cc6f3d?auto=format&fit=crop&w=800&q=80">https://images.unsplash.com/photo-1604908176997-125f25cc6f3d?auto=format&fit=crop&w=800&q=80</a>" alt="Full Feijoada" class="dm_card_img">
</div>
<div class="dm_card_info">
<h3 class="dm_card_title">Full Feijoada</h3>
<p class="dm_card_desc">Rich black bean stew, selected meats, buttered cassava flour, and sautéed collard greens.</p>
<div class="dm_card_footer">
<span class="dm_card_price">$ 12.90</span>
<button class="dm_btn_add">Order</button>
</div>
</div>
</article>
<!-- Card 2 -->
<article class="dm_card">
<div class="dm_card_img_wrapper">
<img src="<a href="https://images.unsplash.com/photo-1598514982205-f36b96d1e8d4?auto=format&fit=crop&w=800&q=80">https://images.unsplash.com/photo-1598514982205-f36b96d1e8d4?auto=format&fit=crop&w=800&q=80</a>" alt="Grandma's Pasta" class="dm_card_img">
</div>
<div class="dm_card_info">
<h3 class="dm_card_title">Grandma's Pasta</h3>
<p class="dm_card_desc">Fresh pasta with rustic roasted tomato sauce and handmade meatballs.</p>
<div class="dm_card_footer">
<span class="dm_card_price">$ 10.50</span>
<button class="dm_btn_add">Order</button>
</div>
</div>
</article>
<!-- Card 3 -->
<article class="dm_card">
<div class="dm_card_img_wrapper">
<img src="<a href="https://images.unsplash.com/photo-1529042410759-befb1204b468?auto=format&fit=crop&w=800&q=80">https://images.unsplash.com/photo-1529042410759-befb1204b468?auto=format&fit=crop&w=800&q=80</a>" alt="Chicken with Okra" class="dm_card_img">
</div>
<div class="dm_card_info">
<h3 class="dm_card_title">Chicken with Okra</h3>
<p class="dm_card_desc">A wood-stove regional classic served with creamy corn polenta.</p>
<div class="dm_card_footer">
<span class="dm_card_price">$ 11.00</span>
<button class="dm_btn_add">Order</button>
</div>
</div>
</article>
</div>
</section>
</main>
<script src="script.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
CSS
:root {
--dm_color_primary: #d9534f;
--dm_color_primary_hover: #c9302c;
--dm_color_bg: #fdfbf7;
--dm_color_surface: #ffffff;
--dm_color_text_main: #333333;
--dm_color_text_muted: #777777;
--dm_border_radius: 12px;
--dm_shadow_sm: 0 2px 8px rgba(0,0,0,0.08);
--dm_shadow_md: 0 8px 16px rgba(0,0,0,0.12);
--dm_transition_default: all 0.3s ease;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.dm_body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--dm_color_bg);
color: var(--dm_color_text_main);
line-height: 1.6;
}
/* Header */
.dm_header {
background-color: var(--dm_color_surface);
box-shadow: var(--dm_shadow_sm);
position: sticky;
top: 0;
z-index: 100;
}
.dm_header_content {
max-width: 1200px;
margin: 0 auto;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 1rem;
}
.dm_logo {
font-size: 1.5rem;
font-weight: bold;
color: var(--dm_color_primary);
}
.dm_search_input {
padding: 0.75rem 1rem;
border: 1px solid #ddd;
border-radius: 8px;
width: 300px;
outline: none;
transition: var(--dm_transition_default);
}
.dm_search_input:focus {
border-color: var(--dm_color_primary);
box-shadow: 0 0 0 3px rgba(217, 83, 79, 0.2);
}
.dm_nav_list {
list-style: none;
display: flex;
gap: 1.5rem;
}
.dm_nav_link {
text-decoration: none;
color: var(--dm_color_text_main);
font-weight: 500;
transition: var(--dm_transition_default);
}
.dm_nav_link:hover {
color: var(--dm_color_primary);
}
/* Hero Section */
.dm_hero_section {
text-align: center;
padding: 4rem 2rem;
background: linear-gradient(rgba(253, 251, 247, 0.9), rgba(253, 251, 247, 0.9)), url('[https://images.unsplash.com/photo-1495195134817-a1691359f9e8?auto=format&fit=crop&w=1200&q=80](https://images.unsplash.com/photo-1495195134817-a1691359f9e8?auto=format&fit=crop&w=1200&q=80)') center/cover;
}
.dm_hero_title {
font-size: 2.5rem;
margin-bottom: 0.5rem;
color: var(--dm_color_primary);
}
.dm_hero_subtitle {
font-size: 1.2rem;
color: var(--dm_color_text_muted);
}
/* Menu Grid */
.dm_menu_section {
max-width: 1200px;
margin: 0 auto;
padding: 3rem 2rem;
}
.dm_section_title {
font-size: 1.8rem;
margin-bottom: 2rem;
border-left: 4px solid var(--dm_color_primary);
padding-left: 1rem;
}
.dm_grid_container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
}
/* Cards */
.dm_card {
background: var(--dm_color_surface);
border-radius: var(--dm_border_radius);
overflow: hidden;
box-shadow: var(--dm_shadow_sm);
transition: var(--dm_transition_default);
display: flex;
flex-direction: column;
}
.dm_card:hover {
transform: translateY(-5px);
box-shadow: var(--dm_shadow_md);
}
.dm_card_img_wrapper {
height: 200px;
overflow: hidden;
}
.dm_card_img {
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.5s ease;
}
.dm_card:hover .dm_card_img {
transform: scale(1.05);
}
.dm_card_info {
padding: 1.5rem;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.dm_card_title {
font-size: 1.25rem;
margin-bottom: 0.5rem;
}
.dm_card_desc {
color: var(--dm_color_text_muted);
font-size: 0.9rem;
margin-bottom: 1.5rem;
flex-grow: 1;
}
.dm_card_footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.dm_card_price {
font-size: 1.25rem;
font-weight: bold;
color: var(--dm_color_primary);
}
.dm_btn_add {
background-color: var(--dm_color_primary);
color: white;
border: none;
padding: 0.5rem 1.25rem;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
transition: var(--dm_transition_default);
}
.dm_btn_add:hover {
background-color: var(--dm_color_primary_hover);
}
/* Responsiveness */
@media (max-width: 768px) {
.dm_header_content {
flex-direction: column;
align-items: stretch;
}
.dm_search_input {
width: 100%;
}
.dm_nav_list {
justify-content: center;
}
}
Enter fullscreen mode Exit fullscreen mode
JavaScript
// Simple client-side search functionality
document.addEventListener('DOMContentLoaded', () => {
const dm_searchInput = document.querySelector('.dm_search_input');
const dm_cards = document.querySelectorAll('.dm_card');
dm_searchInput.addEventListener('input', (event) => {
const dm_searchTerm = event.target.value.toLowerCase();
dm_cards.forEach(dm_card => {
const dm_title = dm_card.querySelector('.dm_card_title').textContent.toLowerCase();
const dm_desc = dm_card.querySelector('.dm_card_desc').textContent.toLowerCase();
if (dm_title.includes(dm_searchTerm) || dm_desc.includes(dm_searchTerm)) {
dm_card.style.display = 'flex';
} else {
dm_card.style.display = 'none';
}
});
});
// Simulated order button click
const dm_addButtons = document.querySelectorAll('.dm_btn_add');
dm_addButtons.forEach(dm_btn => {
dm_btn.addEventListener('click', () => {
const dm_productName = dm_btn.closest('.dm_card').querySelector('.dm_card_title').textContent;
alert(`The dish "${dm_productName}" was added to your order!`);
});
});
});
Enter fullscreen mode Exit fullscreen mode
Journey
The first thing I did was separate the structure in HTML and keep all visual styles in CSS. This makes future maintenance much easier. If I ever need to change a color, spacing, or reorganize the food cards later on, I hardly need to touch the base HTML.
For the top bar, I opted for a fixed header. It doesn't need to be a complex layout, but keeping the search bar accessible at all times improves usability directly by preventing users from having to scroll back to the top whenever they want to filter dishes.
Next, I focused on layout organization using CSS Grid. I personally prefer Grid when elements (like product cards) share similar dimensions because it keeps everything aligned. CSS comes into play to define spacing, borders, subtle shadows, and hover transitions. A simple zoom effect on image hover enhances user experience without cluttering the interface with excessive animations. In my opinion, less is more when building this type of product-driven UI.
Another priority was ensuring full responsiveness. Modern applications must look good on both desktops and mobile screens. Using Media Queries, I restructured layout elements based on screen width, adjusting header positioning and reducing Grid columns automatically for smaller viewports.
I also made sure to use CSS variables (such as --dm_color_primary and --dm_border_radius) for key design tokens. If I need to overhaul the visual theme later, I can do so by changing just a few lines at the top of the CSS file. Additionally, I focused on avoiding unnecessary code duplication by building reusable classes.
Ultimately, CSS does far more than decorate. It transforms raw HTML structure into an enjoyable user experience. I prefer investing time upfront to organize variables and Grid structures properly rather than refactoring a messy codebase down the road. JavaScript was kept lightweight and purposeful, focusing on an active client-side search filter and simple event handling.
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.