
A hero has to answer three questions inside five seconds: what this is, who it is for, and what happens next. Everything else in the first viewport is either serving one of those three or taking space from something that would.
Most generated heroes answer one. They arrive with a headline that names a feeling rather than a category, no audience, and two identically weighted buttons, which is a page asking the visitor to choose before it has told them anything.
A cover like a hundred others is zero effort, and trust is built on invested effort.
A developer on Hacker News
The call, before the values: the hero is the one section where every dimension should be a written number, because it is the only section guaranteed to be seen. The Thanor library ships those numbers with the prompt rather than leaving them to the model.
The frame, and what fills it#
Height is min(88svh, 900px), and there are two decisions inside that value. svh rather than vh, because 100vh on a mobile browser measures the viewport without the collapsing toolbar, so a 100vh hero is taller than the screen and the button falls below the fold on the device where it matters most. svh is the small viewport height and it is always visible.
And 88 rather than 100, so a strip of the next section is showing. That twelve percent is the cheapest scroll cue available and it replaces the animated chevron, which is a component that exists to solve a problem a height value solves better.
The contents, in order, and nothing else is permitted in the first viewport:
- Eyebrow: one line,
12px, uppercase,0.22emtracking, in muted. It names the category so the headline does not have to. - Headline: two lines maximum,
18chto26chper line. - Subhead: one or two sentences,
48ch, naming the audience explicitly. - Primary action: one filled button.
- Secondary action: a text link with an underline. Not a second button.
- Media: one image or one canvas, never both, and never a carousel.
A carousel in a hero is the single most expensive mistake available, because it guarantees that four fifths of your most valuable message is invisible at any given moment.
The header sits inside the same frame and is not a seventh element: 72px tall, transparent over the hero, and it takes the raised colour with a hairline border only after the scroll passes 64px.
The headline, sized and measured#
Ratio 1.333 from 18px. The hero uses steps 5 and 6, and step 7 exists for a one line hero only.
| Step | Size | Line height | Tracking | Used for |
|---|---|---|---|---|
| -1 | 14px | 20px | 0.01em | eyebrow, button label small |
| 0 | 18px | 29px | 0 | body copy elsewhere |
| 1 | 24px | 34px | 0 | subhead on a wide hero |
| 2 | 32px | 40px | -0.01em | h2 elsewhere |
| 3 | 43px | 50px | -0.015em | headline on a phone |
| 4 | 57px | 62px | -0.02em | headline on a tablet |
| 5 | 76px | 80px | -0.025em | two line headline, desktop |
| 6 | 101px | 100px | -0.03em | one line headline, desktop |
Ship the headline as clamp(43px, 7.2vw, 104px), which resolves to 104px at 1445px and above and holds at 43px on a phone. The subhead is 20px at 32px leading, weight 400, in muted rather than ink, which is what stops it competing with the line above it.
The measure matters more than the size. A 76px headline at 40ch is four lines of display type and reads as a paragraph that got bigger. The same words at 22ch are two lines and read as a statement. Set max-width: 22ch on the headline and let the size clamp handle the rest.
The internal rhythm, and the one action#
Vertical gaps inside the hero, which are deliberately not equal:
- Eyebrow to headline:
20px. - Headline to subhead:
24px. - Subhead to button row:
40px. - Button row to the bottom edge of the frame:
96pxminimum.
The 40px before the action and the 24px above it are the important pair. A button 16px under its subhead reads as part of the sentence, and a button 80px below reads as unrelated. 40px is close enough to be the conclusion of the paragraph and far enough to be a separate object.
The primary button: 52px tall, 28px horizontal padding, label at 16px weight 600, and the label is a verb plus the object, never the word Submit and never the word Learn. The secondary action is a text link at 16px with text-underline-offset: 3px, sitting 24px to the right on desktop and 16px below on a phone.
Two more numbers finish the block:
- Risk line,
14pxin muted,12pxunder the button. No card required, free for thirty days, cancel any time. It belongs under the action because that is where the hesitation happens, not in the pricing section. - Horizontal offset: the text block starts at the container's left edge, not centred, whenever there is media beside it. A centred column next to an image is two compositions fighting for the same axis.

