Build a Jewelry Business Landing Page

Build and deploy a jewelry landing page with a booking integration.

Introduction

30 Second Summary

When you run a jewelry business, every customer interaction matters. Your website is often the first impression someone has of your brand, and it needs to feel as polished as the pieces you create.

In this project, you will build a landing page for your jewelry business from scratch using HTML and CSS, connect your Square Appointments booking system, and deploy it live on the internet for free.

What You'll Build

A single-page landing page built with pure HTML and CSS that showcases your jewelry catalog and lets customers enquire about pieces or book consultations directly.

By the end of this project, you'll have:

  • A styled, mobile-friendly landing page with an elegant hero section, product catalog grid, and call-to-action buttons.
  • A product enquiry system where clicking "Enquire Now" on any piece opens the customer's email with a pre-filled subject line.
  • An integrated Square Appointments booking link so clients can schedule consultations directly from your page.
  • A live public URL hosted on Netlify where customers can visit your page from anywhere.
  • Secret Mission: Add a sticky navigation bar with smooth scrolling so customers can jump between sections effortlessly.

Are there any prerequisites?

You will need a Square Appointments account with online booking enabled before starting this project. If you do not have one yet, create a free account at squareup.com and set up online booking first.

Set Up Your Tools

Before you can build your jewelry landing page, you need a code editor to write your HTML and CSS in.

In this step, you will install Visual Studio Code (VS Code for short), create a project folder to keep your files organized, and gather the product images you want to showcase on your page.

In this step, get ready to:
  • Install VS Code, a free code editor.
  • Create your project folder and files.
  • Add placeholder images of your jewelry pieces.
Install Visual Studio Code

VS Code is a free code editor that makes writing HTML and CSS easy with color-coded syntax and helpful suggestions.

✔️ I already have VS Code

Great, you are all set. Open VS Code and move on to the next substep.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Visual Studio Code and press Enter to open it.

ⓧ I need to install VS Code

  • Open your web browser and go to https://code.visualstudio.com/.
  • Click Download for Windows.
  • Run the downloaded .exe installer file.
  • Follow the prompts and accept all defaults.
  • Once the installer finishes, press the Windows key to open your search bar.
  • Type Visual Studio Code and press Enter to open it.

You should see a Welcome tab when VS Code opens for the first time.

VS Code not opening?

Try restarting your computer after the install completes. Some Windows machines need a restart for new programs to appear in search.

Help me troubleshoot opening VS Code after installing it.

Create your project folder and files

Every web project needs a dedicated folder to hold its files. You will create one on your Desktop so it is easy to find later.

  • Right-click on your Desktop and select New, then Folder.
  • Name the folder jewelry-landing-page.
  • Open the jewelry-landing-page folder.
  • Inside it, right-click and select New, then Folder.
  • Name this subfolder images.

Why a separate images folder?

Keeping images in their own folder prevents your project root from getting cluttered. When your site goes live, the browser finds images using the path you specify in your HTML (like images/product1.jpg), so the folder name matters.

Now open this folder in VS Code so you can start creating files.

  • In VS Code, click File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop and select the jewelry-landing-page folder, then click Select Folder.

You should now see the jewelry-landing-page folder name in the Explorer panel on the left side of VS Code.

  • Hover over the folder name in the Explorer panel and click the New File... icon (it looks like a page with a small plus sign).
  • Type index.html and press Enter.
  • Click the New File... icon again.
  • Type style.css and press Enter.

Both files should now appear in the Explorer panel on the left.

What are these two files for?

The index.html file holds the structure and content of your page (headings, text, images, links). The style.css file controls how everything looks (colors, fonts, spacing, layout).

Don't see the Explorer panel?

Press Ctrl+Shift+E (Windows) or Cmd+Shift+E (macOS) to open the Explorer view. Make sure you opened the folder (not just a single file) through File then Open Folder.

Help me find the Explorer panel in VS Code.

Add placeholder images

Your landing page will display photos of your jewelry pieces. You need at least four images saved in the images folder with specific file names so the HTML can find them later.

  • Open your jewelry-landing-page folder on your Desktop in File Explorer.
  • Open the images subfolder.
  • Copy or save 4 to 6 photos of your jewelry pieces into this folder.
  • Rename the files to product1.jpg, product2.jpg, product3.jpg, product4.jpg (and so on if you have more).

No product photos yet?

You can use any placeholder images for now. Save any four pictures from your computer into the images folder and rename them following the same naming pattern. You can swap them for real product photos later.

  • Confirm your images folder contains at least 4 image files by checking the file count in File Explorer.

Images not showing in VS Code Explorer?

Make sure you saved the images directly inside the images folder (not in a subfolder within it). Also verify the file names use lowercase letters and end in .jpg or .png.

Help me get my images to appear in the correct folder.

Your workspace is ready to go. Next up, you will write the HTML that gives your landing page its structure and content.

Build Your HTML Page Structure

Your tools are ready and your project folder is set up. Now it is time to build the actual content your customers will see.

Every web page starts with HTML, the language that defines what content appears on the page and how it is structured. In this step, you will write the full HTML for your jewelry landing page and preview it in the browser.

In this step, get ready to:
  • Write the complete HTML structure for your landing page.
  • Understand the key sections and how they work for your business.
  • Preview your page in the browser to confirm it loads correctly.
Write the page head, hero, and about section

