Learn how to create a restaurant menu page using HTML, CSS, and JavaScript. Step-by-step guide for beginners!
Table of Contents
Creating a restaurant menu page is a great way to showcase your culinary offerings online. In this tutorial, you will learn how to design a simple yet attractive restaurant menu page using HTML, CSS, and JavaScript. This project is perfect for beginners who want to enhance their web development skills.
Prerequisites
Before you start, make sure you have the following:
- A basic understanding of HTML, CSS, and JavaScript.
- A code editor (like Visual Studio Code or Sublime Text).
- A web browser to test your project.
Source Code
Step 1 (HTML Code):
First, create an index.html
file and add the following HTML structure:
Here’s a breakdown of the HTML components:
1. <!DOCTYPE html>
Defines the document type and version (HTML5).
2. <html lang="en">
The root element of the HTML document, specifying English as the language.
3. <head>
Contains meta-information about the document:
<meta charset="UTF-8">
: Sets the character encoding to UTF-8.<meta name="viewport" content="width=device-width, initial-scale=1.0">
: Ensures the page is responsive and scales properly on mobile devices.<title>Restaurant Menu Page</title>
: Sets the title shown in the browser tab.- Google Fonts and Bootstrap stylesheets are linked to style the page with custom fonts and responsive design.
<link rel="stylesheet" href="styles.css">
: Links an external CSS file (styles.css
) for additional styling.
4. <body>
The main content of the webpage. It contains a single div
element with the class container
, which holds the menu
section of the page.
5. <section class="menu">
This section contains:
- A
<div class="title">
with an<h2>
title, "My Restaurant Menu." - A
btn-container
<div>
with buttons for filtering menu items by category (e.g., "ALL," "APPETIZERS," "STEAK CUTS"). - A
section-center
<div>
that holds all the menu items.
6. Menu Items
Each menu item is structured as a menu-items
<div>
inside a responsive col-lg-6 col-sm-12
class:
<img src="..." alt="...">
: Displays the image of the dish with analt
text.- A
menu-info
<div>
containing:menu-title
<div>
with the dish name and price in two<h4>
elements.menu-text
<div>
for a description of the dish.
7. <footer class="title">
A footer with the same title as the header ("My Restaurant Menu").
8. <script src="script.js"></script>
References an external JavaScript file (script.js
), which might handle interactivity like filtering the menu items.
Step 2 (CSS Code):
Next, create a styles.css
file to style your menu page. Add the following CSS:
Here’s a breakdown of the CSS code:
Global Styling
* {
box-sizing: border-box;
}
box-sizing: border-box;
ensures padding and borders are included in the element's total width and height, making layout sizing easier.
Body Styling
body {
margin: 0;
padding: 0;
background-color: #f1f5f8;
font-family: "Zilla Slab", serif;
}
- Removes default margin and padding from the body.
- Sets the background color to a light gray (
#f1f5f8
) and applies a serif font (Zilla Slab
).
Heading Styles
h2 {
font-family: "Great Vibes", cursive;
font-size: 3rem;
text-align: center;
color: #ff6a23;
padding-top: 50px;
}
footer>h2 {
font-family: "Great Vibes", cursive;
font-size: 2rem;
text-align: center;
color: #964b29;
}
h2
elements use a cursive font (Great Vibes
), with large font size (3rem
), centered text, and an orange color (#ff6a23
).- The
footer h2
has a smaller font size (2rem
) and a brown color (#964b29
).
Menu and Button Containers
.menu {
margin-top: 20px;
}
.btn-container {
display: flex;
justify-content: center;
align-items: center;
margin: 40px 0;
}
.btn-item {
margin-left: 15px;
}
.menu
has top margin for spacing..btn-container
usesflex
to center-align buttons within it, with top and bottom margin (40px
)..btn-item
has a left margin to separate each button.
Image Styling
.photo {
width: 30%;
height: 175px;
object-fit: cover;
border: 0.25rem solid black;
border-radius: 10px;
box-shadow: -10px 10px 10px 0px rgba(0,0,0,0.75);
}
.photo
elements are set to a width of30%
and height of175px
.object-fit: cover;
keeps the image proportionate.- A black border and slight rounding (
10px
border-radius) are applied. - A shadow with a dark offset adds depth.
Menu Item Styling
.menu-items {
display: flex;
margin: 20px 0;
padding-right: 50px;
}
.menu-info {
margin-left: 20px;
width: 100%;
}
.menu-title {
display: flex;
justify-content: space-between;
border-bottom: 1px solid black;
}
h4 {
color: #e00a00;
}
.menu-text {
padding-top: 20px;
}
.menu-items
is a flex container with spacing (20px
top/bottom margin,50px
padding-right)..menu-info
aligns its content to the right with a left margin..menu-title
usesjustify-content: space-between;
to spread items across its width, with a bottom border.h4
headings within menu items are styled in red (#e00a00
)..menu-text
has a top padding to create space above it.
Footer Styling
footer {
margin-top: 50px;
position: relative;
bottom: 30px;
width: 100%;
}
- Footer has a top margin (
50px
) to create space from previous content. - It’s positioned
30px
above its default location, covering the full width of the page.
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background-color: #f1f5f8;
font-family: "Zilla Slab", serif;
}
h2 {
font-family: "Great Vibes", cursive;
font-size: 3rem;
text-align: center;
color: #ff6a23;
padding-top: 50px;
}
footer>h2 {
font-family: "Great Vibes", cursive;
font-size: 2rem;
text-align: center;
color: #964b29;
}
.menu {
margin-top: 20px;
}
.btn-container {
display: flex;
justify-content: center;
align-items: center;
margin: 40px 0;
}
.btn-item {
margin-left: 15px;
}
.photo {
width: 30%;
height: 175px;
object-fit: cover;
border: 0.25rem solid black;
border-radius: 10px;
box-shadow: -10px 10px 10px 0px rgba(0,0,0,0.75);
}
.menu-items {
display: flex;
margin: 20px 0;
padding-right: 50px;
}
.menu-info {
margin-left: 20px;
width: 100%;
}
.menu-title {
display: flex;
justify-content: space-between;
border-bottom: 1px solid black;
}
h4 {
color: #e00a00;
}
.menu-text {
padding-top: 20px;
}
footer {
margin-top: 50px;
position: relative;
bottom: 30px;
width: 100%;
}
Step 3 (JavaScript Code):
Create a script.js
file to add your menu items dynamically. Here’s a breakdown of each part:
1. Data Structure
const menu = [ ... ];
The menu
array contains multiple objects, each representing a menu item with properties such as id
, title
, category
, price
, img
, and desc
. Each item belongs to a category like "APPETIZERS," "STEAKS," "SEAFOOD," etc.
2. DOM Selection
const section = document.querySelector(".section-center");
const btnContainer = document.querySelector(".btn-container");
These variables select HTML elements with the classes .section-center
(for displaying menu items) and .btn-container
(for category filter buttons).
3. Generating Unique Categories
const categories = menu.reduce((values, item) => { ... }, ["ALL"]);
Using reduce
, this code extracts unique categories from menu
. If a category is not already in the values
array, it adds it. The initial values
array starts with "ALL"
, representing an option to show all items.
4. Rendering Category Buttons
const categoryList = () => { ... };
This function generates HTML buttons for each category:
- The
map
method creates a button for each category and joins them into a single string (categoryBtns
). - This string is inserted into
btnContainer
as inner HTML. - Each button gets an event listener to filter the menu when clicked.
5. Filtering Menu by Category
filterBtns.forEach((btn) => { ... });
Each category button triggers an event listener:
e.currentTarget.dataset.id
retrieves the clicked button’s category.menu.filter
creates a new array (menuCategory
) with items matching the selected category.- If the
"ALL"
category is clicked,menuList
is called with the entiremenu
array. Otherwise, it usesmenuCategory
to display filtered items.
6. Displaying Menu Items
const menuList = (menuItems) => { ... };
The menuList
function takes an array of menu items (menuItems
) and:
- Maps over each item, creating HTML for the item’s image, title, price, and description.
- Joins these items into a single HTML string and assigns it to
section.innerHTML
, updating the displayed menu.
7. Initial Menu Display and Button Creation
menuList(menu);
categoryList();
This runs menuList
initially to show all menu items and categoryList
to create the category buttons on page load.
const menu = [
{
id: 1,
title: "Spicy Lobster",
category: "APPETIZERS",
price: 19.00,
img:
"https://food.fnr.sndimg.com/content/dam/images/food/fullset/2020/02/05/KC2312_lobster-scampi_s4x3.jpg.rend.hgtvcom.616.462.suffix/1580923140032.jpeg",
desc: `Ounce lobster tails, white wine, san marzano, red chile, olive oil. `,
},
{
id: 2,
title: "Baked Escargot",
category: "APPETIZERS",
price: 16.00,
img:
"https://assets.epicurious.com/photos/57a8adfbb10b4fb03f234f37/master/w_1000,h_667,c_limit/escargots-a-la-bourguignonne.jpg",
desc: `White wine, escargots, parmesan cheese, butter, olive. `,
},
{
id: 3,
title: "Seared Ahi Tuna",
category: "APPETIZERS",
price: 17.50,
img:
"https://hips.hearstapps.com/hmg-prod/images/190226-seared-tuna-435-1552085484.jpg?crop=0.888888888888889xw:1xh;center,top&resize=1200:*",
desc: `Ahi tuna, soy sauce, honey, toasted sesame oil, toasted sesame honey marinade. `,
},
{
id: 4,
title: "Prosciutto Wrapped Mozarella",
category: "APPETIZERS",
price: 14.00,
img:
"https://www.sweetashoney.co/wp-content/uploads/Proscuitto-Wrapped-Mozzarella-7.jpg",
desc: `Balsamic vinegar, fresh mozzarella balls, grape tomatoes. `,
},
{
id: 5,
title: "Filet Mignon, 8 ounce",
category: "STEAKS",
price: 38.00,
img:
"https://qvc.scene7.com/is/image/QVC/m/98/m66298.001",
desc: `Filet mignon, rosemary, butter, olive oil, black pepper. `,
},
{
id: 6,
title: "Filet Mignon, 12 ounce",
category: "STEAKS",
price: 49.00,
img:
"https://i0.wp.com/peteandsams.com/wp-content/uploads/2018/08/HC-Filet-1_small-1024x688.jpg?fit=1024%2C688&ssl=1",
desc: `Filet mignon steaks, garlic, sea salt, fresh rosemary, black pepper. `,
},
{
id: 7,
title: "Rib Eye Steak, 18 ounce",
category: "STEAKS",
price: 39.00,
img:
"https://m.media-amazon.com/images/W/IMAGERENDERING_521856-T1/images/I/61xeljO9CiL.jpg",
desc: `Kansas City Steak Company signature cut Bone-in Ribeye Steak. `,
},
{
id: 8,
title: "Stuffed Lobster Tail",
category: "SEAFOOD",
price: 18.50,
img:
"https://food.fnr.sndimg.com/content/dam/images/food/fullset/2022/07/18/QK706-kardea-brown-crab-stuffed-lobster-tails-with-blender-bernaise.jpg.rend.hgtvcom.616.462.suffix/1658176726805.jpeg",
desc: `Lobster tails, jumbo lump crabmeat, lemon juice, garlic. `,
},
{
id: 9,
title: "Maryland Crab Cake Dinner",
category: "SEAFOOD",
price: 16.00,
img:
"https://happilyunprocessed.com/wp-content/uploads/2019/01/killer-maryland-crab-cakes.jpg",
desc: `Old bay seasoning, lump crab meat, dijon mustard. `,
},
{
id: 10,
title: "Whole Lobster",
category: "SEAFOOD",
price: 19.00,
img:
"https://www.foodrepublic.com/wp-content/uploads/2012/05/Grilled_Lobster.jpg",
desc: `Live maine lobster, butter, sea salt, lemon. `,
},
{
id: 11,
title: "Spinach Salad",
category: "SALADS",
price: 9.50,
img:
"https://www.cookingchanneltv.com/content/dam/images/cook/fullset/2016/4/13/0/CCTIF213H_Warm-Spinach-Salad_s4x3.jpg",
desc: `Additional ingredients include tomatoes, eggs, cheese, slivered almonds, walnuts and/or fresh or dried berries, such as cranberry, or strawberry. `,
},
{
id: 12,
title: "Caprese Salad",
category: "SALADS",
price: 10.50,
img:
"https://www.thespruceeats.com/thmb/2pjgFA7_nbZtlXr68BECvf6fO48=/1500x0/filters:no_upscale():max_bytes(150000):strip_icc()/caprese-salad-tomato-salad-2217097-hero-03-75a0b89b30aa4a52b10fe4fdd9abfeb5.jpg",
desc: `An Italian salad, made of sliced fresh mozzarella, tomatoes, and sweet basil, seasoned with salt, and olive oil. `,
},
{
id: 13,
title: "Apple Crisp",
category: "DESSERTS",
price: 8.50,
img:
"https://storcpdkenticomedia.blob.core.windows.net/media/recipemanagementsystem/media/recipe-media-files/recipes/retail/x17/17651-cinnamon-apple-crisp-760x580.jpg?ext=.jpg",
desc: `Warm apple cinnamon filling topped with a crunchy oat crumble, vanilla ice cream and caramel sauce. `,
},
{
id: 14,
title: "Twin Cannoli",
category: "DESSERTS",
price: 7.00,
img:
"https://www.mystoryinrecipes.com/uploads/4/4/9/3/44938739/5321015_orig.jpg",
desc: `Two crisp cannoli shells filled with our house made chocolate chip ricotta cannoli cream. `,
},
];
const section = document.querySelector(".section-center");
const btnContainer = document.querySelector(".btn-container");
const categories = menu.reduce(
(values, item) => {
if (!values.includes(item.category)) {
values.push(item.category);
}
return values;
},
["ALL"]
);
const categoryList = () => {
const categoryBtns = categories
.map((category) => {
return `<button class="btn btn-outline-dark btn-item" data-id=${category}>${category}</button>`;
})
.join("");
btnContainer.innerHTML = categoryBtns;
const filterBtns = document.querySelectorAll(".btn-item");
filterBtns.forEach((btn) => {
btn.addEventListener("click", (e) => {
const category = e.currentTarget.dataset.id;
console.log(category);
const menuCategory = menu.filter((menuItem) => {
if (menuItem.category === category) {
return menuItem;
}
});
if (category === "ALL") {
menuList(menu);
} else {
menuList(menuCategory);
}
});
});
};
const menuList = (menuItems) => {
let displayMenu = menuItems.map((item) => {
return `<div class="menu-items col-lg-6 col-sm-12">
<img
src=${item.img}
alt=${item.title}
class="photo"
/>
<div class="menu-info">
<div class="menu-title">
<h4>${item.title}</h4>
<h4 class="price">$${item.price}</h4>
</div>
<div class="menu-text">
${item.desc}
</div>
</div>
</div>
`;
});
displayMenu = displayMenu.join("");
section.innerHTML = displayMenu;
};
menuList(menu);
categoryList();
Final Output:
Conclusion:
Congratulations! You've successfully created a restaurant menu page using HTML, CSS, and JavaScript. This project not only helps you practice your coding skills but also gives you a practical example of how web pages are built. You can add more menu items or enhance the design with additional CSS styles.
Now that you have the basics down, you can explore more complex features like adding images, animations, or even making your menu interactive.
Code by: Zeynep Bilge Ozkan
That’s a wrap!
I hope you enjoyed this post. Now, with these examples, you can create your own amazing page.
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