├── README.md
├── index.html
├── index.js
└── styles.css
/README.md:
--------------------------------------------------------------------------------
1 | # RECIPE_APP-using-html-css-js
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
10 | RecipeApp
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
25 |
26 |
Search your favourite recipes...
27 |
28 |
29 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const searchBtn = document.querySelector('.searchBtn');
2 | const searchBox = document.querySelector('.searchBox');
3 | const recipeContainer = document.querySelector('.recipe-container');
4 | const recipeDetailsContent = document.querySelector('.recipe-details-content');
5 | const recipeCloseBtn = document.querySelector('.recipe-close-btn');
6 |
7 |
8 | const fetchRecipes = async (query) => {
9 | recipeContainer.innerHTML = "Fetching Recipes...
";
10 | try {
11 |
12 |
13 | const data = await fetch(`https://www.themealdb.com/api/json/v1/1/search.php?s=${query}`);
14 | const response = await data.json();
15 | recipeContainer.innerHTML = "";
16 | response.meals.forEach(meal => {
17 | const recipeDiv = document.createElement('div');
18 | recipeDiv.classList.add('recipe');
19 | recipeDiv.innerHTML = `
20 | ${meal.strMeal}
21 | ${meal.strArea} Dish
22 | Belongs to ${meal.strCategory} category
`
23 |
24 |
25 | const button = document.createElement('button');
26 | button.textContent = "View Recipe";
27 | recipeDiv.appendChild(button);
28 | button.addEventListener('click', () => {
29 | openRecipePopup(meal);
30 | });
31 |
32 | recipeContainer.appendChild(recipeDiv);
33 |
34 | });
35 | } catch (error) {
36 | recipeContainer.innerHTML = " Error in Fetching Recipes...
";
37 | }
38 | }
39 |
40 |
41 | const fetchIngredients = (meal) => {
42 | let ingredientsList = "";
43 | for (let i = 1; i <= 20; i++) {
44 | const ingredient = meal[`strIngredient${i}`];
45 | if (ingredient) {
46 | const measure = meal[`strMeasure${i}`];
47 | ingredientsList += `${measure} ${ingredient}`
48 | }
49 | else {
50 | break;
51 | }
52 | }
53 | return ingredientsList;
54 | }
55 |
56 |
57 | const openRecipePopup = (meal) => {
58 | recipeDetailsContent.innerHTML = `${meal.strMeal}
59 | Ingredients:
60 | ${fetchIngredients(meal)}
61 |
62 |
Instructions:
63 |
${meal.strInstructions}
64 |
65 |
66 | `
67 |
68 |
69 | recipeDetailsContent.parentElement.style.display = "block";
70 | }
71 | recipeCloseBtn.addEventListener('click', () => {
72 | recipeDetailsContent.parentElement.style.display = "none";
73 | });
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | searchBtn.addEventListener('click', (e) => {
87 | e.preventDefault();
88 | const searchInput = searchBox.value.trim();
89 | if (!searchInput) {
90 | recipeContainer.innerHTML = `Type the meal in the search box.
`;
91 | return;
92 | }
93 | fetchRecipes(searchInput);
94 | });
95 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | font-family: Verdana, Geneva, Tahoma, sans-serif;
6 |
7 | }
8 |
9 | body {
10 | background-color: #2b1d0f;
11 | color: #fff;
12 | }
13 |
14 | header nav {
15 | background-color: #212121;
16 | padding: 20px;
17 | display: flex;
18 | justify-content: space-between;
19 | align-items: center;
20 | z-index: 1;
21 | }
22 |
23 | header nav h1 {
24 | font-size: 26px;
25 | font-weight: 700;
26 | letter-spacing: 1px;
27 | text-transform: uppercase;
28 | }
29 |
30 | header nav form {
31 | display: flex;
32 | justify-content: center;
33 |
34 | }
35 |
36 | form input[type="text"],
37 | button [type="submit"] {
38 | border: none;
39 | font-size: 18px;
40 | padding: 10px;
41 | border-radius: 4px;
42 |
43 | }
44 |
45 | button {
46 | margin-left: 10px;
47 | padding: 10px;
48 | }
49 |
50 | form button[type="submit"] {
51 | background-color: #f44336;
52 | color: #fff;
53 | cursor: pointer;
54 | transition: background-color 0.2s ease-in-out;
55 |
56 | }
57 |
58 | form button[type="submit"]:hover,
59 | .recipe button:hover,
60 | .recipe-close-btn:hover {
61 | background-color: #ff5c5c;
62 | }
63 |
64 | .recipe-container {
65 | text-align: center;
66 | margin-top: 20px;
67 | display: grid;
68 | grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
69 | grid-gap: 40px;
70 | width: 80%;
71 | margin: 10px auto;
72 | padding: 20px;
73 | place-items: center;
74 | }
75 |
76 | .recipe {
77 | background-color: #fff;
78 | display: flex;
79 | flex-direction: column;
80 | color: #000;
81 | border-radius: 6px;
82 | box-shadow: 0 5px 10px rgba(78, 73, 73, 0.1), -5px -5px 10px rgba(34, 34, 34, 0.5);
83 | cursor: pointer;
84 | max-width: 350px;
85 | transition: transform 0.3s ease-in-out;
86 |
87 | }
88 |
89 | .recipe:hover {
90 | transform: scale(1.02);
91 | }
92 |
93 | .recipe img {
94 | height: 300px;
95 | }
96 |
97 | .recipe h3 {
98 | font-size: 20px;
99 | margin-block: 5px;
100 | }
101 |
102 | .recipe p {
103 | font-size: 20px;
104 | color: #4a4a4a;
105 | margin: 5px 0;
106 | }
107 |
108 | .recipe span {
109 | font-weight: 600;
110 | }
111 |
112 | .recipe button {
113 | font-size: 20px;
114 | font-weight: 600;
115 | padding: 10px;
116 | border-radius: 5px;
117 | cursor: pointer;
118 | margin: 18px auto;
119 | background-color: #f44336;
120 | color: #fff;
121 | border: none;
122 | }
123 |
124 | @media screen and (max-width:600px) {
125 | header nav form {
126 | width: 80%;
127 | margin-top: 20px;
128 |
129 | }
130 |
131 | header nav {
132 | flex-direction: column;
133 | }
134 |
135 |
136 | }
137 |
138 | .recipe-details {
139 | display: none;
140 | position: fixed;
141 | top: 50%;
142 | left: 50%;
143 | transform: translate(-50%, -50%);
144 | background-color: #694c3f;
145 | -webkit-transform: translate(-50%, -50%);
146 | border-radius: 12px;
147 | width: 40%;
148 | height: 60%;
149 | font-size: 20px;
150 | transition: all 0.5s ease-in-out;
151 | overflow-y: scroll;
152 | }
153 |
154 | .recipe-details::-webkit-scrollbar {
155 | width: 10px;
156 | }
157 |
158 | .recipe-details::-webkit-scrollbar-thumb {
159 | background-color: #b5b5ba;
160 | border-radius: 16px;
161 | --webkit-border-radius: 16px;
162 |
163 | }
164 |
165 | body::-webkit-scrollbar {
166 | width: 16px;
167 | }
168 |
169 | body::-webkit-scrollbar-thumb {
170 | background-color: #a1a1a1;
171 | border-radius: 6px;
172 |
173 |
174 | }
175 |
176 | body::-webkit-scrollbar-track {
177 | background-color: #ebebeb;
178 | }
179 |
180 |
181 |
182 | .recipe-details-content {
183 | padding: 30px;
184 |
185 | }
186 |
187 | .recipeName {
188 | text-align: center;
189 | text-transform: uppercase;
190 | text-decoration: underline;
191 | margin-bottom: 20px;
192 | }
193 |
194 | .ingredientList li {
195 | margin-top: 10px;
196 | margin-left: 20;
197 | }
198 |
199 | .recipeInstructions p {
200 | line-height: 30px;
201 | white-space: pre-line;
202 | margin-bottom: 20px;
203 | }
204 |
205 | .recipe-close-btn {
206 | border: none;
207 | font-size: 18px;
208 | padding: 8px;
209 | border-radius: 4px;
210 | background-color: #f44336;
211 | color: #fff;
212 | position: absolute;
213 | top: 20px;
214 | right: 20px;
215 | width: 20px;
216 | height: 20px;
217 | display: flex;
218 | justify-content: center;
219 | align-items: center;
220 |
221 | }
222 |
223 | .ingredientList {
224 | margin-bottom: 20px;
225 | }
--------------------------------------------------------------------------------