The top of your HTML file tells the browser how to render the page and loads your fonts. Then the hero section creates a bold first impression for visitors.

  • In VS Code, click on index.html in the Explorer sidebar to open it.
  • Type the following code into the empty file:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Elegant Jewels - Handcrafted Fine Jewelry</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Inter:wght@300;400;500&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="style.css">
</head>
<body>

    <!-- Hero Section -->
    <header class="hero">
        <div class="hero-overlay"></div>
        <div class="hero-content">
            <h1>Elegant Jewels</h1>
            <p class="tagline">Handcrafted fine jewelry for life's most precious moments</p>
            <a href="#catalog" class="btn btn-primary">Explore Collection</a>
        </div>
    </header>

    <!-- About Section -->
    <section id="about" class="about">
        <h2>Our Story</h2>
        <p>Every piece in our collection is thoughtfully designed and handcrafted with care. From custom engagement rings to statement necklaces, we create jewelry that tells your story. Whether you are looking for a timeless classic or a one-of-a-kind design, we are here to bring your vision to life.</p>
    </section>

What does this code do?

The <head> section sets up your page behind the scenes. It loads two elegant fonts from Google Fonts (Playfair Display for headings and Inter for body text) and connects your stylesheet.

The hero section is the full-screen banner your customers see first. The Explore Collection button links to the catalog section further down the page using #catalog as the href.

You will not see a visible change yet. The next two chunks complete the page before you preview it.

Seeing red underlines in VS Code?

VS Code may show warnings because the HTML is incomplete (no closing </body> or </html> tags yet). This is normal and will resolve once you finish typing the rest of the page.

If you see a completely red file, double-check that the very first line is <!DOCTYPE html> with no spaces before it.

Help me fix HTML errors in my index.html file.

Add the product catalog section

The catalog is the heart of your landing page. Each product card displays an image, a name, a starting price, and an "Enquire Now" button that opens the customer's email app.

  • Directly below the about section you just typed, add the following code:
    <!-- Catalog Section -->
    <section id="catalog" class="catalog">
        <h2>Our Collection</h2>
        <p class="section-subtitle">Browse our pieces and enquire about any item that catches your eye</p>
        <div class="catalog-grid">

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product1.jpg" alt="Gold Statement Necklace">
                </div>
                <div class="product-info">
                    <h3>Gold Statement Necklace</h3>
                    <p class="price">From $350</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Gold%20Statement%20Necklace" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product2.jpg" alt="Diamond Engagement Ring">
                </div>
                <div class="product-info">
                    <h3>Diamond Engagement Ring</h3>
                    <p class="price">From $1,200</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Diamond%20Engagement%20Ring" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product3.jpg" alt="Pearl Drop Earrings">
                </div>
                <div class="product-info">
                    <h3>Pearl Drop Earrings</h3>
                    <p class="price">From $180</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Pearl%20Drop%20Earrings" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product4.jpg" alt="Custom Charm Bracelet">
                </div>
                <div class="product-info">
                    <h3>Custom Charm Bracelet</h3>
                    <p class="price">From $250</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Custom%20Charm%20Bracelet" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

        </div>
    </section>

What does this code do?

Each product-card div is a self-contained card showing one jewelry piece. The img tag pulls your photo from the images folder.

The "Enquire Now" links use a mailto: href with a URL-encoded subject line. When a customer clicks it, their email app opens with your address and the product name already filled in.

You will not see a visible change yet. The next chunk finishes the page.

Worried about the placeholder email?

The code uses your-email@example.com as a placeholder. You will replace this with your real business email in a later step. For now, leave it as-is.

Help me understand how mailto links work in HTML.

Add the process, contact, and footer sections

The bottom of your page explains how your business works, invites customers to book a consultation, and closes with a footer.

  • Directly below the catalog section, add the following code to complete your page:
    <!-- How It Works Section -->
    <section id="process" class="process">
        <h2>How It Works</h2>
        <div class="steps-grid">
            <div class="step">
                <span class="step-number">1</span>
                <h3>Browse and Enquire</h3>
                <p>Explore our collection and send an enquiry about any piece that inspires you.</p>
            </div>
            <div class="step">
                <span class="step-number">2</span>
                <h3>Book a Consultation</h3>
                <p>Schedule a free consultation to discuss your vision, customization options, and details.</p>
            </div>
            <div class="step">
                <span class="step-number">3</span>
                <h3>Receive Your Piece</h3>
                <p>We handcraft your jewelry with care and deliver it beautifully packaged to you.</p>
            </div>
        </div>
    </section>

    <!-- Contact / Booking Section -->
    <section id="contact" class="contact">
        <h2>Ready to Create Something Special?</h2>
        <p>Book a free consultation to discuss your dream piece. We would love to hear your ideas.</p>
        <a href="your-square-booking-url" class="btn btn-primary" target="_blank" rel="noopener">Book a Consultation</a>
        <div class="contact-info">
            <p>Or email us directly: <a href="mailto:your-email@example.com">your-email@example.com</a></p>
        </div>
    </section>

    <!-- Footer -->
    <footer class="footer">
        <p>&copy; 2026 Elegant Jewels. All rights reserved.</p>
    </footer>

</body>
</html>

What does this code do?

The "How It Works" section walks customers through your three-step process: browse, book, receive. This builds trust by setting clear expectations.

