Beginner60 minProjectPart 1 of 7

Black Swan Bistro — Part 1

Build Your First Web Page

Learning Objectives

By the end of this lesson, you'll be able to:

  • Set up a project folder with proper file and folder structure
  • Write a semantically correct HTML homepage from scratch
  • Use headings, paragraphs, lists, links, images, and a table in context
  • Create Create a linked CSS stylesheet with colour variables, typography, and layout
  • Preview and debug your page in a browser

Why This Matters:

Most tutorials teach HTML and CSS as separate topics. Real projects need both working together. By building a complete page from start to finish, you’ll see how everything connects — and you’ll have a genuine project to show for it.

Step 1 — Set Up Your Project

Every professional web project starts the same way: an organised folder with files in predictable locations. Let’s create ours.

Where Should Your Project Live?

Before you create anything, decide where on your computer your web projects will live. Pick one location and stick with it — consistency will save you time later.

Operating SystemRecommended Location
macOS~/Sites/ — This is the traditional web development folder on Mac. Open Finder and you’ll find it in your home directory. If it doesn’t exist, create it.
WindowsC:\Users\YourName\Projects\ — Create a Projects folder in your user directory. Avoid putting projects on the Desktop or in OneDrive — syncing services can interfere with development tools.
Linux~/projects/ or ~/Sites/ — Either works. Create whichever name you prefer in your home directory.

Important: Avoid putting projects in cloud-synced folders (Dropbox, iCloud, OneDrive) or on external drives. Build tools like Vite can create thousands of tiny files in node_modules, which confuse sync services and slow everything down.

Create the Black Swan Bistro project

Navigate to your projects folder

Open your terminal and navigate to the folder where your web projects live:

# macOS
cd ~/Sites

# Windows (Command Prompt)
cd %USERPROFILE%\Projects

# Linux
cd ~/projects

If the folder doesn’t exist yet, create it first:

# macOS
mkdir -p ~/Sites && cd ~/Sites

# Windows (Command Prompt)
mkdir %USERPROFILE%\Projects && cd %USERPROFILE%\Projects

# Linux
mkdir -p ~/projects && cd ~/projects
💡 Need a hint?
Pick one location for all your web projects and stick with it. You’ll always know where to find your work.

Create the project folder

Now create the project folder and move into it:

mkdir black-swan-bistro
cd black-swan-bistro

Or create a new folder called black-swan-bistro in Finder / File Explorer.

💡 Need a hint?
Keep the name all lowercase with hyphens — no spaces, no capitals.

Create subfolders

Inside your project folder, create three subfolders:

mkdir css js images

In VS Code you can right-click in the Explorer panel → New Folder.

💡 Need a hint?
These three folders are the standard convention used by virtually every web project.

Create the core files

Create the starter files in their correct locations:

touch index.html css/style.css js/main.js

Or right-click the appropriate folder in VS Code → New File.

💡 Need a hint?
Make sure style.css goes inside the css/ folder, not in the project root.

Open in VS Code

Open the project folder in VS Code:

code .

Or launch VS Code and go to File → Open Folder…, then navigate to your black-swan-bistro folder (e.g. ~/Sites/black-swan-bistro on Mac).

You should see all three subfolders and your files in the Explorer sidebar on the left. If the sidebar isn’t visible, press Cmd+B (Mac) or Ctrl+B (Windows/Linux) to toggle it.

💡 Need a hint?
If the "code" command doesn’t work, open VS Code first, then use File → Open Folder. You can also drag the folder onto the VS Code icon.

Your project structure should now look like this:

black-swan-bistro/
├── index.html
├── css/
│   └── style.css
├── js/
│   └── main.js
└── images/
    └── (empty for now)

⏸️ Pause & Check: Do You Understand?

Before moving forward, can you answer these?

  1. Why is the homepage called index.html and not home.html?
  2. What are the three standard subfolders and what goes in each?
  3. Why do we use lowercase names with hyphens (e.g., black-swan-bistro)?
Check Your Answers
  1. Web servers look for index.html by default. When someone visits your domain without specifying a filename, the server automatically serves index.html.
  2. css/ for stylesheets, js/ for JavaScript files, and images/ for pictures, icons, and graphics.
  3. URLs are case-sensitive on most servers. Spaces cause problems in URLs (they become %20). Hyphens are readable and safe across all operating systems and web servers.

