Create a Restaurant Menu Page with HTML, CSS, and JavaScript

Faraz

By Faraz - Last Updated:

Learn how to create a restaurant menu page using HTML, CSS, and JavaScript. Step-by-step guide for beginners!


create-a-restaurant-menu-page-with-html-css-and-javascript.webp

Table of Contents

  1. Project Introduction
  2. HTML Code
  3. CSS Code
  4. JavaScript Code
  5. Conclusion
  6. Preview

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:

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 an alt 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 uses flex 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 of 30% and height of 175px.
  • 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 uses justify-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 entire menu array. Otherwise, it uses menuCategory 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:

create-a-restaurant-menu-page-with-html-css-and-javascript.gif

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 😊

End of the article

Subscribe to my Newsletter

Get the latest posts delivered right to your inbox


Latest Post

Please allow ads on our site🥺