The contact section includes a "Book a Consultation" button that will link to your Square Appointments page. The target="_blank" attribute opens the booking page in a new tab so customers do not leave your site.

The closing </body> and </html> tags tell the browser your page is complete.

  • Save index.html by pressing Ctrl+S.
  • Open File Explorer and navigate to your jewelry-landing-page folder on your Desktop.
  • Right-click on index.html, select Open with, then choose Google Chrome (or your preferred browser).
  • You should see all your text content on the page, but it will look plain and unstyled. Headings, product names, prices, and button text are all visible as basic black text on a white background.

Seeing a blank page or garbled text?

If the page is completely blank, check that you have the closing </body> and </html> tags at the very end of your file.

If text looks broken or you see raw HTML tags displayed on the page, look for a missing closing angle bracket > or a missing closing tag like </div> or </section>. Compare your code carefully against the full file in the double-check tab below.

Help me debug why my HTML page is not displaying correctly.

✔️ Awesome, I've got everything!

Great. Double-check you have saved your file before moving on.

ⓧ I'd like to double check the full code

Here is the complete index.html file. Compare yours against it:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Elegant Jewels - Handcrafted Fine Jewelry</title>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Inter:wght@300;400;500&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="style.css">
</head>
<body>

    <!-- Hero Section -->
    <header class="hero">
        <div class="hero-overlay"></div>
        <div class="hero-content">
            <h1>Elegant Jewels</h1>
            <p class="tagline">Handcrafted fine jewelry for life's most precious moments</p>
            <a href="#catalog" class="btn btn-primary">Explore Collection</a>
        </div>
    </header>

    <!-- About Section -->
    <section id="about" class="about">
        <h2>Our Story</h2>
        <p>Every piece in our collection is thoughtfully designed and handcrafted with care. From custom engagement rings to statement necklaces, we create jewelry that tells your story. Whether you are looking for a timeless classic or a one-of-a-kind design, we are here to bring your vision to life.</p>
    </section>

    <!-- Catalog Section -->
    <section id="catalog" class="catalog">
        <h2>Our Collection</h2>
        <p class="section-subtitle">Browse our pieces and enquire about any item that catches your eye</p>
        <div class="catalog-grid">

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product1.jpg" alt="Gold Statement Necklace">
                </div>
                <div class="product-info">
                    <h3>Gold Statement Necklace</h3>
                    <p class="price">From $350</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Gold%20Statement%20Necklace" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product2.jpg" alt="Diamond Engagement Ring">
                </div>
                <div class="product-info">
                    <h3>Diamond Engagement Ring</h3>
                    <p class="price">From $1,200</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Diamond%20Engagement%20Ring" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product3.jpg" alt="Pearl Drop Earrings">
                </div>
                <div class="product-info">
                    <h3>Pearl Drop Earrings</h3>
                    <p class="price">From $180</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Pearl%20Drop%20Earrings" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

            <div class="product-card">
                <div class="product-image">
                    <img src="images/product4.jpg" alt="Custom Charm Bracelet">
                </div>
                <div class="product-info">
                    <h3>Custom Charm Bracelet</h3>
                    <p class="price">From $250</p>
                    <a href="mailto:your-email@example.com?subject=Enquiry%20about%20Custom%20Charm%20Bracelet" class="btn btn-enquire">Enquire Now</a>
                </div>
            </div>

        </div>
    </section>

    <!-- How It Works Section -->
    <section id="process" class="process">
        <h2>How It Works</h2>
        <div class="steps-grid">
            <div class="step">
                <span class="step-number">1</span>
                <h3>Browse and Enquire</h3>
                <p>Explore our collection and send an enquiry about any piece that inspires you.</p>
            </div>
            <div class="step">
                <span class="step-number">2</span>
                <h3>Book a Consultation</h3>
                <p>Schedule a free consultation to discuss your vision, customization options, and details.</p>
            </div>
            <div class="step">
                <span class="step-number">3</span>
                <h3>Receive Your Piece</h3>
                <p>We handcraft your jewelry with care and deliver it beautifully packaged to you.</p>
            </div>
        </div>
    </section>

    <!-- Contact / Booking Section -->
    <section id="contact" class="contact">
        <h2>Ready to Create Something Special?</h2>
        <p>Book a free consultation to discuss your dream piece. We would love to hear your ideas.</p>
        <a href="your-square-booking-url" class="btn btn-primary" target="_blank" rel="noopener">Book a Consultation</a>
        <div class="contact-info">
            <p>Or email us directly: <a href="mailto:your-email@example.com">your-email@example.com</a></p>
        </div>
    </section>

    <!-- Footer -->
    <footer class="footer">
        <p>&copy; 2026 Elegant Jewels. All rights reserved.</p>
    </footer>

</body>
</html>
Understand the key parts of your page

Your page has five distinct sections, each serving a specific business purpose. Here is what the most important ones do for your customers.

What is the hero section?

The hero is the full-screen banner at the very top of your page. It is the first thing customers see when they load your site. A bold headline and a clear call-to-action button ("Explore Collection") immediately tell visitors what your business does and invite them to browse.

How do the Enquire Now buttons work?

Each product card has an "Enquire Now" link using a mailto: href. When a customer clicks it, their default email app opens with your email address in the "To" field and the product name pre-filled in the subject line.

This means you immediately know which piece the customer is asking about without them having to type it. No JavaScript or contact form service needed.

