Open In App

Design a Recipe App in HTML CSS & JavaScript

We will create an attractive and styled application that gives the recipe of food, and dishes entered by the user. The user needs to enter the required food name and click on the button. The application uses an External API to fetch the food recipe and represent it in an attractive form. The user can view the detailed Recipe of Dish in the modal component which makes the application more beautiful.

Prerequisites

Approach

Example: We will see the implementation of the above-explained approach.






// script.js
const apiUrl =
    '...';
function defaultFn() {
    const defaultFood = 'chicken';
    searchFn(defaultFood);
}
document.getElementById('searchBtn')
    .addEventListener('click', () => {
        const userIn = document.getElementById('searchInput')
            .value.trim();
        if (userIn !== '') {
            searchFn(userIn);
        } else {
            alert('Please enter a recipe name.');
        }
    });
document.addEventListener('click', (event) => {
    if (event.target.className === 'show-recipe-btn') {
        const rId = event.target.getAttribute('data-id');
        modalFn(rId);
    }
    if (event.target.id === 'closeBtn') {
        closeModalFn();
    }
});
defaultFn();
function searchFn(query) {
    const url = `${apiUrl}${query}`;
    fetch(url)
        .then(res => res.json())
        .then(tmp => {
            if (tmp.meals) {
                showRecpsFn(tmp.meals);
            } else {
                noRecFn();
            }
        })
        .catch(error => console
            .error('Error fetching recipes:', error));
}
function showRecpsFn(r) {
    const rCont = document.getElementById('recipeContainer');
    rCont.innerHTML = '';
    r.slice(0, 20).forEach(recipe => {
        const c = document.createElement('div');
        c.classList.add('animate__animated',
            'animate__fadeIn', 'recipe-card');
        c.innerHTML = `
            <h3>${recipe.strMeal}</h3>
            <img src="${recipe.strMealThumb}"
            alt="${recipe.strMeal}">
            <p>${recipe.strArea}</p>
            <p>${recipe.strCategory}</p>
            <button class="show-recipe-btn"
             data-id="${recipe.idMeal}">Show Recipe</button>
        `;
 
        rCont.appendChild(c);
    });
    if (r.length === 1) {
        const card = rCont.firstChild;
        card.style.margin = 'auto';
    }
}
function noRecFn() {
    const rCont = document.getElementById('recipeContainer');
    rCont.innerHTML = '<p>No Recipe found</p>';
}
function modalFn(recipeId) {
    const mData = document.getElementById('modalContent');
    mData.innerHTML = '';
    fetch(`
...`)
        .then(response => response.json())
        .then(data => {
            const rep = data.meals[0];
            mData.innerHTML = `
                <h2>${rep.strMeal}</h2>
                <h3>Instructions:</h3>
                <p>${formatFn(rep.strInstructions)}</p>
            `;
            document.getElementById('recipeModal')
                .style.display = 'block';
        })
        .catch(error => console.error('Error fetching recipe details:',
            error));
}
function formatFn(instructions) {
    return instructions.split('\r\n').filter(instruction =>
        instruction.trim() !== '').join('<br>');
}
function closeModalFn() {
    document.getElementById('recipeModal').style.display = 'none';
}




<!DOCTYPE html>
<html lang="en">
 
<head>
    <link rel="stylesheet" href=
    <link rel="stylesheet" href=
    <link href=
    rel="stylesheet">
    <link rel="stylesheet" href="style.css">
    <title>GeeksforGeeks Recipe Application</title>
</head>
 
<body>
    <div class="container">
        <h1>GeeksforGeeks Recipe Application</h1>
        <div class="search-container">
            <i class="fas fa-search"></i>
            <input type="text" id="searchInput"
                   placeholder="Search for recipes">
            <button id="searchBtn">Search</button>
        </div>
        <div class="recipe-container" id="recipeContainer"></div>
    </div>
    <div class="modal" id="recipeModal">
        <div class="modal-content">
            <span class="close" id="closeBtn">×</span>
            <div id="modalContent"></div>
        </div>
    </div>
    <script src="script.js"></script>
</body>
 
</html>




