This is the first mini project for Going further with CSS. You will build a responsive marketing page without a framework – fluid type, Grid or Flexbox layout, container queries where they help, and form states done properly. HTML structure can be simple; CSS is what we are practising.
The scenario
Harbour Analytics is a fictional SaaS company selling reporting tools to small businesses. They need a single landing page: hero, feature grid, social proof, pricing teaser, and a sign-up form. Nothing fancy in JavaScript – pure HTML and CSS.
Design can be plain. Readable type, sensible spacing, and layout that works from 320px to wide desktop matter more than brand polish.
Required sections
- Header – logo text, primary nav (Features, Pricing, About), CTA button. Sticky optional but must not break scroll on mobile.
- Hero – headline, subtext, two buttons (primary + secondary), optional illustration placeholder.
- Features – at least six features in a responsive grid (
auto-fitor container queries). - Testimonial – quote, name, role. Max line length for readability.
- Pricing teaser – one highlighted plan card with list of inclusions.
- Sign-up form – email, name, company; proper labels, focus-visible, user-invalid styling.
- Footer – links, copyright.
CSS requirements
Your stylesheet should demonstrate techniques from these tutorials:
- Design tokens on
:root(colours, spacing, fluid type withclamp()) - Logical properties for padding and margins (
padding-block,margin-inline) - At least one
@layerblock (reset/base/components/utilities) - Feature or pricing cards using container queries OR a solid
auto-fitgrid - Form controls with
:focus-visibleand:user-invalid(or:invalidwith care) prefers-reduced-motionandprefers-color-schemehandling (dark tokens at minimum)
Starter HTML skeleton
<!DOCTYPE html>
<html lang="en-GB">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Harbour Analytics</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">…</header>
<main>
<section class="hero">…</section>
<section class="features" id="features">…</section>
<section class="testimonial">…</section>
<section class="pricing" id="pricing">…</section>
<section class="signup">
<form class="signup-form" action="#" method="post">…</form>
</section>
</main>
<footer class="site-footer">…</footer>
</body>
</html>
Suggested CSS structure
@layer reset, base, components, utilities;
@layer reset {
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; }
}
@layer base {
:root {
--color-text: #1a1a1a;
--color-surface: #fff;
--color-accent: #0366d6;
--text-hero: clamp(2rem, 1.5rem + 2vw, 3rem);
--space-section: clamp(3rem, 2rem + 4vw, 6rem);
}
/* dark scheme, body typography */
}
@layer components {
.site-header { … }
.hero { … }
.feature-grid { … }
.plan-card { … }
.signup-form { … }
}
Acceptance checklist
- No horizontal scroll at 320px width
- Headings scale fluidly; body text stays readable
- Keyboard tab through nav, buttons, and form – focus always visible
- Grid reflows without overlapping content
- DevTools flex/grid overlay used during build (you fixed at least one real bug)
Stretch goals
:has()to style the plan card that contains a ‘Popular’ badge- Scroll-margin on section IDs for in-page nav
- Manual theme toggle with
data-themeoverriding system preference
When you finish, you have a portfolio-ready page and a stylesheet structure you can reuse. The final mini project builds a dashboard shell with sidebar, main content, and aside.