How confident are you with this concept?

😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!

Step 2 — Build the HTML

With the folder ready, it’s time to write the HTML. We’ll build the page section by section, using semantic elements — HTML tags that describe what the content is, not just how it looks.

The Boilerplate

Open index.html in VS Code and add the document shell. This is the foundation every HTML page needs:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Black Swan Bistro | Casual Riverside Dining in Perth</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>

    <!-- We'll add content here -->

</body>
</html>

Tip: In VS Code, type ! then press Tab to generate the boilerplate instantly (Emmet shortcut). Then add the <link> and <title> manually.

Header & Navigation

Inside the <body>, start with a <header> containing the restaurant name and a simple navigation. In Part 1 these links can point to sections on the homepage, but keep the labels aligned with the later multi-page project: Home, Menu, About, Contact.

<header>
    <h1>Black Swan Bistro</h1>
    <nav>
        <ul>
            <li><a href="#hero">Home</a></li>
            <li><a href="#menu">Menu</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</a></li>
        </ul>
    </nav>
</header>

Why these labels matter: The project brief and later tutorials use Home, Menu, About, and Contact as the shared site navigation. Keeping those labels now makes the jump from a single homepage to a multi-page site feel much more natural.

Why semantic elements? A <header> tells the browser (and screen readers) “this is the top section of the page.” A <nav> says “this is navigation.” Plain <div>s don’t communicate anything — they’re invisible to accessibility tools.

Hero Section

Below the header, add a hero section that welcomes visitors:

<section id="hero">
    <h2>Casual Riverside Dining in Perth</h2>
    <p>The Black Swan Bistro offers casual lunch and dinner fare
       in a relaxed riverside atmosphere. The menu changes
       seasonally to highlight the freshest Western Australian
       ingredients.</p>
    <a href="#menu">View Our Menu</a>
</section>

About Section

<section id="about">
    <h2>Our Story</h2>
    <p>Founded in 2010 by Chef <strong>Maria Rodriguez</strong>,
       Black Swan Bistro brings over 20 years of culinary
       experience to Perth’s Elizabeth Quay. We blend
       traditional Australian flavours with modern techniques,
       showcasing the finest local produce.</p>
    <p><em>Farm to table. Sustainability. Community.</em></p>
</section>

Notice: We use <strong> for the chef’s name (important information) and <em> for the tagline (emphasis). These are semantic choices — they convey meaning, not just bold/italic styling.

The full menu will come in Part 4, but a homepage should tease the highlights:

<section id="menu">
    <h2>Featured Menu</h2>

    <h3>Starters</h3>
    <ul>
        <li><strong>Sydney Rock Oysters</strong> &mdash; served with
            lemon myrtle mignonette</li>
        <li><strong>Kangaroo Carpaccio</strong> &mdash; with native
            pepperberry &amp; wattleseed crisps</li>
        <li><strong>Pumpkin &amp; Macadamia Soup</strong> &mdash;
            roasted butternut with toasted macadamia</li>
    </ul>

    <h3>Mains</h3>
    <ul>
        <li><strong>Pan-Seared Barramundi</strong> &mdash; with
            lemon butter, asparagus &amp; crushed potatoes</li>
        <li><strong>Grass-Fed Ribeye</strong> &mdash; 300g with
            red wine jus &amp; roasted vegetables</li>
        <li><strong>Wild Mushroom Risotto</strong> &mdash;
            arborio rice with truffle oil &amp; parmesan</li>
    </ul>

    <h3>Desserts</h3>
    <ul>
        <li><strong>Chocolate Lava Cake</strong> &mdash; with
            vanilla bean ice cream</li>
        <li><strong>Pavlova</strong> &mdash; with seasonal
            berries &amp; passionfruit coulis</li>
    </ul>
</section>

⏸️ Pause & Check: Do You Understand?

Before moving forward, can you answer these?

  1. What is the difference between <section> and <div>?
  2. Why do we use <strong> for menu item names instead of <b>?
  3. What does the id attribute on a <section> do?