What about the booking section?

The "Book a Consultation" button currently points to a placeholder URL (your-square-booking-url). In a later step, you will replace this with your real Square Appointments link so customers can schedule directly from your page.

Your HTML skeleton is complete. Right now it looks plain, but all the content and structure is in place. Next up, you will bring this page to life with elegant styling using CSS.

Style Your Page with CSS

Right now your landing page shows all the right content, but it looks like a plain document from the 1990s. Customers landing on this page would not feel the luxury and elegance your jewelry deserves.

In this step, you will write a complete stylesheet that transforms that plain HTML into a polished, professional design. You will define a gold-and-cream color palette, lay out product cards in a grid, add hover animations, and make the page look great on mobile phones.

In this step, get ready to:
  • Write the complete CSS stylesheet with custom colors, typography, and layout.
  • Preview the styled page in your browser and test the responsive mobile layout.
Write the CSS styles

Your stylesheet will be built in four sections, starting with the foundation (colors and resets) and working through each page section from top to bottom.

  • Switch back to VS Code and click on style.css in the Explorer sidebar to open it.
  • Add the following code to define your color palette, reset browser defaults, and create reusable button styles:
/* === Custom Properties (Colors and Fonts) === */
:root {
    --color-gold: #B8860B;
    --color-gold-light: #D4A84B;
    --color-cream: #FFFAF0;
    --color-dark: #2C2C2C;
    --color-dark-light: #4A4A4A;
    --color-white: #FFFFFF;
    --color-border: #E8E0D4;
    --font-heading: 'Playfair Display', serif;
    --font-body: 'Inter', sans-serif;
}

/* === Reset and Base Styles === */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    font-family: var(--font-body);
    font-weight: 300;
    color: var(--color-dark);
    line-height: 1.7;
}

h1, h2, h3 {
    font-family: var(--font-heading);
    font-weight: 700;
    line-height: 1.3;
}

img {
    max-width: 100%;
    height: auto;
    display: block;
}

a {
    text-decoration: none;
    color: inherit;
}

/* === Buttons === */
.btn {
    display: inline-block;
    padding: 14px 32px;
    border-radius: 4px;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.95rem;
    letter-spacing: 0.5px;
    transition: background-color 0.3s ease, transform 0.2s ease;
    cursor: pointer;
}

.btn-primary {
    background-color: var(--color-gold);
    color: var(--color-white);
}

.btn-primary:hover {
    background-color: var(--color-gold-light);
    transform: translateY(-2px);
}

.btn-enquire {
    background-color: var(--color-dark);
    color: var(--color-white);
    padding: 10px 24px;
    font-size: 0.85rem;
}

.btn-enquire:hover {
    background-color: var(--color-gold);
    transform: translateY(-2px);
}

What does this code do?

The :root section defines CSS custom properties (variables) for your brand colors and fonts. Instead of typing #B8860B every time you want gold, you can write var(--color-gold).

The reset removes default browser spacing so every browser starts from the same baseline. The button styles create two reusable classes: .btn-primary (gold) and .btn-enquire (dark). Both lift slightly on hover thanks to transform: translateY(-2px).

  • Save style.css by pressing Ctrl+S.
  • Switch to your browser tab showing the page and refresh it.
  • You should see the font change to a clean sans-serif, all default margins disappear, and the buttons turn into styled gold or dark rectangles.

Page still looks the same?

  • Make sure you saved style.css (look for the dot on the file tab in VS Code that disappears after saving).
  • Confirm that your index.html has <link rel="stylesheet" href="style.css"> in the <head> section. Without this link, the browser does not know the stylesheet exists.
  • Check that both files are in the same folder. If style.css is inside a subfolder, the link path will not match.

Help me figure out why my CSS is not loading.

  • Next, add the hero and about section styles below your existing code in style.css:
/* === Hero Section === */
.hero {
    position: relative;
    min-height: 90vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    background-color: var(--color-dark);
    overflow: hidden;
}

.hero-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
    opacity: 0.9;
}

.hero-content {
    position: relative;
    z-index: 1;
    padding: 2rem;
}

.hero h1 {
    font-size: 3.5rem;
    color: var(--color-gold-light);
    margin-bottom: 1rem;
    letter-spacing: 2px;
}

.hero .tagline {
    font-size: 1.2rem;
    color: var(--color-cream);
    margin-bottom: 2.5rem;
    font-weight: 300;
    max-width: 500px;
    margin-left: auto;
    margin-right: auto;
}

/* === About Section === */
.about {
    padding: 5rem 2rem;
    text-align: center;
    max-width: 700px;
    margin: 0 auto;
}

.about h2 {
    font-size: 2rem;
    color: var(--color-dark);
    margin-bottom: 1.5rem;
}

.about p {
    font-size: 1.05rem;
    color: var(--color-dark-light);
}

What does this code do?

The hero section uses flexbox to perfectly center the heading and button both vertically and horizontally. It fills 90% of the screen height (min-height: 90vh) so the first thing customers see is a bold, full-screen introduction.

The overlay uses a dark gradient layered behind the text with z-index: 1 on the content to make sure the gold heading always sits on top. The about section is capped at 700px wide so paragraph text stays easy to read.

  • Save style.css and refresh your browser.
  • The hero section now fills most of the viewport with a dark blue gradient, a large gold heading, and a gold button. The about section below it has centered, readable text.

