Project: Build a SaaS Product Landing Page using CSS Grid
Step-by-step project guide. Learn how to build a responsive SaaS product landing page using HTML5 and CSS Grid.
Introduction
In our first capstone project, we used Flexbox to build a personal portfolio. Flexbox is excellent for lining up items in a single row or column. However, when you need to align complex elements (like a multi-column pricing layout or a structured features matrix) along both rows and columns simultaneously, you need a two-dimensional layout engine.
In this project, you will build a SaaS Product Landing Page using CSS Grid. We will use grid-template-areas to skeleton the page, design a responsive pricing table, and create a features grid that wraps smoothly, making it a great addition to your frontend placement portfolio.
What You Will Learn
- Structuring a multi-section product landing page.
- Layout mapping using
grid-template-areas. - Designing a responsive 3-column pricing grid.
- Creating a features grid using
repeat(auto-fit, minmax(...)). - Applying styling accents like gradients and glassmorphism.
Prerequisites
- Responsive Grid: Repeat, Minmax, Auto-Fit, and Auto-Fill
- CSS Grid Areas: Area Templates and Positioning Items
Step 1: The HTML5 Markup Structure
Create a saas.html file with sections for the navbar, hero banner, feature blocks, pricing tables, and footer:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SaaS Product Landing Page</title>
<link rel="stylesheet" href="saas.css">
</head>
<body>
<!-- Main Skeleton Container -->
<div class="layout-wrapper">
<!-- Header -->
<header class="header">
<div class="logo">SaaSify</div>
<nav class="nav">
<a href="#features">Features</a>
<a href="#pricing">Pricing</a>
<button class="btn-cta">Start Free</button>
</nav>
</header>
<!-- Hero Area -->
<section class="hero-section">
<h1>The Modern Workspace <br><span class="gradient-text">Redefined</span></h1>
<p>Streamline your development workflows, track progress in real-time, and collaborate globally in a single glassmorphic workspace console.</p>
<div class="hero-buttons">
<button class="btn-primary">Get Started</button>
<button class="btn-secondary">Watch Demo</button>
</div>
</section>
<!-- Features Area -->
<section id="features" class="features-section">
<h2>Why Teams Choose SaaSify</h2>
<div class="features-grid">
<!-- Feature 1 -->
<div class="feature-card">
<div class="feature-icon">⚡</div>
<h3>Real-time Sync</h3>
<p>Sync development assets across global teams instantly with no latency issues.</p>
</div>
<!-- Feature 2 -->
<div class="feature-card">
<div class="feature-icon">🛡️</div>
<h3>Secure Backups</h3>
<p>Enterprise-grade encryption protecting your repository assets continuously.</p>
</div>
<!-- Feature 3 -->
<div class="feature-card">
<div class="feature-icon">📊</div>
<h3>Console Analytics</h3>
<p>Inspect project velocities and deployments with integrated charts.</p>
</div>
</div>
</section>
<!-- Pricing Area -->
<section id="pricing" class="pricing-section">
<h2>Simple, Transparent Pricing</h2>
<div class="pricing-grid">
<!-- Tier 1 -->
<div class="price-card">
<h3>Hobby</h3>
<div class="price">$0<span>/mo</span></div>
<p>Essential widgets for solo creators.</p>
<button class="btn-card">Get Started</button>
</div>
<!-- Tier 2 (Featured) -->
<div class="price-card featured">
<div class="badge">Popular</div>
<h3>Startup</h3>
<div class="price">$29<span>/mo</span></div>
<p>Advanced metrics and team integration libraries.</p>
<button class="btn-card primary">Get Started</button>
</div>
<!-- Tier 3 -->
<div class="price-card">
<h3>Enterprise</h3>
<div class="price">Custom</div>
<p>Dedicated instances and custom SLA options.</p>
<button class="btn-card">Contact Sales</button>
</div>
</div>
</section>
<!-- Footer -->
<footer class="footer">
<p>© 2026 SaaSify Inc. All rights reserved.</p>
</footer>
</div>
</body>
</html>
Step 2: The CSS stylesheet (saas.css)
Create a saas.css stylesheet, defining custom properties, a background gradient, and grid areas:
/* ==========================================================================
Design Tokens & Resets
========================================================================== */
:root {
--bg-dark: #090d16;
--bg-glass: rgba(255, 255, 255, 0.03);
--border-glass: rgba(255, 255, 255, 0.08);
--color-accent: #38bdf8;
--color-accent-hover: #0ea5e9;
--text-white: #ffffff;
--text-muted: #64748b;
--font-sans: 'Inter', system-ui, sans-serif;
}
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: var(--bg-dark);
background-image: radial-gradient(circle at top right, #0c1c38, var(--bg-dark));
color: var(--text-white);
font-family: var(--font-sans);
line-height: 1.6;
overflow-x: hidden;
}
/* ==========================================================================
Grid Area Template Map
========================================================================== */
.layout-wrapper {
display: grid;
grid-template-columns: 1fr;
grid-template-rows: auto;
/* Map out layout sections */
grid-template-areas:
"header"
"hero"
"features"
"pricing"
"footer";
}
.header { grid-area: header; }
.hero-section { grid-area: hero; }
.features-section { grid-area: features; }
.pricing-section { grid-area: pricing; }
.footer { grid-area: footer; }
/* ==========================================================================
Header Navbar
========================================================================== */
.header {
display: grid;
grid-template-columns: auto 1fr;
align-items: center;
padding: 24px 8%;
}
.logo {
font-size: 1.75rem;
font-weight: 800;
color: var(--text-white);
}
.nav {
justify-self: end; /* Align navigation elements to right */
display: flex;
align-items: center;
gap: 32px;
}
.nav a {
color: var(--text-muted);
text-decoration: none;
font-weight: 500;
transition: color 0.2s;
}
.nav a:hover {
color: var(--text-white);
}
.btn-cta {
background-color: #ffffff;
color: #000000;
border: none;
padding: 10px 20px;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: opacity 0.2s;
}
.btn-cta:hover {
opacity: 0.9;
}
/* ==========================================================================
Hero Section
========================================================================== */
.hero-section {
padding: 100px 8% 80px 8%;
text-align: center;
max-width: 900px;
margin: 0 auto;
}
.hero-section h1 {
font-size: 4rem;
font-weight: 900;
line-height: 1.1;
margin-bottom: 24px;
}
.gradient-text {
background: linear-gradient(135deg, #38bdf8, #818cf8);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero-section p {
font-size: 1.25rem;
color: var(--text-muted);
margin-bottom: 40px;
}
.hero-buttons {
display: flex;
justify-content: center;
gap: 16px;
}
.btn-primary {
background-color: var(--color-accent);
color: #000;
border: none;
padding: 14px 28px;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: background-color 0.2s;
}
.btn-primary:hover {
background-color: var(--color-accent-hover);
}
.btn-secondary {
background-color: var(--bg-glass);
color: #fff;
border: 1px solid var(--border-glass);
padding: 14px 28px;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: background-color 0.2s;
}
.btn-secondary:hover {
background-color: rgba(255, 255, 255, 0.08);
}
/* ==========================================================================
Features Section (CSS Grid Auto-Fit)
========================================================================== */
.features-section {
padding: 80px 8%;
max-width: 1200px;
margin: 0 auto;
text-align: center;
}
.features-section h2 {
font-size: 2.5rem;
margin-bottom: 48px;
}
.features-grid {
display: grid;
/* Auto column wrapping: minimum 300px, max spans space */
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 32px;
}
.feature-card {
background: var(--bg-glass);
border: 1px solid var(--border-glass);
padding: 40px 32px;
border-radius: 16px;
text-align: left;
transition: border-color 0.3s;
}
.feature-card:hover {
border-color: rgba(56, 189, 248, 0.3);
}
.feature-icon {
font-size: 2.5rem;
margin-bottom: 24px;
}
.feature-card h3 {
font-size: 1.5rem;
margin-bottom: 12px;
}
.feature-card p {
color: var(--text-muted);
}
/* ==========================================================================
Pricing Section (CSS Grid Multi-Column)
========================================================================== */
.pricing-section {
padding: 80px 8%;
max-width: 1200px;
margin: 0 auto;
text-align: center;
}
.pricing-section h2 {
font-size: 2.5rem;
margin-bottom: 48px;
}
.pricing-grid {
display: grid;
/* Fixed 3 columns layout */
grid-template-columns: 1fr 1fr 1fr;
gap: 32px;
align-items: center;
}
.price-card {
background: var(--bg-glass);
border: 1px solid var(--border-glass);
padding: 48px 32px;
border-radius: 20px;
text-align: center;
position: relative;
}
.price-card.featured {
border: 2px solid var(--color-accent);
background: rgba(56, 189, 248, 0.02);
/* Push featured card up slightly to make it stand out */
transform: translateY(-8px);
}
.badge {
position: absolute;
top: 16px;
right: 16px;
background-color: var(--color-accent);
color: #000;
padding: 4px 12px;
font-size: 0.75rem;
font-weight: 700;
border-radius: 20px;
text-transform: uppercase;
}
.price {
font-size: 3rem;
font-weight: 800;
margin: 24px 0;
}
.price span {
font-size: 1rem;
color: var(--text-muted);
}
.btn-card {
width: 100%;
padding: 12px;
border-radius: 8px;
border: 1px solid var(--border-glass);
background: transparent;
color: white;
font-weight: 600;
cursor: pointer;
margin-top: 32px;
transition: all 0.2s;
}
.btn-card:hover {
background: rgba(255, 255, 255, 0.05);
}
.btn-card.primary {
background-color: var(--color-accent);
color: #000;
border: none;
}
.btn-card.primary:hover {
background-color: var(--color-accent-hover);
}
/* ==========================================================================
Footer Section
========================================================================== */
.footer {
padding: 48px 8%;
border-top: 1px solid var(--border-glass);
text-align: center;
color: var(--text-muted);
font-size: 0.875rem;
}
Responsive Layouts (Media Queries)
Add media queries at the bottom of saas.css to collapse pricing grids and adjust hero font sizing on mobile viewports:
@media (max-width: 992px) {
.pricing-grid {
grid-template-columns: 1fr; /* Collapse pricing columns into vertical stack */
gap: 24px;
}
.price-card.featured {
transform: none; /* Reset 3D transformation offsets */
}
.hero-section h1 {
font-size: 2.75rem;
}
}
@media (max-width: 768px) {
.header {
grid-template-columns: 1fr;
justify-items: center;
gap: 16px;
}
.nav {
justify-self: center;
}
}
Summary
This SaaS product landing page maps structural layout blocks via grid-template-areas templates. Features matrices are wrapped automatically using Grid auto-fit and minmax() functions, while pricing listings collapse into single-column stacks under tablet breakpoints.
Related Articles
Next Tutorial
Ready for a complex frontend project? Let's build a responsive dashboard UI: Project: Responsive Admin Dashboard.