Colour, and the scrim over a photograph#
Five values, and one gradient that is not a decoration.
| Role | Hex | Contrast on ground | Where it goes |
|---|---|---|---|
| Ground | #0E1014 | the hero background | |
| Raised | #171A20 | inline card, input, chip | |
| Ink | #F5F3EE | 17.17:1 | headline and subhead ink |
| Muted | #96938C | 6.21:1 | eyebrow, subhead, caption |
| Accent | #7FD1C1 | 10.69:1 | filled button, link underline |
An accent filled button takes #0E1014 text, which is the same 10.69:1 because contrast is symmetric. A #F5F3EE filled button with #0E1014 text measures 17.17:1 and is the safer primary when the accent is doing work elsewhere.
Type over a photograph needs a scrim, and a flat wash is the wrong shape for it. Use linear-gradient(to top, rgba(14, 16, 20, 0.72) 0%, rgba(14, 16, 20, 0) 62%), which darkens the band the text occupies and leaves the top 38% of the photograph at full strength. A flat rgba(14, 16, 20, 0.45) over the whole image protects the same type and costs the picture, which is a poor trade when the picture is the reason the hero has an image.
Two last requirements on that image:
- Aspect
4 / 5for a portrait split hero,16 / 9for a full width one, withobject-fit: coverand a declaredaspect-ratioso the frame reserves its box and the headline never shifts after load. fetchpriority="high"on that one image, and nothing inside the first viewport is lazy loaded.
The entrance, and the two layouts#
One curve, cubic-bezier(0.22, 1, 0.36, 1), one duration, 720ms, one travel distance, 20px upward, and the sequence is made entirely of delays:
| Element | Delay | Duration | Transform |
|---|---|---|---|
| Eyebrow | 0ms | 720ms | translateY(20px) to 0 |
| Headline | 80ms | 720ms | translateY(20px) to 0 |
| Media | 120ms | 900ms | scale(1.04) to scale(1) |
| Subhead | 180ms | 720ms | translateY(20px) to 0 |
| Buttons | 280ms | 720ms | translateY(20px) to 0 |
The whole hero is settled at 1000ms. That ceiling is the rule: a hero still animating at two seconds has spent the visitor's five second budget on itself. Under prefers-reduced-motion: reduce, every row resolves instantly at full opacity with no transform.
Two layouts, and both have fixed column values on a 12 column grid:
- Split. Text on columns
1to5, media on7to12, gutter24px. Text is vertically centred against the media, not against the frame. - Stacked. Text on columns
2to8, media full bleed beneath with the gradient scrim, text over it. Headline at step 6, one line, and the media is the only element in the hero that touches the viewport edge.
Collapse both to a single column at 900px. On the split layout the text goes above the media on a phone, not below it, because a headline pushed under an image is a headline nobody reads, and the media takes 56svh so the button still clears the fold.
The verdict on hero sections#
The hero is where specification pays back fastest, because it is one screen and every value in it is visible. Sixteen numbers describe it completely: one height, two measures, three type steps, four gaps, five colours and one scrim. Written down, a model builds the same hero every time. Left to prose, you get a different hero each run, which is the variance everybody complains about and it has a mechanical cause.
The set:
min(88svh, 900px), never100vh.- Headline
clamp(43px, 7.2vw, 104px)at22ch, two lines maximum. - Gaps of
20,24,40and96, unequal on purpose. - Five colours, a gradient scrim to
62%, declaredaspect-ratioon media. 720msoncubic-bezier(0.22, 1, 0.36, 1), delays at0,80,120,180and280, all settled by1000ms.- One filled button, one text link, no carousel.
Then run the five second test on it: show somebody the first viewport for five seconds, take it away, and ask what the product is and who it is for. A hero that fails that has a copy problem no measurement fixes, and a hero that passes it and still looks cheap has exactly the problem this article's numbers solve.
What comes after the hero decides whether any of it converts, and the section order for the rest of the page is the other half of this article. For the system the hero sits inside, the expensive look specification has the palette and the spacing ladder, and the awwwards recipe is the version that spends more of its budget on the first screen. To skip writing the sixteen numbers yourself, browse the Thanor library and take a hero that already has them.
Questions this raises
How tall should a hero section be?
88svh, capped at 900px. Use svh rather than vh so a mobile browser toolbar does not push content out of the frame, and keep the remaining 12 percent so the next section's top edge is visible and the page reads as continuing.
How long should a hero headline be?
18 to 26 characters per line, two lines at most, which is roughly 6 to 12 words in total. Past 26 characters a display size headline wraps to four lines and stops reading as a statement.
What are the right entrance animation timings for a hero?
720ms on cubic-bezier(0.22, 1, 0.36, 1) with a 20px rise, staggered by delay: eyebrow at 0ms, media at 120ms, headline at 80ms, subhead at 180ms and the button at 280ms. The whole hero settles inside one second.
What overlay makes text readable over a photograph?
A vertical gradient from rgba(14, 16, 20, 0.72) at the edge nearest the text to fully transparent at 62 percent, rather than a flat wash over the whole image. A flat wash dulls the photograph to protect type that only needs help in one band.
Should the hero have one button or two?
One filled button and one text link, never two filled buttons. Two equal buttons ask the visitor to make a decision they do not yet have the information to make.
Where do I get a hero specification I can paste into a model?
The Thanor library is available now, and every prompt in it carries the height, the measure, the type ladder, the scrim value and the entrance timings as literal numbers.
Part of
The expensive look
What makes a site read as expensive, written as values rather than adjectives: the type scale, the spacing, the curve and its duration, and the order the sections run in.
