Published on

Master Basic CSS by Creating a Stylish Cafe Menu: A Beginners Guide

Authors

'Master Basic CSS by Creating a Stylish Cafe Menu: A Beginners Guide'

Learn fundamental CSS concepts like Flexbox, typography, and the box model by building a beautiful, practical cafe menu from scratch. Perfect for beginners!

Table of Contents

Have you ever written a line of HTML, loaded it in your browser, and felt that spark of excitement seeing your creation come to life? Now, imagine taking that plain text and transforming it into a beautifully designed, professional-looking webpage. That's the magic of CSS, and it's more accessible than you think.

In this comprehensive guide, we're going to demystify the basics of Cascading Style Sheets (CSS) by building something tangible and fun: a stylish menu for a fictional cafe. Why a menu? It's the perfect project for beginners! It allows us to explore typography, layout, spacing, and color in a contained, practical way. By the end of this tutorial, you'll not only have a great-looking project for your portfolio but also a solid grasp of the fundamental CSS concepts that power the web.

What You'll Learn:

  • How to structure your content with semantic HTML.
  • The fundamentals of the CSS Box Model.
  • Styling text and importing custom web fonts.
  • Laying out content with the power of Flexbox.
  • Adding polish with shadows, transitions, and pseudo-classes.

Prerequisites: A basic understanding of HTML tags is helpful, but no prior CSS knowledge is required. We'll start from scratch. Ready to become a CSS wizard? Let's get brewing!


Section 1: The Foundation - Structuring Our Menu with HTML

Before we can paint a masterpiece, we need a canvas. In web development, our canvas is a well-structured HTML document. Good HTML gives our content meaning and provides the hooks we need to apply our CSS styles. Let's create the skeleton for our cafe menu.

Create a new folder for your project. Inside it, create two files: index.html and styles.css.

Open index.html and paste in the following boilerplate code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>The Cozy Bean Cafe</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>

    <!-- Our menu content will go here -->

</body>
</html>

Now, let's add the menu structure inside the <body> tag. We'll use semantic tags like <main>, <section>, and <article> to give our content clear meaning.

  • <main>: This will wrap our entire menu.
  • <h1> & <p>: For the cafe's name and tagline.
  • <section>: To group different categories of items (e.g., Coffee, Tea).
  • <h2>: For the title of each section.
  • <article>: To represent a single menu item.
  • <p> tags with classes: To distinguish between the item's name and its price.

Here is the complete HTML structure. Replace <!-- Our menu content will go here --> with this:

<main class="menu">
    <div class="menu-header">
        <h1>The Cozy Bean</h1>
        <p>Where every cup is a warm hug.</p>
    </div>

    <section class="menu-section">
        <h2 class="section-title">Coffee & Espresso</h2>
        <article class="menu-item">
            <p class="item-name">Drip Coffee</p>
            <p class="item-price">$2.50</p>
        </article>
        <article class="menu-item">
            <p class="item-name">Espresso</p>
            <p class="item-price">$3.00</p>
        </article>
        <article class="menu-item">
            <p class="item-name">Latte</p>
            <p class="item-price">$4.25</p>
        </article>
        <article class="menu-item special">
            <p class="item-name">Caramel Macchiato</p>
            <p class="item-price">$4.75</p>
        </article>
    </section>

    <section class="menu-section">
        <h2 class="section-title">Teas & More</h2>
        <article class="menu-item">
            <p class="item-name">Chai Latte</p>
            <p class="item-price">$4.50</p>
        </article>
        <article class="menu-item">
            <p class="item-name">Matcha Latte</p>
            <p class="item-price">$5.00</p>
        </article>
        <article class="menu-item">
            <p class="item-name">Hot Chocolate</p>
            <p class="item-price">$3.75</p>
        </article>
    </section>

    <section class="menu-section">
        <h2 class="section-title">Pastries</h2>
        <article class="menu-item">
            <p class="item-name">Croissant</p>
            <p class="item-price">$3.00</p>
        </article>
        <article class="menu-item">
            <p class="item-name">Cinnamon Roll</p>
            <p class="item-price">$3.50</p>
        </article>
    </section>
</main>

If you open index.html in your browser now, it will look very plain. That's perfect! We have our raw materials ready. Now, let's start styling.

Section 2: First Styles and The Box Model

Open your empty styles.css file. The first thing we need to do is tell the browser how we want it to calculate the size of our elements. This might sound strange, but it's a crucial first step that prevents a lot of headaches later.

The box-sizing Reset

Every element in HTML is a rectangular box. This box has content, padding, a border, and a margin. By default, when you set width: 200px;, the browser applies that width to the content area only. Padding and borders are then added on top of that width, making the element bigger than you intended.

We can fix this with a simple rule. Add this to the top of your styles.css:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
  • The * is a universal selector; it targets every single element on the page.
  • margin: 0; and padding: 0; removes the default spacing that browsers add to elements like headings and paragraphs.
  • box-sizing: border-box; is the magic. It tells the browser to include padding and borders within the total width and height of an element. If you set width: 200px;, the element will be exactly 200px wide, period. This is much more intuitive.

Setting Up the Body