body {
    margin: 0;
    padding: 0;
    font-family: 'Montserrat', sans-serif;
    background: linear-gradient(to right,
            #3494E6, #EC6EAD);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    overflow-x: hidden;
}
 
.container {
    background: rgba(255, 255, 255, 0.9);
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    width: 100%;
    overflow: hidden;
    text-align: center;
    max-width: 1700px;
    margin: auto;
}
 
h1 {
    font-size: 24px;
    color: green;
    margin-bottom: 20px;
}
 
.search-container {
    display: flex;
    align-items: center;
    margin-bottom: 20px;
}
 
i {
    font-size: 24px;
    margin-right: 10px;
    color: #333;
}
 
input {
    flex: 1;
    padding: 10px;
    font-size: 16px;
    border: none;
    border-radius: 5px;
    border-color: #FF4848;
}
 
button {
    padding: 10px 20px;
    font-size: 16px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    background: #FF4848;
    color: #fff;
}
 
#searchBtn:hover {
    background: #FF6565;
}
 
.recipe-container {
    display: grid;
    grid-template-columns: repeat(auto-fill,
            minmax(200px, 1fr));
    gap: 10px;
    max-width: 100%;
    overflow-y: auto;
    max-height: 70vh;
}
 
.recipe-card {
    background: linear-gradient(to right,
            #a0f8a4, rgb(160, 212, 255), 90%, 54%);
    border-radius: 20px;
    padding: 8px;
    box-shadow: 0 2px 5px rgb(255, 3, 3);
    transition: transform 0.3s ease-in-out;
    overflow: hidden;
    text-align: center;
}
 
.recipe-card:hover {
    transform: scale(1.03);
}
 
.recipe-card img {
    max-width: 70%;
    height: 40%;
    border-radius: 5px;
    margin-bottom: 10px;
}
 
.recipe-card h3 {
    margin-bottom: 5px;
    font-size: 14px;
}
 
.recipe-card p {
    font-size: 14px;
    color: rgb(0, 0, 0);
    margin-bottom: 10px;
}
 
.show-recipe-btn {
    background: #FF4848;
    color: #fff;
    padding: 8px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    margin-top: 10px;
}
 
.show-recipe-btn:hover {
    background: #FF6565;
}
 
.modal {
    display: none;
    position: fixed;
    z-index: 1000;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
}
 
.modal-content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    max-width: 400px;
    width: 100%;
}
 
.close {
    position: absolute;
    top: 10px;
    right: 10px;
    font-size: 20px;
    color: #555;
    cursor: pointer;
}
 
@media screen and (max-width: 600px) {
    .recipe-container {
        grid-template-columns: repeat(auto-fill,
                minmax(100%, 1fr));
    }
}
 
.search-container {
    display: flex;
    align-items: center;
    margin-bottom: 20px;
}
 
i {
    font-size: 24px;
    margin-right: 10px;
    color: #333;
}
 
input {
    flex: 1;
    padding: 10px;
    font-size: 16px;
    border: none;
    border-radius: 5px;
    border-color: #FF4848;
}
 
button {
    padding: 10px 20px;
    font-size: 16px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    background: #FF4848;
    color: #fff;
}
 
#searchBtn:hover {
    background: #FF6565;
}
 
.recipe-container {
    display: grid;
    grid-template-columns: repeat(auto-fill,
            minmax(200px, 1fr));
    gap: 10px;
    max-width: 100%;
    overflow-y: auto;
    max-height: 70vh;
}
 
.recipe-card {
    background: linear-gradient(to right,
            #a0f8a4,
            rgb(160, 212, 255), 90%, 54%);
    border-radius: 20px;
    padding: 8px;
    box-shadow: 0 2px 5px rgb(255, 3, 3);
    transition: transform 0.3s ease-in-out;
    overflow: hidden;
    text-align: center;
}
 
.recipe-card:hover {
    transform: scale(1.03);
}
 
.recipe-card img {
    max-width: 70%;
    height: 40%;
    border-radius: 5px;
    margin-bottom: 10px;
}
 
.recipe-card h3 {
    margin-bottom: 5px;
    font-size: 14px;
}
 
.recipe-card p {
    font-size: 14px;
    color: rgb(0, 0, 0);
    margin-bottom: 10px;
}
 
.show-recipe-btn {
    background: #FF4848;
    color: #fff;
    padding: 8px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    margin-top: 10px;
}
 
.show-recipe-btn:hover {
    background: #FF6565;
}
 
.modal {
    display: none;
    position: fixed;
    z-index: 1000;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.5);
}
 
.modal-content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #fff;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
    max-width: 400px;
    width: 100%;
}
 
.close {
    position: absolute;
    top: 10px;
    right: 10px;
    font-size: 20px;
    color: #555;
    cursor: pointer;
}
 
@media screen and (max-width: 600px) {
    .recipe-container {
        grid-template-columns: repeat(auto-fill,
                minmax(100%, 1fr));
    }
}

Output:




Article Tags :