Hero section looks broken or text is invisible?

  • If the heading text is hidden behind the gradient, check that .hero-content has position: relative and z-index: 1. Without these, the overlay covers everything.
  • If the hero is not tall, make sure you typed min-height: 90vh (not 90px). vh means viewport height.

Help me fix my hero section styling.

  • Add the catalog section styles below your about styles in style.css:
/* === Catalog Section === */
.catalog {
    padding: 5rem 2rem;
    background-color: var(--color-cream);
    text-align: center;
}

.catalog h2 {
    font-size: 2rem;
    margin-bottom: 0.5rem;
}

.section-subtitle {
    color: var(--color-dark-light);
    margin-bottom: 3rem;
    font-size: 1rem;
}

.catalog-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 2rem;
    max-width: 1100px;
    margin: 0 auto;
}

.product-card {
    background-color: var(--color-white);
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--color-border);
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.product-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
}

.product-image {
    width: 100%;
    height: 280px;
    overflow: hidden;
    background-color: #f0ebe3;
}

.product-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.product-info {
    padding: 1.5rem;
    text-align: center;
}

.product-info h3 {
    font-size: 1.15rem;
    margin-bottom: 0.5rem;
}

.product-info .price {
    color: var(--color-gold);
    font-weight: 500;
    margin-bottom: 1rem;
    font-size: 0.95rem;
}

What does this code do?

The .catalog-grid uses CSS Grid with auto-fit and minmax(260px, 1fr) to automatically arrange product cards. The grid fits as many 260px-wide cards as possible per row, expanding them to fill available space.

Each .product-card has a hover effect that lifts the card upward and adds a soft shadow. The object-fit: cover on images ensures your jewelry photos fill the card without stretching or distorting.

  • Save style.css and refresh your browser.
  • The catalog section now shows your product cards in a neat grid with a cream background. Move your mouse over a card to see it lift with a shadow effect.

Cards stacked in a single column?

  • Make sure your browser window is wide enough (at least 600px). The grid needs space for two columns of 260px-wide cards.
  • Check that you typed display: grid on .catalog-grid (not .catalog). The grid property must be on the container that directly wraps the cards.

Help me fix my product card grid layout.

  • Add the remaining section styles (how it works, contact, footer, and responsive rules) below your catalog styles in style.css:
/* === How It Works Section === */
.process {
    padding: 5rem 2rem;
    text-align: center;
}

.process h2 {
    font-size: 2rem;
    margin-bottom: 3rem;
}

.steps-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 2.5rem;
    max-width: 900px;
    margin: 0 auto;
}

.step {
    padding: 1.5rem;
}

.step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background-color: var(--color-gold);
    color: var(--color-white);
    font-family: var(--font-heading);
    font-size: 1.2rem;
    font-weight: 700;
    margin-bottom: 1rem;
}

.step h3 {
    font-size: 1.1rem;
    margin-bottom: 0.75rem;
}

.step p {
    color: var(--color-dark-light);
    font-size: 0.95rem;
}

/* === Contact / Booking Section === */
.contact {
    padding: 5rem 2rem;
    text-align: center;
    background-color: var(--color-dark);
    color: var(--color-cream);
}

.contact h2 {
    font-size: 2rem;
    color: var(--color-gold-light);
    margin-bottom: 1rem;
}

.contact p {
    font-size: 1.05rem;
    margin-bottom: 2rem;
    max-width: 500px;
    margin-left: auto;
    margin-right: auto;
}

.contact-info {
    margin-top: 2rem;
}

.contact-info a {
    color: var(--color-gold-light);
    border-bottom: 1px solid var(--color-gold-light);
}

.contact-info a:hover {
    color: var(--color-white);
    border-color: var(--color-white);
}

/* === Footer === */
.footer {
    padding: 2rem;
    text-align: center;
    background-color: #1a1a1a;
    color: #999;
    font-size: 0.85rem;
}

/* === Responsive Design (Mobile) === */
@media (max-width: 768px) {
    .hero h1 {
        font-size: 2.2rem;
    }

    .hero .tagline {
        font-size: 1rem;
    }

    .catalog-grid {
        grid-template-columns: 1fr;
        max-width: 400px;
    }

    .steps-grid {
        grid-template-columns: 1fr;
    }

    .about,
    .catalog,
    .process,
    .contact {
        padding: 3.5rem 1.5rem;
    }
}

What does this code do?

The .step-number creates gold circles (48px round) for the numbered steps. The contact section uses a dark background with light text to create contrast and draw attention to the booking button.

The @media block at the bottom is a responsive design rule. When the browser window is narrower than 768px (like a phone screen), it shrinks the heading, switches the grid to a single column, and reduces padding so everything fits comfortably.

  • Save style.css and refresh your browser.
  • Scroll down to see the "How It Works" section with gold numbered circles, the dark contact section with a gold heading, and the footer at the bottom.

Responsive styles not working?

  • Make sure the @media block is at the very bottom of your file. CSS reads top to bottom, and media queries must come after the styles they override.
  • Check that your index.html has the viewport meta tag: <meta name="viewport" content="width=device-width, initial-scale=1.0">. Without it, mobile browsers ignore media queries.

Help me debug my responsive CSS.

✔️ Awesome, I've got everything!

Great. Make sure you have saved style.css before moving on.