Check Your Answers
  1. A <section> is a semantic element — it tells browsers and screen readers "this is a distinct section of content." A <div> has no meaning; it's just a generic container. Use <section> when the content represents a thematic grouping.
  2. <strong> means "this content is important" — screen readers will emphasise it. <b> just makes text bold visually without conveying any meaning. Semantic HTML uses <strong> for importance.
  3. It gives the section a unique identifier. Navigation links can point to it using href="#id" to scroll the user directly to that section. Each id must be unique on the page.

How confident are you with this concept?

😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!

Hours & Location

A table is the right element when you have rows and columns of related data — like opening hours:

<section id="hours">
    <h2>Hours &amp; Location</h2>

    <table>
        <thead>
            <tr>
                <th>Day</th>
                <th>Hours</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>Monday</td>
                <td>Closed</td>
            </tr>
            <tr>
                <td>Tuesday &ndash; Saturday</td>
                <td>5:30 pm &ndash; 10:00 pm</td>
            </tr>
            <tr>
                <td>Sunday Lunch</td>
                <td>12:00 pm &ndash; 3:00 pm</td>
            </tr>
        </tbody>
    </table>

    <address>
        123 Gourmet Lane, Elizabeth Quay<br>
        Perth, WA 6000<br>
        <a href="tel:+61893001234">(08) 9300 1234</a><br>
        <a href="mailto:hello@blackswanbistro.com.au">
            hello@blackswanbistro.com.au</a>
    </address>
</section>

Why <address>? The <address> element tells search engines and screen readers “this is contact information.” It’s a small semantic detail that improves accessibility and SEO.

<footer>
    <p>&copy; 2025 Black Swan Bistro. All rights reserved.</p>
    <p>
        <a href="#">Facebook</a> |
        <a href="#">Instagram</a> |
        <a href="#">TripAdvisor</a>
    </p>
</footer>

Save the file and open index.html in your browser. You should see all your content displayed in plain, unstyled HTML — readable, structured, and semantic. It won’t look pretty yet, but every element is in place.

Step 3 — Style with CSS

Now let’s transform that plain HTML into something that looks like a real restaurant website. Open css/style.css and we’ll build the stylesheet section by section.

Colour Variables & Base Styles

Start by defining the restaurant’s brand colours as CSS custom properties. This means you only need to change one value to update the colour everywhere it’s used:

/* ── Brand colours ─────────────────────────────── */
:root {
    --bistro-burgundy: #7d1c20;
    --bistro-gold: #d4af37;
    --bistro-ink: #2a1c16;
    --bistro-charcoal: #1c1c1c;
    --bistro-cream: #f6f1eb;
    --bistro-smoke: #ede7df;
}

/* ── Base reset & typography ──────────────────── */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: 'Source Sans Pro', Arial, sans-serif;
    color: var(--bistro-ink);
    background-color: var(--bistro-cream);
    line-height: 1.6;
}

Why custom properties? If the client says “make the burgundy a bit darker,” you change one line and every heading, link, and border using var(--bistro-burgundy) updates automatically. This is how professionals manage colours.

Header & Navigation

/* ── Header ────────────────────────────────────── */
header {
    background-color: var(--bistro-charcoal);
    color: #f8f8f8;
    padding: 1.5rem 2rem;
    text-align: center;
}

header h1 {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 2.4rem;
    letter-spacing: 0.05em;
    margin-bottom: 0.5rem;
}

/* ── Navigation ───────────────────────────────── */
nav ul {
    list-style: none;
    display: flex;
    justify-content: center;
    gap: 2rem;
}

nav a {
    color: #f8f8f8;
    text-decoration: none;
    font-size: 1.1rem;
    transition: color 0.3s ease;
}

nav a:hover {
    color: var(--bistro-gold);
}

Hero Section

/* ── Hero ──────────────────────────────────────── */
#hero {
    background-color: var(--bistro-burgundy);
    color: #fff;
    text-align: center;
    padding: 4rem 2rem;
}

#hero h2 {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 2rem;
    margin-bottom: 1rem;
}

#hero p {
    max-width: 600px;
    margin: 0 auto 1.5rem;
    font-size: 1.1rem;
    line-height: 1.8;
}

#hero a {
    display: inline-block;
    padding: 0.75rem 2rem;
    background-color: var(--bistro-gold);
    color: var(--bistro-charcoal);
    text-decoration: none;
    font-weight: 600;
    border-radius: 4px;
    transition: background-color 0.3s ease;
}

