LearnAI ToolsCareerPractice BuildsPlayContact
BootstrapIntermediate~2 hours

Marketing Landing Page

Assemble a full responsive landing page using the navbar, carousel, and cards.

NavbarCarouselResponsive Design

Overview

A marketing landing page is the project that finally strings several Bootstrap components together into one real page instead of practicing them in isolation. A real landing page needs a navbar that collapses cleanly on mobile, a hero that makes the pitch in one glance, a carousel or gallery that shows the product in action, a grid of feature cards, and a footer — and all five have to actually work together as one responsive whole, not just individually.

In this tutorial you will build a landing page for a fictional product called Northwind Studio: a collapsing navbar with jump links, a bold hero section, a three-slide image carousel with indicators and prev/next controls, a three-card features grid, and a closing footer, all using nothing but Bootstrap's own classes and components.

What You'll Build
  • A `navbar-expand-lg` navbar that collapses into a hamburger toggler below the `lg` breakpoint.
  • A full-width hero section with a headline, supporting copy, and a call-to-action button.
  • A Bootstrap `carousel` with indicators, captions, and prev/next controls, auto-advancing on page load.
  • A responsive `row-cols-*` grid of feature cards.
  • A closing footer whose two halves stack on mobile and sit side by side on desktop.

Prerequisites

  • The `navbar` component and how `navbar-expand-*` controls the breakpoint it collapses at.
  • Bootstrap's grid system and `row-cols-*` (used earlier for the Admin Dashboard project).
  • The `card` component at a basic level.
  • How Bootstrap's JS components read `data-bs-*` attributes to know what to toggle or control, without you writing click handlers.

Project Structure

Everything lives in one file, `landing.html`, with five sections stacked top to bottom in `<body>`: a `navbar`, a hero `<header>`, a `carousel`, a features `<section>`, and a `<footer>`. The navbar's links use fragment `href`s (`#hero`, `#features`) that target `id` attributes on the sections below them, exactly like the jump-link pattern from earlier HTML/CSS projects — Bootstrap doesn't change how fragment links work, it only restyles the nav they live inside.

The carousel gets its own top-level `id` (`heroCarousel`) that every one of its indicator buttons and prev/next controls references through `data-bs-target`. That single id is what ties an otherwise unrelated set of buttons to one specific carousel instance — important once a page has more than one carousel on it, though this project only builds one.

Step 1: Set Up the Page and Load Bootstrap

Start with the standard boilerplate and load Bootstrap's CSS and JS bundle. Nothing here differs from the earlier two projects — this exact `<link>`/`<script>` pairing is what every Bootstrap page in this course starts from.

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Northwind Studio - Ship Better Products, Faster</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!-- Navbar, hero, carousel, features, and footer are added in the steps that follow -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Step 2: Build the Responsive Navbar

`navbar-expand-lg` keeps the nav links horizontal from the `lg` breakpoint up and collapses them into a hamburger below it. The toggler button carries `data-bs-toggle="collapse"` and `data-bs-target="#navMenu"`; Bootstrap's JS reads those two attributes and shows or hides whichever element has that matching `id`, so no click handler needs to be written.