ⓧ I'd like to double check the full code

Here is the complete style.css file. Compare yours against it to catch any differences:

/* === Custom Properties (Colors and Fonts) === */
:root {
    --color-gold: #B8860B;
    --color-gold-light: #D4A84B;
    --color-cream: #FFFAF0;
    --color-dark: #2C2C2C;
    --color-dark-light: #4A4A4A;
    --color-white: #FFFFFF;
    --color-border: #E8E0D4;
    --font-heading: 'Playfair Display', serif;
    --font-body: 'Inter', sans-serif;
}

/* === Reset and Base Styles === */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    font-family: var(--font-body);
    font-weight: 300;
    color: var(--color-dark);
    line-height: 1.7;
}

h1, h2, h3 {
    font-family: var(--font-heading);
    font-weight: 700;
    line-height: 1.3;
}

img {
    max-width: 100%;
    height: auto;
    display: block;
}

a {
    text-decoration: none;
    color: inherit;
}

/* === Buttons === */
.btn {
    display: inline-block;
    padding: 14px 32px;
    border-radius: 4px;
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 0.95rem;
    letter-spacing: 0.5px;
    transition: background-color 0.3s ease, transform 0.2s ease;
    cursor: pointer;
}

.btn-primary {
    background-color: var(--color-gold);
    color: var(--color-white);
}

.btn-primary:hover {
    background-color: var(--color-gold-light);
    transform: translateY(-2px);
}

.btn-enquire {
    background-color: var(--color-dark);
    color: var(--color-white);
    padding: 10px 24px;
    font-size: 0.85rem;
}

.btn-enquire:hover {
    background-color: var(--color-gold);
    transform: translateY(-2px);
}

/* === Hero Section === */
.hero {
    position: relative;
    min-height: 90vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    background-color: var(--color-dark);
    overflow: hidden;
}

.hero-overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
    opacity: 0.9;
}

.hero-content {
    position: relative;
    z-index: 1;
    padding: 2rem;
}

.hero h1 {
    font-size: 3.5rem;
    color: var(--color-gold-light);
    margin-bottom: 1rem;
    letter-spacing: 2px;
}

.hero .tagline {
    font-size: 1.2rem;
    color: var(--color-cream);
    margin-bottom: 2.5rem;
    font-weight: 300;
    max-width: 500px;
    margin-left: auto;
    margin-right: auto;
}

/* === About Section === */
.about {
    padding: 5rem 2rem;
    text-align: center;
    max-width: 700px;
    margin: 0 auto;
}

.about h2 {
    font-size: 2rem;
    color: var(--color-dark);
    margin-bottom: 1.5rem;
}

.about p {
    font-size: 1.05rem;
    color: var(--color-dark-light);
}

/* === Catalog Section === */
.catalog {
    padding: 5rem 2rem;
    background-color: var(--color-cream);
    text-align: center;
}

.catalog h2 {
    font-size: 2rem;
    margin-bottom: 0.5rem;
}

.section-subtitle {
    color: var(--color-dark-light);
    margin-bottom: 3rem;
    font-size: 1rem;
}

.catalog-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 2rem;
    max-width: 1100px;
    margin: 0 auto;
}

.product-card {
    background-color: var(--color-white);
    border-radius: 8px;
    overflow: hidden;
    border: 1px solid var(--color-border);
    transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.product-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.08);
}

.product-image {
    width: 100%;
    height: 280px;
    overflow: hidden;
    background-color: #f0ebe3;
}

.product-image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.product-info {
    padding: 1.5rem;
    text-align: center;
}

.product-info h3 {
    font-size: 1.15rem;
    margin-bottom: 0.5rem;
}

.product-info .price {
    color: var(--color-gold);
    font-weight: 500;
    margin-bottom: 1rem;
    font-size: 0.95rem;
}

/* === How It Works Section === */
.process {
    padding: 5rem 2rem;
    text-align: center;
}

.process h2 {
    font-size: 2rem;
    margin-bottom: 3rem;
}

.steps-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 2.5rem;
    max-width: 900px;
    margin: 0 auto;
}

.step {
    padding: 1.5rem;
}

.step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background-color: var(--color-gold);
    color: var(--color-white);
    font-family: var(--font-heading);
    font-size: 1.2rem;
    font-weight: 700;
    margin-bottom: 1rem;
}

.step h3 {
    font-size: 1.1rem;
    margin-bottom: 0.75rem;
}

.step p {
    color: var(--color-dark-light);
    font-size: 0.95rem;
}

/* === Contact / Booking Section === */
.contact {
    padding: 5rem 2rem;
    text-align: center;
    background-color: var(--color-dark);
    color: var(--color-cream);
}

.contact h2 {
    font-size: 2rem;
    color: var(--color-gold-light);
    margin-bottom: 1rem;
}

.contact p {
    font-size: 1.05rem;
    margin-bottom: 2rem;
    max-width: 500px;
    margin-left: auto;
    margin-right: auto;
}

.contact-info {
    margin-top: 2rem;
}

.contact-info a {
    color: var(--color-gold-light);
    border-bottom: 1px solid var(--color-gold-light);
}

.contact-info a:hover {
    color: var(--color-white);
    border-color: var(--color-white);
}

/* === Footer === */
.footer {
    padding: 2rem;
    text-align: center;
    background-color: #1a1a1a;
    color: #999;
    font-size: 0.85rem;
}