#hero a:hover {
    background-color: #c9a030;
}

Content Sections

/* ── Sections (shared) ─────────────────────────── */
section {
    max-width: 900px;
    margin: 0 auto;
    padding: 3rem 2rem;
}

section h2 {
    font-family: 'Playfair Display', Georgia, serif;
    font-size: 1.8rem;
    color: var(--bistro-burgundy);
    margin-bottom: 1rem;
    border-bottom: 2px solid var(--bistro-gold);
    padding-bottom: 0.5rem;
}

section h3 {
    font-size: 1.3rem;
    color: var(--bistro-charcoal);
    margin-top: 1.5rem;
    margin-bottom: 0.75rem;
}

Menu List Styling

/* ── Menu items ────────────────────────────────── */
#menu ul {
    list-style: none;
    padding: 0;
}

#menu li {
    padding: 0.75rem 0;
    border-bottom: 1px dotted var(--bistro-smoke);
}

#menu li:last-child {
    border-bottom: none;
}

Hours Table

/* ── Table ─────────────────────────────────────── */
table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 2rem;
}

th {
    background-color: var(--bistro-burgundy);
    color: #fff;
    padding: 0.75rem 1rem;
    text-align: left;
}

td {
    padding: 0.75rem 1rem;
    border-bottom: 1px solid var(--bistro-smoke);
}

tr:nth-child(even) {
    background-color: var(--bistro-smoke);
}

/* ── Address ───────────────────────────────────── */
address {
    font-style: normal;
    line-height: 1.8;
}

address a {
    color: var(--bistro-burgundy);
}
/* ── Footer ────────────────────────────────────── */
footer {
    background-color: var(--bistro-charcoal);
    color: #ccc;
    text-align: center;
    padding: 2rem;
    margin-top: 2rem;
}

footer a {
    color: var(--bistro-gold);
    text-decoration: none;
}

footer a:hover {
    text-decoration: underline;
}

⏸️ Pause & Check: Do You Understand?

Before moving forward, can you answer these?

  1. What advantage do CSS custom properties (variables) give you over hard-coded colour values?
  2. Why does the nav use display: flex and gap instead of float?
  3. What does box-sizing: border-box do, and why set it on every element?
Check Your Answers
  1. You define a colour once in :root and reference it everywhere with var(). To change the brand colour, you update one line instead of hunting through the entire stylesheet.
  2. Flexbox handles horizontal spacing cleanly — items auto-centre, gap adds even spacing, and it's easy to switch to vertical stacking on mobile. Float-based navigation requires clearfix hacks and is harder to maintain.
  3. It makes width and height include padding and border, so a 300px-wide element stays 300px even when you add padding. Without it, padding increases the total size, which breaks layouts.

How confident are you with this concept?

😕 Still confused | 🤔 Getting there | 😊 Got it! | 🎉 Could explain it to a friend!

Step 4 — Make It Responsive

Your page needs to work on phones too. Add this at the bottom of your stylesheet:

/* ── Responsive ────────────────────────────────── */
@media (max-width: 700px) {
    header h1 {
        font-size: 1.8rem;
    }

    nav ul {
        flex-direction: column;
        gap: 0.75rem;
    }

    #hero {
        padding: 2.5rem 1rem;
    }

    #hero h2 {
        font-size: 1.5rem;
    }

    section {
        padding: 2rem 1rem;
    }
}

Save, refresh your browser, and resize the window. The nav should stack vertically on narrow screens, and the text should stay readable at any width.

Step 5 — Preview & Debug

Before calling this done, run through this quick checklist:

Pre-Flight Checklist

  • Open in browser — double-click index.html or use VS Code’s Live Server extension
  • Check DevTools Console — press F12 and look for errors (red text). A 404 means a file path is wrong
  • Validate your HTML — right-click → “View Page Source” and scan for unclosed tags or typos
  • Resize the window — does the layout hold up at phone, tablet, and desktop widths?
  • Check links — click each nav link. They should scroll to the matching section

Common issues:

  • Styles not loading? Check the <link> tag — does href="css/style.css" match your actual file path?
  • Fonts not changing? Google Fonts requires an internet connection. We’ll add the <link> for Playfair Display in Part 2; for now the fallback serif will kick in.
  • Nav links not scrolling? Make sure each section’s id matches the href in the nav (e.g., id="menu" and href="#menu").