Next, let's set up some global styles for the entire page by targeting the <body> tag. This is where we can define a background color and a default font.

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: #f4f1eb;
    color: #333;
    line-height: 1.6;
}
  • font-family: This is a "font stack." The browser will try to use the first font ('Segoe UI'). If the user doesn't have it, it moves to the next ('Tahoma'), and so on. It's a fallback system to ensure your site looks acceptable on any device.
  • background-color: We're using a soft, off-white color (#f4f1eb) for a warm, cozy feel.
  • color: This sets the default text color for the entire page.
  • line-height: This increases the space between lines of text, making everything more readable.

Save your styles.css file and refresh index.html in your browser. You should see the background color change and the font style update. The default margins are gone, and everything is flush against the top-left corner. We're in control now!

Section 3: Styling the Menu Container and Typography

Our menu content is currently stretched across the entire width of the page. Let's rein it in and make it look like a distinct menu card.

Centering the Menu

We'll target the <main> element, which we gave a class of menu.

.menu {
    width: 90%;
    max-width: 800px;
    margin: 50px auto;
    padding: 30px;
    background-color: #fff;
    border-radius: 10px;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

Let's break this down:

  • width: 90%;: The menu will take up 90% of the browser's width.
  • max-width: 800px;: ...but it will never get wider than 800px. This combination makes our layout responsive on smaller screens without looking gigantic on large monitors.
  • margin: 50px auto;: This is a powerful shorthand. 50px applies 50 pixels of margin to the top and bottom. auto tells the browser to automatically calculate the left and right margins, which has the effect of perfectly centering the block-level element.
  • padding: 30px;: Adds 30px of space inside the menu container, pushing the content away from the edges.
  • background-color: #fff;: A clean white background to make it pop against our beige body.
  • border-radius: 10px;: This rounds the corners of our menu card.
  • box-shadow: This adds a subtle shadow. The values are: horizontal-offset vertical-offset blur-radius spread-radius color. Here, we're using a semi-transparent black (rgba(0, 0, 0, 0.1)) to create a soft, lifting effect.

Importing a Custom Font and Styling Headers

The default font is okay, but for a stylish cafe, we need better typography. Let's use Google Fonts, a free library of thousands of web fonts.

  1. Go to fonts.google.com.
  2. Search for two fonts: "Playfair Display" (for headings) and "Lato" (for body text).
  3. Select a style for each (e.g., "Regular 400" and "Bold 700" for Playfair Display, "Regular 400" for Lato).
  4. Click the "View selected families" icon, and then select the @import tab. Copy the @import code.

Now, paste this @import rule at the very top of your styles.css file, even before the * reset.

@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400&family=Playfair+Display:wght@400;700&display=swap');

/* ... rest of your CSS ... */

Now we can use these fonts. Let's update our body and add styles for our headings.

/* Update the body rule */
body {
    font-family: 'Lato', sans-serif; /* Use Lato for body text */
    background-color: #f4f1eb;
    color: #4a4a4a; /* A slightly softer black */
    line-height: 1.6;
}

/* Style the main header */
.menu-header {
    text-align: center;
    margin-bottom: 40px;
}

.menu-header h1 {
    font-family: 'Playfair Display', serif;
    font-size: 3rem; /* 'rem' is a responsive unit of measurement */
    color: #8B4513; /* A saddle brown color */
    font-weight: 700;
}

.menu-header p {
    font-size: 1.1rem;
    color: #777;
}

/* Style the section titles */
.section-title {
    font-family: 'Playfair Display', serif;
    font-size: 2rem;
    color: #333;
    text-align: center;
    margin-bottom: 25px;
    border-bottom: 2px solid #f0e5d8;
    padding-bottom: 10px;
}

Refresh your browser. Wow! The difference is huge. We have a beautifully centered menu card with elegant typography. The custom fonts add a ton of personality.

Section 4: The Magic of Flexbox for Item Layout

Right now, our menu items (name and price) are stacked on top of each other. We want them on the same line, with the name on the left and the price on the right. This is a perfect job for Flexbox.

Flexbox is a CSS layout model that makes it easy to align and distribute space among items in a container. To use it, we simply apply display: flex; to the parent container (.menu-item).

.menu-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 15px;
}

Let's unpack these powerful properties:

  • display: flex;: This turns the .menu-item article into a "flex container." Its direct children (the <p> tags for name and price) are now "flex items."
  • justify-content: space-between;: This is the key. It takes all the available horizontal space within the container and distributes it between the flex items, pushing them to opposite ends.
  • align-items: center;: This vertically aligns the flex items in the center of the container. It's useful if the name and price have different font sizes.
  • margin-bottom: 15px;: Adds some breathing room between each menu item.

Now let's style the text inside the items themselves.

.item-name {
    font-size: 1.1rem;
    font-weight: bold;
}

.item-price {
    font-size: 1.1rem;
    color: #8B4513;
    font-weight: bold;
}

Save and refresh. Just like that, our items are perfectly aligned. This is the power of modern CSS. What used to be a complicated task is now accomplished with just a few lines of code.

Section 5: Adding Stylish Flourishes

