A hero section is the first block a visitor sees when a page loads. It holds the headline, one line of support, a call to action and usually a visual, and it has a few seconds to explain what the page is and what to do next.
The stage at the top of this post runs ten modern hero sections live. Each one shows a different pattern and the CSS behind it, from container queries to scroll-driven animations. The stage plays through them on its own while it is on screen; hover to pause it, or pick one from the dock. Then read how each one is built below.
What is a hero section?
The hero section is the top area of a page, the part visible before any scrolling. On most sites it is the most-viewed block on the page and the one that decides whether a visitor stays.
A good hero has the same few parts, whatever it looks like:
- A headline that says what you offer in plain words.
- A supporting line that adds who it is for or why it is different.
- One primary call to action, with an optional secondary one.
- A visual that shows the product, the work or the mood.
- A trust signal when you have one: a number, a client list or a rating.
The ten heroes below use these parts in very different ways. The brands are fictional, so each pattern can have its own look.
What makes a hero section modern
Modern does not mean more animation. The heroes that hold up in 2026 share a few traits:
- One message. One headline, one main action, no slider of five competing offers.
- A fast first paint. The hero usually holds the Largest Contentful Paint element, so text or a light image beats a heavy video.
- Layout that follows its container. Container queries let the same hero work full-screen, in a column or in a preview frame.
- Motion with an off switch. Every animation stops when the visitor asks for reduced motion.
Here is how the ten compare:
| Hero | Best for | Key technique | Type pairing |
|---|---|---|---|
| X-ray lens | Architecture, engineering, dev tools | mask-image with CSS variables |
Light narrow sans + mono labels |
| Particle type | Festivals, art and creative brands | Canvas sampling + spring physics | One heavy sans + text |
| Live bento grid | SaaS with several selling points | grid-template-areas, @container |
Heavy sans + tabular figures |
| Self-playing product UI | Apps and dashboards | perspective, a scripted tour |
Sans + mono for figures |
| Kinetic proximity type | Events, type and design brands | Variable font axes | One variable sans |
| View-transition configurator | Products with variants | startViewTransition() |
Display serif + sans |
| Split-flap board | Travel, events, launches | 3D flaps, backface-visibility |
Condensed sans + tabular times |
| Scroll-driven cinematic | Product launches, physical products | animation-timeline: view() |
Condensed + regular widths of one family |
| Type-first editorial | Studios, agencies, personal brands | clamp() with cqi, text-wrap: balance |
Display serif + neutral sans |
| Prompt-first | AI tools, search, generators | @property animated border |
One soft sans |
Every demo uses the same base: the hero is a size container, so its breakpoints come from its own width, not the screen’s. That is why the Desktop, Tablet and Phone buttons in each demo change the layout while your screen stays the same.
.hero {
container: hero / inline-size;
}
@container hero (max-width: 760px) {
.hero-bottom { grid-template-columns: 1fr; }
}
If container queries are new to you, the complete guide to CSS container queries covers the syntax and units in detail.
1. X-ray lens hero
The X-ray lens hero is the one this page opens with. It stacks two versions of the same composition. On top is the finished design; underneath is its blueprint. A circular lens follows the pointer and cuts a hole in the top layer, so you look through to the plan.
We draw the lines you will live between.
Houses and small civic buildings in timber and stone, designed from the first sketch to the last joint.
The hole is a radial gradient used as a mask, with its center and radius in CSS variables:
.render {
mask-image: radial-gradient(
circle var(--r) at var(--x) var(--y),
transparent 98%, #000 100%
);
}
JavaScript only moves --x and --y, easing toward the pointer for a soft follow. The blueprint layer is aria-hidden, because it repeats the content.
Each layer draws the house as an inline SVG with the same viewBox and the same coordinates, so every line of the blueprint sits exactly under the render. On the blueprint, vector-effect: non-scaling-stroke keeps the lines one pixel thin at any size.
An inline SVG is not an LCP candidate. In my test on this page, the headline stayed the LCP element even though the drawing covers more of the screen.
The type follows the drawing-board idea: a light, narrow sans for the headline and a mono face for labels and dimensions, like the title block on a technical drawing. The lens edge carries a faint red and blue fringe, like real glass. Underneath is a real section drawing: the steel truss hidden in the walls that carries the 11-meter cantilever, piles down to bedrock, a ground-source heat loop and the sun angles for the site.
That is what makes an X-ray hero worth building. The lens shows something the finished image can’t, so moving the pointer pays off.
The idea fits any business with a “behind the scenes” story: architects, engineers, design systems or a developer tool that shows the code under the UI.
2. Particle type hero
Here the headline is made of about three thousand particles. Move the pointer through the letters and they scatter, then spring back into place. On a phone, a tap blows them apart and a slow breeze moves them every few seconds.
Drift
Art made of code, light and noise. Three nights, forty artists, one harbour.
The trick is to draw the word once on a hidden canvas, then keep every few pixels that are not transparent. Each kept pixel becomes a particle with a home position:
off.font = `900 ${size}px "Noto Sans Hebrew"`;
off.fillText('DRIFT', x, y);
const { data } = off.getImageData(0, 0, w, h);
for (let y = 0; y < h; y += step) {
for (let x = 0; x < w; x += step) {
if (data[(y * w + x) * 4 + 3] > 140) {
particles.push({ hx: x, hy: y, x, y, vx: 0, vy: 0 });
}
}
}
Every frame, each particle is pulled back toward its home and pushed away from the pointer:
for (const p of particles) {
p.vx = (p.vx + (p.hx - p.x) * 0.05) * 0.85;
p.vy = (p.vy + (p.hy - p.y) * 0.05) * 0.85;
const dx = p.x - px, dy = p.y - py, d = Math.hypot(dx, dy);
if (d < radius) {
p.vx += (dx / d) * (1 - d / radius) * 4;
p.vy += (dy / d) * (1 - d / radius) * 4;
}
p.x += p.vx;
p.y += p.vy;
}
Three rules keep it light. The loop stops once every particle has settled, it only runs while the hero is on screen, and particles of the same color are drawn together so the canvas changes its fill color six times per frame, not three thousand.
A canvas is not text, so the real headline sits next to it as a visually hidden element, and the line under the word is normal HTML. That line is what search engines and screen readers get, and it is what the browser can report as the Largest Contentful Paint.
3. Live bento grid hero
A bento hero splits the first screen into tiles of different sizes, like a lunch box. It works when a product has several selling points and one headline cannot carry them all. A static bento looks like a brochure, so this one moves: a live visitor count, a feed of new events, numbers that count up and borders that light up under the pointer.
Know what every visitor did next.
Funnels, retention and live sessions in one dashboard. Set up in five minutes, no SQL.
+38%
The layout is a named grid. The headline tile spans two columns and two rows, so size alone tells the eye where to start. Two container queries reflow it into two columns, then one:
.bento {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
grid-template-areas:
"head head stat feed"
"head head chart feed"
"logos logos logos logos";
}
@container hero (max-width: 820px) {
.bento {
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-areas: "head head" "stat chart" "feed feed" "logos logos";
}
}
The glowing border follows the pointer. Each tile has a pseudo-element with a radial gradient at the pointer position, and a mask shows only its 1px edge:
.tile::after {
content: '';
position: absolute;
inset: 0;
padding: 1px;
border-radius: inherit;
background: radial-gradient(220px circle at var(--mx) var(--my), #1d6b43, transparent 70%);
mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
Rules that keep a bento from turning into a pile of cards:
- One dominant tile. The headline tile is the largest and the only dark one.
- Real data in the tiles. A number, a chart or a live feed earns its space. A tile with only an icon and a title does not.
- Tabular figures for numbers.
font-variant-numeric: tabular-numskeeps a ticking counter from jittering, without switching to a mono font. - Fewer tiles on mobile. This demo drops the funnel and the logo strip on narrow screens instead of stacking six cards.
4. Self-playing product UI hero
A product hero shows the interface itself. This one also runs it: a ghost cursor matches two invoices, the counters update, a toast confirms each match, and the month closes. The visitor sees the product working before they sign up.
Close the books in hours, not weeks.
Ledgerline matches payouts, invoices and bank lines as they land, so month-end is a review, not a project.
2,400 finance teamsSOC 2 Type II
The interface is plain HTML and CSS, not a video or a screenshot, so it stays sharp at any size and weighs a few kilobytes. The panels sit in 3D space: the parent sets perspective, the stack uses transform-style: preserve-3d, and each floating card gets its own translateZ() depth.
The tour is a short async script. The cursor moves by changing two CSS variables, and CSS handles the easing:
async function tour() {
while (true) {
await untilVisible();
await click(rowA.querySelector('.match')); // cursor glides there, presses
setStatus(rowA, 'Matched');
count('matched', +1);
toast('Invoice #4472 matched');
await sleep(1000);
await click(closeButton);
showBanner('March closed, 3 days early');
await sleep(5000); // hold, reset, loop
}
}
A tour like this needs the same care as a video. It pauses when the hero leaves the screen, it never moves the real pointer or steals focus, and under reduced motion it stays still in its first state. Mark the mock interface aria-hidden="true", since its numbers are decoration.
Mono type belongs to the figures inside the interface only: amounts, counts, runway. The headline and buttons stay in the sans.
5. Kinetic proximity type hero
You don’t see this one often. Each letter of the headline grows heavier and narrower as the pointer gets close, as if the type reacts to you. On touch screens, a slow wave runs through the letters instead.
Type thatmoves withyou.
Three days, one track, 24 speakers on variable fonts, motion and reading on screens.
It works because a variable font has continuous axes. The font here goes from weight 300 to 900 and width 62.5 to 100, so every letter can sit anywhere in between. JavaScript splits the headline into letter spans and sets two variables on each one:
.ch {
display: inline-block;
font-variation-settings: "wght" var(--w, 300), "wdth" var(--s, 100);
}
A frame loop measures the distance from each letter to the pointer and eases the values toward their targets. It only runs while the hero is on screen, checked with an IntersectionObserver.
There is no font pairing here on purpose: one variable family is the whole show. Two details make it safe to ship:
- Screen readers get the sentence, not letters. The letter spans are
aria-hidden, and a visually hidden copy holds the full headline. - Keep it short. Every width change reflows the line, so this works for about 25 letters, not a paragraph.
6. View-transition configurator hero
In this hero the product is the call to action. Pick a color and the whole hero changes to match: the headphones, the background and the text. The new look spreads in a circle from the swatch you clicked.
Silence, in four colours.
Adaptive noise cancelling, 40 hours of battery and cushions you forget you are wearing.
Ink · €349
Each colorway is a set of custom properties on the hero, so changing color is one attribute:
.hero[data-c="ink"] { --bg: #121418; --ink: #f1efea; --body: #3a3e46; }
.hero[data-c="sand"] { --bg: #ece5d9; --ink: #231f19; --body: #cdbb9e; }
.headphones .cup { fill: var(--body); }
The reveal comes from the View Transitions API. The browser takes a snapshot of the hero before and after the change, and you animate the new snapshot with a growing circle:
hero.style.viewTransitionName = 'hero';
const vt = document.startViewTransition(() => { hero.dataset.c = colour; });
vt.ready.then(() => {
document.documentElement.animate(
{ clipPath: [`circle(0 at ${x}px ${y}px)`, `circle(${r}px at ${x}px ${y}px)`] },
{ duration: 750, easing: 'cubic-bezier(.65, 0, .35, 1)',
pseudoElement: '::view-transition-new(hero)' }
);
});
Same-document view transitions work in Chrome 111+, Safari 18+ and Firefox 144+. Where they are missing, or under reduced motion, the color simply switches. The swatches are a real radio group, so arrow keys move between colors and a screen reader announces the selected one.
The type pairing is the classic luxury one: a narrow serif for the headline, with its italic in the product color, and a plain sans for everything else.
7. Split-flap board hero
The split-flap hero turns the headline into a station departure board. Each letter flips through the alphabet until it lands, and the last line keeps changing destination: Berlin, Vienna, Prague, Paris.
Fall asleep in Oslo. Wake up in Berlin, Vienna, Prague or Paris.
Private cabins, real beds and breakfast at the border. Five sleeper routes from Oslo, every night.
Every cell is four layers: the top and bottom half of the current letter, plus two flaps. The top flap folds down, then the bottom flap folds up with the next letter:
.cell .top-flap {
transform-origin: 50% 100%;
backface-visibility: hidden;
animation: fold-down 38ms ease-in forwards;
}
.cell .bottom-flap {
transform-origin: 50% 0;
transform: rotateX(90deg);
animation: fold-up 38ms ease-out 38ms forwards;
}
@keyframes fold-down { to { transform: rotateX(-90deg); } }
@keyframes fold-up { to { transform: rotateX(0); } }
JavaScript steps each cell through the character set to its target and starts each column 45 milliseconds after the one before, which gives the board its ripple. The board is aria-hidden; a visually hidden sentence carries the message, so a screen reader does not hear forty letters change.
Size the cells with cqi so the whole board fits the hero at any width. Fifteen columns at 7.4cqi fit a 390px phone with room to spare.
8. Scroll-driven cinematic hero
The cinematic hero starts as a headline over a framed image. As you scroll, the image opens to full-bleed and the product specs arrive at the end.
Go where the signal ends.
A satellite messenger the size of a lighter. Text from anywhere on Earth.
140 gweight21 daysbatterySpring 2027first units shipThe whole effect is CSS. MDN describes the feature like this:
“The CSS scroll-driven animations module provides functionality that builds on the CSS animations module and Web Animations API. It allows you to animate property values along a scroll-based timeline rather than the default time-based document timeline.” (MDN, CSS scroll-driven animations)
The hero is taller than the screen and its inner layer is position: sticky, so it stays pinned while you scroll through it. A named view timeline on the hero drives the animations:
.hero {
height: 220svh;
view-timeline: --cine block;
view-timeline-inset: var(--header-height) 0px;
}
.hero-pin { position: sticky; top: var(--header-height); height: 100svh; }
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.hero-media {
animation: open linear both;
animation-timeline: --cine;
animation-range: contain 0% contain 60%;
}
}
}
@keyframes open {
from { clip-path: inset(56% 14% 7% 14% round 14px); }
to { clip-path: inset(0 0 0 0 round 0); }
}
view-timeline-inset subtracts the fixed site header, so the animation starts at the top of the page, not 87px later. Without support or with reduced motion, the hero falls back to a normal one-screen layout with everything visible.
Scroll-driven animations now work in every major engine. Chrome and Edge have had them since version 115, Safari since 26, and Firefox 159 turned them on by default on October 27, 2026.
Mist layers drift at different speeds as you scroll, the stars fade out as the image opens, and the device itself rises in with the specs at the end.
The headline never fades. Only the label and the button do, so the message is still there when the image fills the screen. The type comes from one family at two widths: the condensed cut for the headline and specs, the regular width for the line under them.
For the heights, svh keeps the pinned layer from jumping when a mobile browser’s toolbar shows and hides. The guide to dvh, svh and lvh explains the difference.
9. Type-first editorial hero
The type-first hero drops the image and lets one large headline carry the page. It suits studios and personal brands, where the voice matters more than a product shot.
Brands people remember long after the scroll.
Identity, websites and motion for companies that would rather be recognised than merely seen.
- 01Identity systems
- 02Websites
- 03Motion
The headline size comes from the container width, using the cqi unit (1% of the container’s inline size). A second limit, based on the screen height, keeps the headline from overflowing a short laptop screen:
.hero-title {
font-family: 'Instrument Serif', Georgia, serif;
font-size: clamp(2.9rem, min(10.4cqi, var(--stage-height) * .135), 12rem);
line-height: .9;
text-wrap: balance;
max-width: 16ch;
}
text-wrap: balance evens out the line lengths so the last line is not a single orphaned word. The text-wrap guide explains when to use balance and when pretty is the better choice.
Hover the list of services and a project card follows the cursor, a common move on studio sites that gives a type-led hero something to show without adding an image to the first paint.
The fonts contrast on purpose: a narrow, high-contrast display serif for the headline and a plain sans for everything you read. Keep the serif for the headline and the logo only, or the contrast stops working.
Watch out for font weight on the wire. A display font is the whole design here, so keep it to one file. The serif in this demo is a 15 KB latin subset with font-display: swap.
10. Prompt-first hero
In a prompt-first hero, the input box is the call to action. It became the default for AI tools, because the fastest way to show the product is to let the visitor use it on the first screen.
What will you build today?
Describe it in a sentence. Get a working site you can edit, host and own.
The glowing border is a conic gradient whose angle animates. Gradients cannot animate on their own, but a custom property registered with @property can:
@property --angle {
syntax: '<angle>';
inherits: false;
initial-value: 0deg;
}
.prompt {
border: 1px solid transparent;
background:
linear-gradient(#171620, #171620) padding-box,
conic-gradient(from var(--angle), #8a5af4, #dd56b8, #4e82e5, #8a5af4) border-box;
animation: spin 7s linear infinite;
}
@keyframes spin { to { --angle: 360deg; } }
The CSS @property guide shows more effects built the same way.
Click a suggestion and a small preview window assembles a site for it: a title, a hero block, products or a menu. It is a mock-up, but it shows what the product does in the first few seconds.
Keep the box usable:
- Give it a real label. A placeholder is not a label. The demo uses a visually hidden
<label>. - Do not autofocus it. On a phone that opens the keyboard over your hero.
- Pause rotating placeholders while the field has focus or text, and stop them under reduced motion.
How the ten fit together: color and type
Shown one after another, ten unrelated palettes would look like a template pack. The set follows a few rules instead:
- Light and dark alternate in the order of the dock, so every switch is a clear change of scene.
- Accents share a lightness. On dark heroes every accent sits at about the same OKLCH lightness as the site’s gold, so none of them outshines the rest.
- No accent sits close to the gold of the dock, so the controls never blend into a demo.
- Neutrals are tinted toward each hero’s own hue, not plain gray.
- Each hero has its own emphasis. An italic word, a highlighter, the weight change or the lens, not the same colored word ten times.
Type follows one rule: at most two families per hero, each with one job. Type-led heroes and the two serif heroes are never next to each other in the dock, so no two neighbors feel alike. A display face sets the voice, a text face does the reading, and mono appears only for data.
Every text color in the demos passes WCAG contrast of 4.5:1, or 3:1 for large display type.
Hero section performance and accessibility checklist
Whatever pattern you pick, check these before you ship:
- Know your LCP element. In most heroes it is the headline or the main image. Never start it at
opacity: 0for an entrance animation. I measured what that does in how hero animations were killing my LCP. - Size images for the screen. Serve a smaller file to phones and avoid a video as the only visual.
- Use
svhfor full-height heroes, not100vh, which is taller than the visible area on mobile. - Respect reduced motion. Wrap motion in
prefers-reduced-motion: no-preferenceand design a good static state. - Check contrast on every layer. Text over gradients and images needs 4.5:1 too.
- Use real buttons and labels. A call to action that is a styled
divcannot be reached with a keyboard.
FAQs
Common questions about hero sections:
Summary
A modern hero section does one job: it tells visitors what the page offers and what to do next, fast. The ten patterns here get there in very different ways. One is just a big headline, one is a lens that shows the blueprint under the design, and one is a departure board that flips its own letters.
Pick the pattern that fits your story, build it as a container so it works at any width, pair at most two fonts with clear roles, and give every motion a calm static fallback.