💪 Extend Your Homepage

Now try this on your own without hints!

Your Task:

You’ve built the core homepage. Now add two more features on your own:

  1. A “Catering” section between About and Menu. Include a heading, a short paragraph about Black Swan Catering for events, and a link that says “Enquire Now” pointing to #contact.
  2. A “Gallery Preview” section before the footer. Add three placeholder <img> tags with descriptive alt text (the images can be broken for now — we’ll add real images in Part 2). Hint: use <figure> and <figcaption>.
Requirements:
  • Catering section uses a semantic <section> with an id
  • Heading hierarchy is correct (h2 for section title, not h1)
  • Enquire Now link points to #contact
  • Gallery uses <figure> and <figcaption> elements
  • All images have descriptive alt text
Stretch Goals (Optional):
  • Add matching CSS styles for both new sections
  • Add a nav link for the Catering section in the header
  • Style the gallery images in a row using display: flex

Success Criteria:

CriteriaYou've succeeded if...
Catering section uses a semantic <section> with an idSection has <section id=catering> wrapping the content
Heading hierarchy is correctUses <h2> for the section heading, not <h1>
Gallery uses <figure> and <figcaption>Each image is wrapped in <figure> with a <figcaption> caption
New sections have matching CSS stylesStyles follow the same pattern as existing sections

What You’ve Built

Take a moment to appreciate what you’ve accomplished. You now have:

  • A properly structured project folder with separated HTML, CSS, JS, and images
  • A semantic HTML homepage with header, nav, hero, about, menu, hours table, address, and footer
  • A CSS stylesheet with custom properties, typography, layout, and a responsive media query
  • A page that works on desktop and mobile

Coming Up in Part 2

In Part 2 — Layout & Sections, you’ll take this single-column page and give it a professional multi-section layout using CSS Flexbox. You’ll add Google Fonts, images, and refine the spacing and visual hierarchy.

Summary

🏁 Part 1 Complete: Your First Web Page

Key Takeaways:

  • Every web project starts with a clean folder structure: index.html at the root, css/, js/, and images/ subfolders.
  • Semantic HTML (<header>, <nav>, <section>, <footer>, <address>) communicates meaning to browsers, screen readers, and search engines.
  • CSS custom properties (--bistro-burgundy) let you manage brand colours from a single place.
  • A mobile-friendly @media query ensures your page works on any device.
  • DevTools (F12) is your debugging partner — always check the Console for errors.

Learning Objectives Review:

Look back at what you set out to learn. Can you now:

  • ✅ Set up a project folder with proper structure Check!
  • ✅ Write a semantic HTML homepage from scratch Got it!
  • ✅ Use headings, paragraphs, lists, links, a table, and address Can explain it!
  • ✅ Create a linked CSS stylesheet with variables and layout Could teach this!
  • ✅ Preview and debug in a browser Check!

If you can confidently answer "yes" to most of these, you're ready to move on!

Think & Reflect:

🏗️ Building from Scratch

  • What was the most surprising thing about building a real page from scratch?
  • Which step felt most natural? Which felt hardest?

🎨 HTML & CSS Together

  • Which HTML element did you find most useful? Which felt unfamiliar?
  • How did adding CSS change your perception of the plain HTML page?

🚀 Next Steps

  • If you were building this for a real restaurant, what would you add next?

🤔 Real-World Test:

Every real website follows this same process:

  1. Set up a project folder with clear structure
  2. Write semantic HTML with proper heading hierarchy
  3. Link a stylesheet and define brand colours as variables
  4. Test in the browser and fix issues with DevTools

You’ve just done all four. This is genuinely how professional web developers start every project.

🎯 Looking Ahead:

In Part 2, you’ll transform this single-column page into a proper layout with Flexbox, add images, integrate Google Fonts, and refine the visual design. Your Black Swan Bistro site is just getting started!

Recommended Next Steps

Continue Learning

Ready to move forward? Continue with the next tutorial in this series:

Black Swan Bistro (BSB) Part 2: Build the Homepage Wireframe Layout with CSS

Additional Resources

Deepen your understanding with these helpful resources:

Progress tracking is disabled. Enable it in to track your completed tutorials.