/* === Responsive Design (Mobile) === */
@media (max-width: 768px) {
    .hero h1 {
        font-size: 2.2rem;
    }

    .hero .tagline {
        font-size: 1rem;
    }

    .catalog-grid {
        grid-template-columns: 1fr;
        max-width: 400px;
    }

    .steps-grid {
        grid-template-columns: 1fr;
    }

    .about,
    .catalog,
    .process,
    .contact {
        padding: 3.5rem 1.5rem;
    }
}
Preview your styled page

With the full stylesheet in place, it is time to do a thorough visual check of your entire page.

  • Make sure both index.html and style.css are saved (press Ctrl+S in each tab).
  • Switch to your browser and refresh the page.
  • Scroll from top to bottom. You should see the full-screen hero with gold text, the about section, a cream-background catalog grid with product cards, the numbered how-it-works steps, the dark contact section, and the footer.
  • Hover your mouse over a product card. It should lift upward slightly and gain a soft shadow.
  • Try resizing your browser window narrower (drag the edge inward) to see the mobile-responsive layout. The product grid should collapse to a single column.

What is responsive design?

Responsive design means your page automatically adjusts its layout depending on the screen size. The @media (max-width: 768px) rule you added tells the browser: "when the window is smaller than 768 pixels wide, use these alternative styles instead."

This ensures customers browsing on their phones see a single-column layout with readable text, rather than a squished desktop layout.

Your landing page now looks polished and professional. Next up, you will connect your real Square Appointments booking link and swap in your actual business details so the page is ready for real customers.

Connect Your Square Appointments Booking

Your landing page looks polished and professional. However, the buttons still point to placeholder values that do not actually connect to your business.

In this step, you will grab your real booking URL from Square Appointments and swap in your actual business details. After this, every button on your page will do something real.

In this step, get ready to:
  • Copy your Square Appointments booking URL from the Square Dashboard.
  • Replace all placeholder values in your HTML with real business details.
  • Verify that booking and enquiry buttons work correctly.
Get your Square Appointments booking URL

Square provides a direct URL to your online booking page. Customers who click this link land straight on your scheduling page where they can pick a time slot.

  • Open your web browser and go to https://squareup.com/dashboard.
  • Sign in with your Square account credentials.
  • Click Appointments in the left sidebar (or Payments > Appointments).
  • Click Online Booking.
  • Click Channels.
  • Under "Add your booking flow to an existing site", click Get Started.
  • Click Get URL.
  • Copy the booking URL that appears. Keep this in your clipboard for the next substep.

What is this booking URL?

This URL is a direct link to your Square Appointments scheduling page. When a customer clicks it, they see your available time slots and can book a consultation without needing to call or email you first.

Don't see the Online Booking option?

You need to have online booking enabled and a booking site published before the Channels option appears. Check that you have completed your Square Appointments setup and published your online booking site first.

Help me find my Square Appointments booking URL

Update your landing page with real details

Now you will swap the placeholder text in your HTML with your real business information. This turns your template into a working landing page that connects to your actual booking system and email.

  • Switch back to VS Code and open index.html.
  • Press Ctrl+H to open the Find and Replace tool.
  • In the top field (Find), type your-square-booking-url.
  • In the bottom field (Replace), paste the Square Appointments booking URL you just copied.
  • Click the replace icon (or press Ctrl+Shift+1) to replace the match.

After the replacement, your booking link in the contact section should look like this:

<a href="[[SQUARE_BOOKING_URL="your Square Appointments booking URL"]]" class="btn btn-primary" target="_blank" rel="noopener">Book a Consultation</a>

What does target="_blank" do?

The target="_blank" attribute tells the browser to open the booking page in a new tab. This keeps your landing page open so customers can return to it easily after scheduling.

Next, replace the placeholder email address with your real business email.

  • In the Find field, clear the previous text and type your-email@example.com.
  • In the Replace field, type your actual business email address.
  • Click the "Replace All" icon (the double-document icon) to replace every occurrence at once.

Why replace all at once?

Your email address appears six times in the file. Once in the contact section and once inside each of the four product card "Enquire Now" links. Replace All swaps them all in one click so you do not miss any.

Finally, personalise the content to match your business.

  • Replace the business name ("Elegant Jewels") and tagline with your own business name and tagline if you wish.
  • Update each product card's name, price, and alt text to match your real jewelry pieces.
  • If your product photos have different file names than product1.jpg through product4.jpg, update the src attributes in each <img> tag to match your actual file names.
  • Save the file by pressing Ctrl+S.

Keep the mailto subject lines updated

If you rename a product, also update the matching ?subject=Enquiry%20about%20 portion in that card's mailto: link. Spaces in the subject are encoded as %20.

  • Switch to your browser tab showing the landing page and refresh the page.
  • Click the Book a Consultation button at the bottom of the page. Your Square Appointments booking page should open in a new tab.
  • Go back to your landing page and click any Enquire Now button on a product card. Your email app should open with your business email in the To field and the product name in the subject line.

Booking link not opening?

Make sure you replaced the exact text your-square-booking-url and that your pasted URL starts with https://. If the URL is missing the protocol, the browser treats it as a relative path on your own site.

Also check that you did not accidentally delete the surrounding quotation marks in the href="..." attribute.

Help me fix my booking link in index.html

