Landing page structure is a fixed sequence of sections, each with one job: say what the product is, prove it, explain how it works, answer the objections, and ask for the action. Get the sequence right and the page almost writes itself.
What sections go on a landing page, and in what order?
The order is not arbitrary. Each section exists to remove the objection raised by the one before it, so it follows the order a sceptical visitor thinks in.
- Header — the logo, the primary navigation and one clear action, present from the first screen.
- Hero — the promise in one sentence, one line of support, and the main action.
- Proof strip — logos, ratings or a count of users, immediately under the promise.
- Problem and solution — what is wrong today and what the product changes.
- Features — three or four capabilities, each with a heading and a short explanation.
- How it works — three steps, because a process is easier to believe than a promise.
- Pricing — the plans, with one recommended and one call to action.
- Testimonial — one specific story, with a name and a role.
- Questions — the objections that are still unanswered.
- Final call to action — the same action as the hero, restated.
- Footer — secondary links, contact details and the small print.
Two of those deserve emphasis. The proof strip goes directly under the hero because scepticism is highest there, and the final call to action repeats the hero action because a reader who scrolls the whole page has just finished being convinced and needs to be told what to do next.
How do you keep the shell consistent?
Every page needs a small number of shared pieces: a container that limits line length, a vertical rhythm shared by all the sections, and a header and footer that behave the same everywhere. These belong in your layout and base files rather than in the landing page, because the pricing page needs the same shell.
<header class="site-header">
<a class="brand" href="/">Fernway</a>
<nav aria-label="Primary">
<a href="#features">Features</a>
<a href="#pricing">Pricing</a>
</nav>
<a class="button" href="#signup">Start caring for plants</a>
</header>
<main>
<section class="hero" aria-labelledby="hero-title">
<h1 id="hero-title">Keep your plants alive without thinking about it</h1>
<p>Fernway checks the light and moisture in each room and tells you the one thing that actually matters this week.</p>
<form class="signup" action="/subscribe" method="post">
<label for="email">Email address</label>
<input id="email" name="email" type="email" autocomplete="email" required>
<button type="submit">Start free</button>
</form>
</section>
<section class="features" id="features" aria-labelledby="features-title">
<h2 id="features-title">What you get</h2>
<ul class="feature-list">
<li><h3>Room by room light checks</h3><p>Placement advice that accounts for your windows.</p></li>
<li><h3>Watering reminders that adapt</h3><p>Schedules that shift with the season and the weather.</p></li>
</ul>
</section>
<section class="pricing" id="pricing" aria-labelledby="pricing-title">
<h2 id="pricing-title">Plans</h2>
<ul class="plan-list">
<li class="plan"><h3>Single plant</h3><p>Free</p></li>
<li class="plan plan--featured"><h3>Whole home</h3><p>4 a month</p></li>
</ul>
</section>
</main>
<footer class="site-footer">
<p>Fernway, made in a flat in Manchester.</p>
</footer>
Notice the details in that skeleton. The page has exactly one first-level heading, and it is the promise in the hero. Every section is named with aria-labelledby pointing at its own heading, so a screen reader user can jump between sections from the landmark menu. The email field has a real label rather than a placeholder, and the input carries a type and an autocomplete hint so the browser can fill it. The footer is outside the main region, as it should be.
How should the hero be built?
The hero has three parts and no more: the headline, one supporting sentence, and the action. The headline states the outcome in the reader's words rather than describing the product, and the supporting sentence gives the mechanism that makes the outcome believable. Everything else is decoration.
.hero {
display: grid;
gap: 1.5rem;
padding-block: 4rem;
max-inline-size: 40rem;
}
@media (min-width: 48rem) {
.hero {
grid-template-columns: 1.1fr 0.9fr;
align-items: center;
gap: 3rem;
max-inline-size: none;
}
}
.hero h1 {
margin: 0;
font-size: clamp(2rem, 5vw, 3.25rem);
line-height: 1.1;
text-wrap: balance;
}
The base rule handles the narrow screen with a single column, and the media query adds the second column once there is room for it. That is the mobile-first pattern: the default is the simple layout, and the enhancement is added on top. text-wrap: balance evens out the lines of a headline so it does not leave one lonely word on the last line.
How do you make repeated sections consistent?
Features, pricing plans and testimonials all appear several times, and each repetition should be built from the same component rather than copied. The visual consistency is the easy part; the important part is that the markup for a feature item is identical everywhere it appears, so the page is navigable and the CSS stays short.
.feature-list {
display: grid;
gap: 2rem;
margin: 0;
padding: 0;
list-style: none;
}
@media (min-width: 40rem) {
.feature-list {
grid-template-columns: repeat(2, 1fr);
}
}
.plan-list {
display: grid;
gap: 1.5rem;
margin: 0;
padding: 0;
list-style: none;
}
.plan {
padding: 1.5rem;
border: 1px solid #e2e8f0;
border-radius: 12px;
}
.plan--featured {
border-color: #1d4ed8;
box-shadow: 0 10px 30px rgb(15 23 42 / 0.08);
}
Both lists reset their own margins and padding, because a list has default indentation that you almost never want inside a layout grid. The featured plan carries an extra modifier class rather than a separate block of rules, so the two plans share everything except the treatment that marks the recommended one.
What makes a call to action work?
An action needs three things: a button that looks clickable, a label that says what happens next, and a form that can report a problem. The button should be the most prominent thing in its section, and the label should describe the result rather than the mechanism, so "Start free" is better than "Submit".
Give the button a visible focus ring, because a keyboard user has to be able to see where they are. The :focus-visible selector draws that ring only when the browser decides the interaction is keyboard-driven, which avoids the stray outline that appears when you click a button with a mouse.
.button {
display: inline-block;
padding: 0.75rem 1.25rem;
border: 0;
border-radius: 999px;
background: #1d4ed8;
color: #ffffff;
font: inherit;
font-weight: 600;
text-decoration: none;
}
.button:focus-visible {
outline: 3px solid #0f172a;
outline-offset: 3px;
}
Notes from the field
- One first-level heading per page, and it belongs to the hero.
- Name every section with a heading so the landmark menu is useful.
- Each section removes the objection raised by the previous one.
- Repeat the same action at the top and the bottom of the page.
- Build repeated blocks as components, not as copies of the markup.
- Label form fields properly and give buttons a visible focus ring.
- Reset the default list indentation whenever a list becomes a layout grid.
- Write the narrow layout first and let the media query add columns.
Try it yourself: build the Fernway page above and give it the four sections it is missing: a proof strip, a how-it-works block, a testimonial and a question list. Write the copy for each in two sentences or fewer. Then set max-inline-size: 40rem on every section and check that no line of body text runs past a comfortable reading length. Last, remove the hero action button and see how much less clear the page becomes, which is a quick way to confirm that a page has one job per section.