<!-- sticky-top keeps the navbar pinned to the top of the viewport while scrolling -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="container">
<a class="navbar-brand" href="#">Northwind Studio</a>
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse" data-bs-target="#navMenu"
aria-controls="navMenu" aria-expanded="false" aria-label="Toggle navigation">
<!-- data-bs-toggle/data-bs-target: read by Bootstrap's JS bundle to know
which element (#navMenu, below) to show or hide when this is clicked -->
<span class="navbar-toggler-icon"></span>
</button>
<!-- collapse: hidden below lg until the toggler above opens it -->
<div class="collapse navbar-collapse" id="navMenu">
<ul class="navbar-nav ms-auto"> <!-- ms-auto pushes the links to the right on wide screens -->
<li class="nav-item"><a class="nav-link active" aria-current="page" href="#hero">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#features">Features</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
</ul>
</div>
</div>
</nav>

Step 3: Build the Hero Section

`display-4` is one of Bootstrap's large display headings, sized specifically for hero-style copy rather than a regular `<h1>`. The lead paragraph is constrained with `col-lg-8 mx-auto` so its lines stay a readable width and stay centered, instead of stretching edge to edge on a wide screen the way an unconstrained paragraph would.

<!-- id="hero" is the target of the navbar's "Home" link -->
<header id="hero" class="bg-primary text-white text-center py-5">
<div class="container py-5">
<h1 class="display-4 fw-bold">Ship Better Products, Faster</h1>
<!-- col-lg-8 mx-auto: constrains and centers the paragraph so lines don't
stretch full width on large screens -->
<p class="lead col-lg-8 mx-auto">
Northwind Studio helps teams plan, design, and launch products without
the usual six months of meetings.
</p>
<a href="#features" class="btn btn-light btn-lg mt-3">See What's Included</a>
</div>
</header>

Step 4: Build the Carousel

`data-bs-ride="carousel"` auto-starts the slideshow the moment the page loads, with no extra JavaScript. Exactly one `carousel-item` must carry the `active` class — that is what the carousel shows first, and only one indicator button matches it with its own `active` class. `carousel-caption` uses `d-none d-md-block` so captions are hidden on small screens, where they would otherwise overlap the image awkwardly.

<!-- data-bs-ride="carousel" auto-starts the slideshow on page load -->
<div id="heroCarousel" class="carousel slide" data-bs-ride="carousel">
<!-- Indicators: one dot per slide; data-bs-slide-to picks which slide it jumps to -->
<div class="carousel-indicators">
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<!-- Exactly one slide needs "active" - it's what the carousel shows first -->
<div class="carousel-item active">
<img src="https://placehold.co/1200x480?text=Plan" class="d-block w-100" alt="Screenshot of the planning dashboard">
<!-- d-none d-md-block: captions hidden on small screens where they'd overlap the image -->
<div class="carousel-caption d-none d-md-block">
<h5>Plan</h5>
<p>Map out your roadmap in minutes, not sprints.</p>
</div>
</div>
<div class="carousel-item">
<img src="https://placehold.co/1200x480?text=Design" class="d-block w-100" alt="Screenshot of the design workspace">
<div class="carousel-caption d-none d-md-block">
<h5>Design</h5>
<p>Prototype directly alongside your team, no handoff needed.</p>
</div>
</div>
<div class="carousel-item">
<img src="https://placehold.co/1200x480?text=Launch" class="d-block w-100" alt="Screenshot of the launch checklist">
<div class="carousel-caption d-none d-md-block">
<h5>Launch</h5>
<p>Ship with a checklist that actually catches problems early.</p>
</div>
</div>
</div>
<!-- data-bs-slide="prev"/"next" tells Bootstrap's JS which direction to
advance, independent of the indicator buttons above -->
<button class="carousel-control-prev" type="button" data-bs-target="#heroCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#heroCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>

Step 5: Build the Features Section

The features grid reuses the same `row-cols-1 row-cols-md-3 g-4` pattern from the Admin Dashboard project — one card per row on phones, three across from `md` up. `border-0 shadow-sm` replaces the card's default hard border with a soft drop shadow, a common look for feature cards on a marketing page, where a heavier border tends to look too utilitarian.

<!-- id="features" is the target of both the navbar's "Features" link and the hero's CTA button -->
<section id="features" class="py-5">
<div class="container">
<h2 class="text-center mb-5">Everything Your Team Needs</h2>
<div class="row row-cols-1 row-cols-md-3 g-4">
<div class="col">
<div class="card h-100 border-0 shadow-sm"> <!-- border-0 shadow-sm: soft shadow instead of a hard border -->
<div class="card-body text-center">
<h3 class="h5 card-title">Roadmapping</h3>
<p class="card-text">Visual timelines that update themselves as work moves.</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h3 class="h5 card-title">Live Collaboration</h3>
<p class="card-text">Comment, sketch, and review without leaving the page.</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h3 class="h5 card-title">One-Click Launch</h3>
<p class="card-text">Push a release checklist straight to your whole team.</p>
</div>
</div>
</div>
</div>
</div>
</section>

Step 6: Build the Footer

The footer's two halves — the copyright line and the link list — use `flex-column flex-md-row` so they stack on mobile and sit side by side from `md` up, without a custom media query. Giving the footer its own `id="contact"` lets the navbar's "Contact" link jump straight to it, the same fragment-link pattern used everywhere else on this page.

<!-- id="contact" is the target of the navbar's "Contact" link -->
<footer id="contact" class="bg-dark text-white-50 py-4">
<!-- flex-column on mobile stacks the two halves; flex-md-row lays them side
by side from md up, without a custom media query -->
<div class="container d-flex flex-column flex-md-row justify-content-between align-items-center">
<p class="mb-0">&copy; 2026 Northwind Studio. All rights reserved.</p>
<ul class="nav">
<li class="nav-item"><a href="#" class="nav-link px-2 text-white-50">Privacy</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-white-50">Terms</a></li>
</ul>
</div>
</footer>

Complete Code

Here is the complete landing page with the navbar, hero, carousel, features section, and footer assembled in order.

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Northwind Studio - Ship Better Products, Faster</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="container">
<a class="navbar-brand" href="#">Northwind Studio</a>
<button class="navbar-toggler" type="button"
data-bs-toggle="collapse" data-bs-target="#navMenu"
aria-controls="navMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navMenu">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link active" aria-current="page" href="#hero">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#features">Features</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
</ul>
</div>
</div>
</nav>
<header id="hero" class="bg-primary text-white text-center py-5">
<div class="container py-5">
<h1 class="display-4 fw-bold">Ship Better Products, Faster</h1>
<p class="lead col-lg-8 mx-auto">
Northwind Studio helps teams plan, design, and launch products without
the usual six months of meetings.
</p>
<a href="#features" class="btn btn-light btn-lg mt-3">See What's Included</a>
</div>
</header>
<div id="heroCarousel" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-indicators">
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="0" class="active" aria-current="true" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-bs-target="#heroCarousel" data-bs-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active">
<img src="https://placehold.co/1200x480?text=Plan" class="d-block w-100" alt="Screenshot of the planning dashboard">
<div class="carousel-caption d-none d-md-block">
<h5>Plan</h5>
<p>Map out your roadmap in minutes, not sprints.</p>
</div>
</div>
<div class="carousel-item">
<img src="https://placehold.co/1200x480?text=Design" class="d-block w-100" alt="Screenshot of the design workspace">
<div class="carousel-caption d-none d-md-block">
<h5>Design</h5>
<p>Prototype directly alongside your team, no handoff needed.</p>
</div>
</div>
<div class="carousel-item">
<img src="https://placehold.co/1200x480?text=Launch" class="d-block w-100" alt="Screenshot of the launch checklist">
<div class="carousel-caption d-none d-md-block">
<h5>Launch</h5>
<p>Ship with a checklist that actually catches problems early.</p>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#heroCarousel" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#heroCarousel" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
<section id="features" class="py-5">
<div class="container">
<h2 class="text-center mb-5">Everything Your Team Needs</h2>
<div class="row row-cols-1 row-cols-md-3 g-4">
<div class="col">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h3 class="h5 card-title">Roadmapping</h3>
<p class="card-text">Visual timelines that update themselves as work moves.</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h3 class="h5 card-title">Live Collaboration</h3>
<p class="card-text">Comment, sketch, and review without leaving the page.</p>
</div>
</div>
</div>
<div class="col">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<h3 class="h5 card-title">One-Click Launch</h3>
<p class="card-text">Push a release checklist straight to your whole team.</p>
</div>
</div>
</div>
</div>
</div>
</section>
<footer id="contact" class="bg-dark text-white-50 py-4">
<div class="container d-flex flex-column flex-md-row justify-content-between align-items-center">
<p class="mb-0">&copy; 2026 Northwind Studio. All rights reserved.</p>
<ul class="nav">
<li class="nav-item"><a href="#" class="nav-link px-2 text-white-50">Privacy</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-white-50">Terms</a></li>
</ul>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Live Preview

Sample Run

What Happens

Click Run to see what this code prints.

Extend This Project

  • Add a pricing section with three tiered `card`s, one of them visually emphasized as "Most Popular" using a colored `border` and a `badge`.
  • Add a "Book a Demo" `modal`, triggered by a button in the navbar, so a call-to-action is available without leaving the page.
  • Add `scroll-behavior: smooth` in a small `<style>` block so the fragment-link jumps from Step 2/3/6 animate instead of snapping instantly.
  • Swap the carousel's static images for short customer testimonials, reusing the same carousel markup with text instead of `<img>` tags.
  • Add a few lines of vanilla JavaScript that shrink the navbar's padding once the page has scrolled past the hero, a common "sticky navbar" polish detail on real marketing sites.

Summary

You assembled a complete marketing landing page out of five Bootstrap components working together: a collapsing navbar for navigation, a hero for the headline pitch, a carousel for showing the product in motion, a card grid for features, and a footer to close the page out — all connected by the same fragment-link and `data-bs-target` patterns used throughout Bootstrap's component library. Once you can compose components like this instead of treating each one as a standalone demo, you can build essentially any marketing page Bootstrap is capable of.