Your landing page is now fully functional. Every button connects to a real action. Next up, you will deploy this page live on the internet so customers can actually visit it.

Deploy Your Page Live with Netlify

Your landing page is looking polished and working perfectly on your local machine. The booking button opens your Square Appointments page, and the enquiry buttons launch pre-filled emails.

There is one problem: only you can see it. To turn this into a real business tool, you need to put it on the internet where customers can visit. In this step, you will deploy your page live using Netlify, a free hosting service that makes this incredibly simple.

In this step, get ready to:
  • Create a free Netlify account.
  • Deploy your landing page live to the internet.
  • Verify your site is publicly accessible.
Create a Netlify account

Netlify offers a free hosting plan that keeps your site live indefinitely. You do not need a credit card or any technical setup to get started.

  • Open your browser and go to https://app.netlify.com/login.
  • Click Sign up to create a new account using your email address.
  • Fill in your email and choose a password.
  • Check your email inbox for a confirmation message from Netlify and click the verification link if prompted.

Why Netlify?

Netlify's free plan includes 300 credits, a global CDN, and custom domain support with SSL. Your site stays live for free as long as you want it.

Unlike other hosting options, Netlify Drop requires no Git knowledge and no command line. You just drag and drop your folder.

Not receiving the confirmation email?

Check your spam or junk folder. The email comes from Netlify and may take a minute to arrive.

If you still cannot find it, try signing up with a different email address.

Help me sign up for Netlify.

Deploy your site with Netlify Drop

Netlify Drop lets you deploy a website by dragging your project folder directly into the browser. No terminal commands needed.

  • In your browser, go to https://app.netlify.com/drop.
  • Open File Explorer by pressing the Windows key and typing File Explorer.
  • Navigate to your Desktop and find the jewelry-landing-page folder.
  • Drag and drop the entire jewelry-landing-page folder onto the Netlify Drop zone in your browser.
  • Wait for the upload to complete. This usually takes less than 30 seconds.

What does Netlify need from your folder?

Netlify looks for an index.html file at the root level of the folder you drop. Since your jewelry-landing-page folder has index.html right at the top level (alongside style.css and your images/ folder), everything will deploy correctly.

Once the upload finishes, Netlify gives you a live URL ending in .netlify.app.

  • Click the URL that Netlify shows you to open your live site in a new tab.
  • Verify that your hero section, product catalog, and booking button all appear correctly.
  • Click Book a Consultation to confirm it still opens your Square Appointments page.
  • Try clicking an Enquire Now button to confirm the email link works.
  • Share the URL with a friend or open it on your phone to confirm anyone can access it.

Images not showing on the live site?

Make sure you dragged the entire jewelry-landing-page folder (not just the individual files). The images/ subfolder needs to be included in the upload.

Also check that the file names in your index.html match your actual image file names exactly. File names are case-sensitive on web servers.

Help me fix images not loading on my Netlify site.

Secret mission

Add a Sticky Navigation Bar

Your landing page looks great, but customers have to scroll all the way back up to navigate between sections. Add a professional sticky navigation bar that stays visible as visitors scroll, with smooth-scrolling links that jump to each section instantly.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely on Netlify's free plan with no ongoing costs. Your site stays live indefinitely without charging you anything.

Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • A Netlify site (hosted for free on the Free plan with 300 credits included).
  • Your jewelry-landing-page folder on your Desktop (local files).

Keep everything running

No action needed. Choose this if you are still actively building or want your jewelry landing page to remain live for customers.

  • Your Netlify site stays live indefinitely on the free plan at no cost.
  • Your local files remain in the jewelry-landing-page folder on your Desktop.
  • To update your site later, make changes to your files locally and drag the folder to Netlify Drop again.

Pause - I'll come back to this later

Take your site offline while keeping all your configuration saved. You can re-enable it at any time.

  • In your Netlify dashboard, click on your site name to open it.
  • Go to Project configuration in the left sidebar.
  • Click General, then scroll down to Danger zone.
  • Click Disable project to take the site offline.
  • Your local files remain safely in the jewelry-landing-page folder on your Desktop.
  • When you are ready to bring the site back, return to the same Danger zone section and click Enable project.

Delete - I don't want to use this again

Remove all project resources and start fresh. This permanently deletes your Netlify site and local files.

  • In your Netlify dashboard, click on your site name to open it.
  • Go to Project configuration in the left sidebar.
  • Scroll down to the Danger zone section.
  • Follow the guided steps to delete your site permanently.
  • Delete your local project folder by opening File Explorer, navigating to your Desktop, right-clicking the jewelry-landing-page folder, and selecting Delete.

Nice Work!

Nice Work!

You just built and deployed a professional jewelry business landing page from scratch using pure HTML and CSS. Your customers can now browse your collection, enquire about pieces, and book consultations directly from a live public URL.

What you learned:

  • Built a complete landing page from scratch using HTML and CSS, including a hero section, product catalog grid, and responsive mobile layout.
  • Created a product catalog with individual enquiry buttons that open the customer's email app with a pre-filled subject line for each jewelry piece.
  • Connected your Square Appointments booking system so clients can schedule consultations directly from your page.
  • Deployed a live website to the internet for free using Netlify Drop, giving you a public URL to share with customers.
  • Secret Mission: Added a sticky navigation bar with smooth scrolling so customers can jump between sections easily.

Ready to quiz yourself?