Hero Section
25 minWalkthrough: Hero Section
This walkthrough builds a production hero section from scratch, applying typography, animation, and copywriting principles simultaneously. By the end you'll have a hero that demonstrates every pillar working together — not as theory, but as shipped code.
We'll start with the worst version and fix it layer by layer, so you can see the compounding effect of small decisions.
The starting point
Here's a hero section that works. It has a headline, a subheadline, a CTA, and it renders without errors. Most production sites ship something at this quality level:
<section className="flex items-center justify-center px-6 py-24">
<div className="text-center">
<h1 className="text-4xl font-bold">
Build Better Websites with Our Platform
</h1>
<p className="mt-4 text-gray-500">
Our innovative solution helps you create beautiful, fast, and
reliable websites with ease. Get started today and see the
difference.
</p>
<button className="mt-8 rounded bg-blue-600 px-4 py-2 text-white">
Learn More
</button>
</div>
</section>
Count the problems. We'll fix them in order: copy first, then typography, then craft, then animation.
Layer 1: Copywriting
The headline is what-first: "Build Better Websites with Our Platform." It leads with the product, not the reader's motivation. The subheadline is a stack of adjectives ("beautiful, fast, and reliable") with no proof. The CTA is the weakest possible label: "Learn More."
Fix the headline
Apply the Why-First framework. Ask: why does the reader care? Not what the product does, but what changes for them.
Before: "Build Better Websites with Our Platform" After: "Ship interfaces your users actually notice"
The new headline leads with the outcome (interfaces users notice), uses a verb that implies action (ship), and doesn't mention the product at all. It also has a quieter confidence — no superlatives, no "better," no exclamation marks.
Fix the subheadline
Apply Show Don't Tell. Replace the adjectives with a specific scenario:
Before: "Our innovative solution helps you create beautiful, fast, and reliable websites with ease." After: "The thousand small decisions — the right easing curve, the curly apostrophe, the CTA that says exactly what happens next — are the difference between forgettable and remarkable."
This is longer, but every word earns its place. The em-dash pair is correct (not hyphens). The three examples are specific and drawn from the four pillars. The close ("forgettable and remarkable") is a concrete contrast, not a vague promise.
Fix the CTA
Apply the CTA Clarity formula: action verb + what they get + qualifier.
Before: "Learn More" After: "Start the course — free"
"Start" is a strong action verb. "The course" tells them what they get. "Free" is the qualifier that reduces friction. The em-dash separates the action from the qualifier.
Layer 2: Typography
With the copy fixed, the typographic problems become visible.
Eyebrow text
Add a small label above the headline. This is the eyebrow — it establishes context before the reader hits the headline:
<p className="text-sm font-medium tracking-widest uppercase text-muted-foreground">
A course in obsessive attention to detail
</p>
The eyebrow uses tracking-widest (letter-spacing) because it's set in caps. Caps without letterspacing feel cramped — the extra space between letters compensates for the perceived density of all-uppercase forms.
Headline sizing
The headline should use a display scale, not body typography:
<h1 className="mt-4 text-4xl font-bold tracking-tight sm:text-6xl">
tracking-tight is critical. Large text needs negative letter-spacing because at display sizes, the default spacing looks loose and uncertain. The same text that looks fine at 16px looks gappy at 48px.
Responsive scaling (text-4xl → sm:text-6xl) ensures the headline commands attention on desktop without overflowing on mobile.
Subheadline typography
The subheadline should use text-balance to prevent orphaned words, and text-lg leading-8 for comfortable reading:
<p className="text-muted-foreground mt-6 text-lg leading-8 text-balance">
Proper punctuation
The copy uses an em-dash. In JSX, use the HTML entity or Unicode directly:
{/* Not: "decisions - the right" (hyphen) */}
{/* Not: "decisions -- the right" (double hyphen) */}
{/* Correct: */}
decisions — the right
The thin spaces ( ) around the em-dash are a typographic refinement. They prevent the dash from optically crowding the adjacent words while being narrower than full word spaces.
Layer 3: Craft
Spacing system
Replace arbitrary py-24 with a spacing system. The hero should have generous vertical padding that scales with the viewport:
<section className="flex flex-1 flex-col items-center justify-center px-6 py-24 sm:py-32">
<div className="mx-auto max-w-2xl text-center">
max-w-2xl constrains the content width. Without it, the subheadline stretches across the entire viewport, making line length unbearable on wide screens.
Button styling
The CTA button needs proper sizing (44px touch target minimum), consistent border radius, and hover state:
<a
href="/foundations/the-one-percent"
className="inline-flex h-11 items-center justify-center rounded-lg bg-primary px-6 font-medium text-primary-foreground text-sm transition-colors hover:bg-primary/90"
>
Start the course — free
</a>
Use an <a> tag, not a <button> — this navigates to a URL, so it's semantically a link. The h-11 ensures a 44px minimum touch target. transition-colors applies a smooth hover state.
Secondary action
Add a secondary link for users who aren't ready to commit:
<div className="mt-10 flex items-center justify-center gap-4">
<a href="/foundations/the-one-percent" className="...primary styles...">
Start the course — free
</a>
<a href="#structure" className="text-muted-foreground text-sm hover:text-foreground">
See the syllabus
</a>
</div>
Two actions, clear visual hierarchy. The primary CTA has a background; the secondary is text-only. Never give two CTAs equal visual weight.
Layer 4: Animation
The hero should animate its entrance, but only on first load — not on every page navigation. The animation serves orientation (the content is arriving) and delight (first impression), both of which are one-time events.
Stagger entrance
Each element enters sequentially with a slight delay. The order follows reading order: eyebrow → headline → subheadline → CTA. Each element fades in and translates up:
<motion.p
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, ease: [0.22, 1, 0.36, 1] }}
className="text-sm tracking-widest uppercase text-muted-foreground"
>
A course in obsessive attention to detail
</motion.p>
<motion.h1
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.1, ease: [0.22, 1, 0.36, 1] }}
className="mt-4 text-4xl font-bold tracking-tight sm:text-6xl"
>
Ship interfaces your users actually notice
</motion.h1>
Key decisions:
- 50ms stagger between elements (0.1, 0.15, 0.2). Short enough to feel like a sequence, not a slideshow.
- 10px vertical translation — subtle. The content enters from just below, not from the bottom of the screen.
- Custom ease
[0.22, 1, 0.36, 1]— a strong deceleration curve that starts fast and settles gently. - 500ms duration — longer than UI animations because this is a first-impression entrance, not a state transition.
Reduced motion
Wrap the animation in a prefers-reduced-motion check:
const prefersReduced = useReducedMotion();
<motion.h1
initial={prefersReduced ? false : { opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
...
>
When initial is false, motion/react skips the entrance animation entirely. The content appears in its final state immediately. This isn't a slower animation — it's no animation at all, which is what the user has requested.
The compound effect
Compare the starting point with the finished version. The copy went from generic to specific. The typography went from unsized to display-scaled with proper punctuation. The craft went from arbitrary to systematic. The animation went from absent to purposeful.
No single change would survive an A/B test. Together, they're the difference between "it works" and "someone cared." That's the thesis of this entire course — and a hero section is where users form their first judgment about whether you're in the first category or the second.