Our menu is functional, but now it's time for the details that make a design feel polished and professional.

The Classic Dotted Line Connector

A common feature in menus is a dotted line that connects the item name to the price. This helps the eye track across the empty space. With Flexbox, this is surprisingly elegant to achieve.

First, we need to modify our HTML slightly. We'll add an empty <span> between the name and the price. This span will act as our flexible, dotted line.

Update one of the <article> elements to see how it works:

<!-- FROM THIS: -->
<article class="menu-item">
    <p class="item-name">Latte</p>
    <p class="item-price">$4.25</p>
</article>

<!-- TO THIS: -->
<article class="menu-item">
    <p class="item-name">Latte</p>
    <span class="dots"></span>
    <p class="item-price">$4.25</p>
</article>

Go ahead and add <span class="dots"></span> to all your .menu-item articles.

Now, for the CSS magic. We'll tell this <span> to grow and fill all the available space, and then we'll give it a dotted bottom border.

.dots {
    flex-grow: 1;
    border-bottom: 2px dotted #ccc;
    margin: 0 10px;
    position: relative;
    top: -4px; /* Adjust vertical position */
}
  • flex-grow: 1;: This is the star of the show. It tells this flex item (.dots) to take up any remaining space in the flex container. Since the name and price have fixed widths based on their content, the .dots span will expand and contract to fill the gap perfectly.
  • border-bottom: We create the line using a border.
  • margin: 0 10px;: Adds a little space between the line and the text on either side.
  • position: relative; top: -4px;: A little tweak to nudge the dotted line down so it aligns better with the middle of the text.

Highlighting a Special Item

Remember we added a .special class to the Caramel Macchiato? Let's use that to make it stand out. We can use a pseudo-element (::after) to add a small "Special!" badge.

.special {
    position: relative; /* Needed for absolute positioning of the pseudo-element */
}

.special .item-name::after {
    content: 'Special!';
    background-color: #ffc107;
    color: #333;
    font-size: 0.7rem;
    font-weight: bold;
    padding: 2px 6px;
    border-radius: 4px;
    margin-left: 10px;
    vertical-align: middle;
}
  • position: relative;: We add this to the .special item so we can position the ::after element relative to it.
  • .special .item-name::after: This selector targets a pseudo-element that is created after the content of the .item-name element, but only if it's inside a .special item.
  • content: 'Special!';: A pseudo-element is invisible without the content property. This is the text it will display.
  • The rest of the properties are for styling our little badge to make it look nice.

Section 6: Interactive Polish with Pseudo-classes and Transitions

A great user experience often involves subtle feedback. Let's make our menu feel more interactive by adding a hover effect.

We'll use the :hover pseudo-class, which applies styles only when the user's mouse is over an element.

.menu-item {
    /* ... existing styles ... */
    padding: 10px;
    border-radius: 5px;
    transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
}

.menu-item:hover {
    background-color: #f9f6f2;
    transform: scale(1.02);
}

Here's what we added:

  1. To the original .menu-item rule, we added padding, a border-radius, and a transition.
    • The transition property is what makes the change smooth. We're telling the browser: "If the background-color or transform properties change, animate that change over 0.3 seconds using an ease-in-out timing function."
  2. We created a new rule, .menu-item:hover.
    • background-color: #f9f6f2;: When hovered, the item's background will change to a slightly darker shade.
    • transform: scale(1.02);: This will make the item grow by 2%, giving it a satisfying "pop" effect.

Save and refresh. Now when you mouse over the menu items, they'll smoothly change color and size. This small detail makes the page feel much more alive and professional.


Conclusion: You've Mastered the Basics!

Take a step back and look at what you've built. From a plain, unstyled HTML document, you've created a genuinely stylish and professional-looking cafe menu. More importantly, you've used some of the most fundamental and powerful tools in the CSS toolbox.

Let's recap what you've accomplished:

  • You learned the importance of a semantic HTML structure.
  • You mastered the essential box-sizing: border-box reset.
  • You styled typography, imported custom Google Fonts, and managed colors.
  • You used margin: auto to center layouts.
  • You harnessed the power of Flexbox (display: flex, justify-content, flex-grow) to create a complex, responsive alignment with ease.
  • You added polish with box-shadow, border-radius, and pseudo-elements (::after).
  • You made the page interactive with the :hover pseudo-class and smooth transition effects.

These concepts are not just for menus; they are the building blocks for almost any website layout you can imagine. You now have a solid foundation to build upon.

What's Next?

Don't stop here! The best way to learn is by experimenting. Here are a few challenges to take your skills to the next level:

  1. Make it Responsive: Our menu looks decent on mobile, but it could be better. Research CSS Media Queries to change styles for different screen sizes. For example, you could reduce the font size on smaller screens.
  2. New Color Scheme: Try creating a different theme. Maybe a dark mode menu?
  3. Add Images: Try adding a small thumbnail image for each menu item and use Flexbox to align it.
  4. Add a Footer: Create a footer for the menu with fictional contact information or social media icons.

Congratulations on completing this project! You've taken a massive step in your web development journey. Keep building, keep experimenting, and have fun with the creative power of CSS.