Centered hero
Headline, sub, two buttons and a trust row. The default that earns its place.
<section class="hero">
<p class="eyebrow">Now in open beta</p>
<h1>Put a static site online in the time it takes to make coffee</h1>
<p class="lede">No build step, no framework to learn, no account until you want one.
Drag a folder, get a URL.</p>
<div class="actions">
<a class="btn" href="/start/">Deploy a site</a>
<a class="btn ghost" href="/docs/">Read the docs</a>
</div>
<p class="trust">Free for personal projects · No card required · 40 ms median response</p>
</section>* { box-sizing: border-box; margin: 0; }
body {
font: 16px/1.65 system-ui, -apple-system, "Segoe UI", sans-serif;
color: #16202e;
background: #fff;
}
.hero {
max-width: 760px;
margin: 0 auto;
padding: 84px 24px 72px;
text-align: center;
}
.eyebrow {
display: inline-block;
font-size: .8rem;
color: #2a3abf;
background: #eef0fe;
border: 1px solid #dbe0fd;
padding: 5px 13px;
border-radius: 999px;
margin-bottom: 22px;
}
.hero h1 {
font-size: clamp(2.1rem, 1.1rem + 3.6vw, 3.6rem);
line-height: 1.08;
letter-spacing: -0.025em;
text-wrap: balance;
}
.lede {
margin: 20px auto 0;
max-width: 52ch;
font-size: 1.12rem;
color: #5b6b83;
text-wrap: pretty;
}
.actions {
margin-top: 32px;
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
}
.btn {
display: inline-block;
font-size: .98rem;
font-weight: 500;
text-decoration: none;
padding: 13px 26px;
border-radius: 10px;
background: #3b4fe4;
color: #fff;
border: 1px solid #3b4fe4;
}
.btn:hover { background: #2a3abf; border-color: #2a3abf; }
.btn.ghost { background: #fff; color: #16202e; border-color: #dbe1ea; }
.btn.ghost:hover { background: #f6f8fb; }
.trust {
margin-top: 26px;
font-size: .85rem;
color: #8593ab;
}
@media (max-width: 480px) {
.hero { padding: 56px 20px 48px; }
.actions .btn { width: 100%; }
}<section class="mx-auto max-w-3xl px-6 py-20 text-center">
<p class="mb-5 inline-block rounded-full border border-indigo-200 bg-indigo-50 px-3 py-1 text-sm text-indigo-700">
Now in open beta
</p>
<h1 class="text-balance text-4xl font-semibold leading-tight tracking-tight text-slate-900 sm:text-5xl lg:text-6xl">
Put a static site online in the time it takes to make coffee
</h1>
<p class="mx-auto mt-5 max-w-lg text-pretty text-lg text-slate-500">
No build step, no framework to learn, no account until you want one. Drag a folder, get a URL.
</p>
<div class="mt-8 flex flex-wrap justify-center gap-3">
<a class="rounded-lg bg-indigo-600 px-6 py-3 font-medium text-white hover:bg-indigo-700" href="/start/">Deploy a site</a>
<a class="rounded-lg border border-slate-200 px-6 py-3 font-medium text-slate-900 hover:bg-slate-50" href="/docs/">Read the docs</a>
</div>
<p class="mt-6 text-sm text-slate-400">Free for personal projects · No card required · 40 ms median response</p>
</section>How it works
The centred hero is the default for a reason: it works with any headline length, needs no artwork, and puts the single most important sentence in the place people look first.
The headline is real text. Setting it as an image is still common and it costs you the search snippet, the ability to select and translate it, and any hope of it reflowing on a narrow screen.
clamp() with a rem in the middle term. clamp(2.1rem, 1.1rem + 3.6vw, 3.6rem) scales with the viewport but keeps a rem component, so a reader who has raised their browser font size still gets larger text. A pure vw value ignores that setting entirely, which is an accessibility failure people rarely notice because they never test it.
text-wrap: balance on the headline, pretty on the paragraph. balance evens out the line lengths of short text, which stops the classic five-words-then-one-word break. pretty only prevents orphans, which is the right treatment for a longer paragraph — balance is capped at a few lines and is expensive on long text.
A 52ch measure on the lede. Line length is the single biggest factor in whether a paragraph is comfortable to read. Around 50 to 75 characters is the range, and centred text wants the shorter end of it.
Two buttons, one of them quiet. If both calls to action look equally important, neither is. The ghost button is there for people who are not ready yet, and it should look like it.
Accessibility notes
One <h1>, and it is the actual headline rather than a logo or a tagline. Screen reader users jump by heading, and the <h1> is what tells them what the page is.
The eyebrow is a paragraph, not a heading. Marking it up as an <h2> above the <h1> — which happens a lot — breaks the document outline.
Both buttons are links, because they navigate. Use a <button> only when something happens on the same page.
Making it yours
The eyebrow is the first thing to cut. It is useful for a genuine status — beta, a launch date, a version — and it is filler for anything else.
Full-width buttons below 480 pixels is a deliberate choice: two side-by-side buttons on a phone give you two cramped tap targets instead of one comfortable one.
For a coloured background, the gradient generator will build one. Check the headline contrast at both ends of the gradient, not just the middle.
Related templates
Split hero with image
Text on one side, image on the other, stacking cleanly on mobile.
HTMLCSSGradient hero with search
A full-bleed gradient hero with a prominent search field.
HTMLCSSSingle-file landing page
A complete landing page in one file — hero, features, call to action.
HTMLCSSNewsletter signup
An inline email capture with validation and a success state, in three layouts.
HTMLCSSJavaScriptCheck your version
Once you have edited this, the HTML validator will catch any tag you left unclosed, and the formatter will tidy the indentation. Both run in your browser.