31 CSS Hero Sections21 / 31
Product Shot Hero
Apple-keynote product shot — a CSS-painted device front-and-centre with floating feature badges that pulse around it. Ice blue + chrome silver on warm white.
Published
The code
<section class="hs-21" aria-label="Hero">
<div class="hs-21__stage">
<div class="hs-21__device" aria-hidden="true">
<div class="hs-21__screen"></div>
<div class="hs-21__cam"></div>
</div>
<span class="hs-21__pulse hs-21__p1"><strong>· chip</strong>16-core neural</span>
<span class="hs-21__pulse hs-21__p2"><strong>· battery</strong>22 hours</span>
<span class="hs-21__pulse hs-21__p3"><strong>· weight</strong>1.24 kg</span>
</div>
<div class="hs-21__copy">
<h2>The lightest pro<br />laptop we've ever <em>shipped.</em></h2>
<a class="hs-21__cta" href="#buy">From $1,499 →</a>
</div>
</section><section class="hs-21" aria-label="Hero">
<div class="hs-21__stage">
<div class="hs-21__device" aria-hidden="true">
<div class="hs-21__screen"></div>
<div class="hs-21__cam"></div>
</div>
<span class="hs-21__pulse hs-21__p1"><strong>· chip</strong>16-core neural</span>
<span class="hs-21__pulse hs-21__p2"><strong>· battery</strong>22 hours</span>
<span class="hs-21__pulse hs-21__p3"><strong>· weight</strong>1.24 kg</span>
</div>
<div class="hs-21__copy">
<h2>The lightest pro<br />laptop we've ever <em>shipped.</em></h2>
<a class="hs-21__cta" href="#buy">From $1,499 →</a>
</div>
</section>.hs-21 {
display: grid;
grid-template-columns: 1.2fr 1fr;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 56px);
gap: clamp(24px, 4vw, 56px);
align-items: center;
background: radial-gradient(circle at 30% 30%, #d8e8f0 0%, transparent 50%), radial-gradient(circle at 80% 70%, #e8eef2 0%, transparent 50%), #f8fafc;
font-family: 'Inter', system-ui, sans-serif;
color: #1a2840;
box-sizing: border-box;
}
.hs-21__stage {
position: relative;
height: 100%;
min-height: 320px;
display: grid;
place-items: center;
}
.hs-21__device {
width: 320px;
height: 200px;
background: linear-gradient(160deg, #b8c8d8 0%, #8090a8 50%, #607080 100%);
border-radius: 14px;
position: relative;
box-shadow: 0 22px 60px rgba(96,112,128,0.4), inset 0 1px 0 rgba(255,255,255,0.5), inset 0 -2px 0 rgba(0,0,0,0.18);
}
.hs-21__screen {
position: absolute;
inset: 8px;
background: linear-gradient(135deg, #1a2840 0%, #0a1428 100%);
border-radius: 7px;
box-shadow: inset 0 0 0 2px #0a1428;
}
.hs-21__cam {
position: absolute;
top: 4px;
left: 50%;
transform: translateX(-50%);
width: 5px;
height: 5px;
border-radius: 50%;
background: #1a2840;
}
.hs-21__pulse {
position: absolute;
background: #fff;
border: 1px solid #d0d8e0;
padding: 8px 12px;
border-radius: 999px;
font-size: 12.5px;
color: #1a2840;
display: inline-flex;
flex-direction: column;
gap: 1px;
box-shadow: 0 8px 22px rgba(96,112,128,0.18);
animation: hs-21-bob 4s ease-in-out infinite;
}
.hs-21__pulse strong {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
color: #6b85a5;
font-weight: 600;
letter-spacing: 0.04em;
}
.hs-21__p1 {
top: 10%;
left: 4%;
animation-delay: 0s;
}
.hs-21__p2 {
top: 35%;
right: 0;
animation-delay: -1.3s;
}
.hs-21__p3 {
bottom: 12%;
left: 12%;
animation-delay: -2.6s;
}
@keyframes hs-21-bob {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-6px);
}
}
.hs-21__copy {
padding: 12px 0;
}
.hs-21 h2 {
margin: 0 0 22px;
font-size: clamp(30px, 4.5vw, 48px);
font-weight: 700;
letter-spacing: -0.025em;
line-height: 1.05;
color: #1a2840;
}
.hs-21 h2 em {
background: linear-gradient(90deg, #6b85a5, #b8c8d8);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-style: italic;
font-weight: 800;
}
.hs-21__cta {
display: inline-block;
padding: 13px 24px;
background: #1a2840;
color: #f8fafc;
border-radius: 999px;
text-decoration: none;
font-weight: 600;
font-size: 14.5px;
transition: transform 0.15s;
}
.hs-21__cta:hover {
transform: translateY(-1px);
}
@media (max-width: 720px) {
.hs-21 {
grid-template-columns: 1fr;
}
}
@media (prefers-reduced-motion: reduce) {
.hs-21__pulse {
animation: none;
}
.hs-21__cta {
transition: none;
}
}.hs-21 {
display: grid;
grid-template-columns: 1.2fr 1fr;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 56px);
gap: clamp(24px, 4vw, 56px);
align-items: center;
background: radial-gradient(circle at 30% 30%, #d8e8f0 0%, transparent 50%), radial-gradient(circle at 80% 70%, #e8eef2 0%, transparent 50%), #f8fafc;
font-family: 'Inter', system-ui, sans-serif;
color: #1a2840;
box-sizing: border-box;
}
.hs-21__stage {
position: relative;
height: 100%;
min-height: 320px;
display: grid;
place-items: center;
}
.hs-21__device {
width: 320px;
height: 200px;
background: linear-gradient(160deg, #b8c8d8 0%, #8090a8 50%, #607080 100%);
border-radius: 14px;
position: relative;
box-shadow: 0 22px 60px rgba(96,112,128,0.4), inset 0 1px 0 rgba(255,255,255,0.5), inset 0 -2px 0 rgba(0,0,0,0.18);
}
.hs-21__screen {
position: absolute;
inset: 8px;
background: linear-gradient(135deg, #1a2840 0%, #0a1428 100%);
border-radius: 7px;
box-shadow: inset 0 0 0 2px #0a1428;
}
.hs-21__cam {
position: absolute;
top: 4px;
left: 50%;
transform: translateX(-50%);
width: 5px;
height: 5px;
border-radius: 50%;
background: #1a2840;
}
.hs-21__pulse {
position: absolute;
background: #fff;
border: 1px solid #d0d8e0;
padding: 8px 12px;
border-radius: 999px;
font-size: 12.5px;
color: #1a2840;
display: inline-flex;
flex-direction: column;
gap: 1px;
box-shadow: 0 8px 22px rgba(96,112,128,0.18);
animation: hs-21-bob 4s ease-in-out infinite;
}
.hs-21__pulse strong {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
color: #6b85a5;
font-weight: 600;
letter-spacing: 0.04em;
}
.hs-21__p1 {
top: 10%;
left: 4%;
animation-delay: 0s;
}
.hs-21__p2 {
top: 35%;
right: 0;
animation-delay: -1.3s;
}
.hs-21__p3 {
bottom: 12%;
left: 12%;
animation-delay: -2.6s;
}
@keyframes hs-21-bob {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-6px);
}
}
.hs-21__copy {
padding: 12px 0;
}
.hs-21 h2 {
margin: 0 0 22px;
font-size: clamp(30px, 4.5vw, 48px);
font-weight: 700;
letter-spacing: -0.025em;
line-height: 1.05;
color: #1a2840;
}
.hs-21 h2 em {
background: linear-gradient(90deg, #6b85a5, #b8c8d8);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-style: italic;
font-weight: 800;
}
.hs-21__cta {
display: inline-block;
padding: 13px 24px;
background: #1a2840;
color: #f8fafc;
border-radius: 999px;
text-decoration: none;
font-weight: 600;
font-size: 14.5px;
transition: transform 0.15s;
}
.hs-21__cta:hover {
transform: translateY(-1px);
}
@media (max-width: 720px) {
.hs-21 {
grid-template-columns: 1fr;
}
}
@media (prefers-reduced-motion: reduce) {
.hs-21__pulse {
animation: none;
}
.hs-21__cta {
transition: none;
}
}Here's a working CSS Hero Section from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Product Shot Hero
Source: https://codefronts.com/layouts/css-hero-sections/product-shot-hero/
Apple-keynote product shot — a CSS-painted device front-and-centre with floating feature badges that pulse around it. Ice blue + chrome silver on warm white.
## HTML
```html
<section class="hs-21" aria-label="Hero">
<div class="hs-21__stage">
<div class="hs-21__device" aria-hidden="true">
<div class="hs-21__screen"></div>
<div class="hs-21__cam"></div>
</div>
<span class="hs-21__pulse hs-21__p1"><strong>· chip</strong>16-core neural</span>
<span class="hs-21__pulse hs-21__p2"><strong>· battery</strong>22 hours</span>
<span class="hs-21__pulse hs-21__p3"><strong>· weight</strong>1.24 kg</span>
</div>
<div class="hs-21__copy">
<h2>The lightest pro<br />laptop we've ever <em>shipped.</em></h2>
<a class="hs-21__cta" href="#buy">From $1,499 →</a>
</div>
</section>
```
## CSS
```css
.hs-21 {
display: grid;
grid-template-columns: 1.2fr 1fr;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 56px);
gap: clamp(24px, 4vw, 56px);
align-items: center;
background: radial-gradient(circle at 30% 30%, #d8e8f0 0%, transparent 50%), radial-gradient(circle at 80% 70%, #e8eef2 0%, transparent 50%), #f8fafc;
font-family: 'Inter', system-ui, sans-serif;
color: #1a2840;
box-sizing: border-box;
}
.hs-21__stage {
position: relative;
height: 100%;
min-height: 320px;
display: grid;
place-items: center;
}
.hs-21__device {
width: 320px;
height: 200px;
background: linear-gradient(160deg, #b8c8d8 0%, #8090a8 50%, #607080 100%);
border-radius: 14px;
position: relative;
box-shadow: 0 22px 60px rgba(96,112,128,0.4), inset 0 1px 0 rgba(255,255,255,0.5), inset 0 -2px 0 rgba(0,0,0,0.18);
}
.hs-21__screen {
position: absolute;
inset: 8px;
background: linear-gradient(135deg, #1a2840 0%, #0a1428 100%);
border-radius: 7px;
box-shadow: inset 0 0 0 2px #0a1428;
}
.hs-21__cam {
position: absolute;
top: 4px;
left: 50%;
transform: translateX(-50%);
width: 5px;
height: 5px;
border-radius: 50%;
background: #1a2840;
}
.hs-21__pulse {
position: absolute;
background: #fff;
border: 1px solid #d0d8e0;
padding: 8px 12px;
border-radius: 999px;
font-size: 12.5px;
color: #1a2840;
display: inline-flex;
flex-direction: column;
gap: 1px;
box-shadow: 0 8px 22px rgba(96,112,128,0.18);
animation: hs-21-bob 4s ease-in-out infinite;
}
.hs-21__pulse strong {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
color: #6b85a5;
font-weight: 600;
letter-spacing: 0.04em;
}
.hs-21__p1 {
top: 10%;
left: 4%;
animation-delay: 0s;
}
.hs-21__p2 {
top: 35%;
right: 0;
animation-delay: -1.3s;
}
.hs-21__p3 {
bottom: 12%;
left: 12%;
animation-delay: -2.6s;
}
@keyframes hs-21-bob {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-6px);
}
}
.hs-21__copy {
padding: 12px 0;
}
.hs-21 h2 {
margin: 0 0 22px;
font-size: clamp(30px, 4.5vw, 48px);
font-weight: 700;
letter-spacing: -0.025em;
line-height: 1.05;
color: #1a2840;
}
.hs-21 h2 em {
background: linear-gradient(90deg, #6b85a5, #b8c8d8);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-style: italic;
font-weight: 800;
}
.hs-21__cta {
display: inline-block;
padding: 13px 24px;
background: #1a2840;
color: #f8fafc;
border-radius: 999px;
text-decoration: none;
font-weight: 600;
font-size: 14.5px;
transition: transform 0.15s;
}
.hs-21__cta:hover {
transform: translateY(-1px);
}
@media (max-width: 720px) {
.hs-21 {
grid-template-columns: 1fr;
}
}
@media (prefers-reduced-motion: reduce) {
.hs-21__pulse {
animation: none;
}
.hs-21__cta {
transition: none;
}
}
```Here's a working CSS Hero Section from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Product Shot Hero
Source: https://codefronts.com/layouts/css-hero-sections/product-shot-hero/
Apple-keynote product shot — a CSS-painted device front-and-centre with floating feature badges that pulse around it. Ice blue + chrome silver on warm white.
## HTML
```html
<section class="hs-21" aria-label="Hero">
<div class="hs-21__stage">
<div class="hs-21__device" aria-hidden="true">
<div class="hs-21__screen"></div>
<div class="hs-21__cam"></div>
</div>
<span class="hs-21__pulse hs-21__p1"><strong>· chip</strong>16-core neural</span>
<span class="hs-21__pulse hs-21__p2"><strong>· battery</strong>22 hours</span>
<span class="hs-21__pulse hs-21__p3"><strong>· weight</strong>1.24 kg</span>
</div>
<div class="hs-21__copy">
<h2>The lightest pro<br />laptop we've ever <em>shipped.</em></h2>
<a class="hs-21__cta" href="#buy">From $1,499 →</a>
</div>
</section>
```
## CSS
```css
.hs-21 {
display: grid;
grid-template-columns: 1.2fr 1fr;
width: 100%;
min-height: 100vh;
padding: clamp(28px, 5vw, 56px);
gap: clamp(24px, 4vw, 56px);
align-items: center;
background: radial-gradient(circle at 30% 30%, #d8e8f0 0%, transparent 50%), radial-gradient(circle at 80% 70%, #e8eef2 0%, transparent 50%), #f8fafc;
font-family: 'Inter', system-ui, sans-serif;
color: #1a2840;
box-sizing: border-box;
}
.hs-21__stage {
position: relative;
height: 100%;
min-height: 320px;
display: grid;
place-items: center;
}
.hs-21__device {
width: 320px;
height: 200px;
background: linear-gradient(160deg, #b8c8d8 0%, #8090a8 50%, #607080 100%);
border-radius: 14px;
position: relative;
box-shadow: 0 22px 60px rgba(96,112,128,0.4), inset 0 1px 0 rgba(255,255,255,0.5), inset 0 -2px 0 rgba(0,0,0,0.18);
}
.hs-21__screen {
position: absolute;
inset: 8px;
background: linear-gradient(135deg, #1a2840 0%, #0a1428 100%);
border-radius: 7px;
box-shadow: inset 0 0 0 2px #0a1428;
}
.hs-21__cam {
position: absolute;
top: 4px;
left: 50%;
transform: translateX(-50%);
width: 5px;
height: 5px;
border-radius: 50%;
background: #1a2840;
}
.hs-21__pulse {
position: absolute;
background: #fff;
border: 1px solid #d0d8e0;
padding: 8px 12px;
border-radius: 999px;
font-size: 12.5px;
color: #1a2840;
display: inline-flex;
flex-direction: column;
gap: 1px;
box-shadow: 0 8px 22px rgba(96,112,128,0.18);
animation: hs-21-bob 4s ease-in-out infinite;
}
.hs-21__pulse strong {
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
color: #6b85a5;
font-weight: 600;
letter-spacing: 0.04em;
}
.hs-21__p1 {
top: 10%;
left: 4%;
animation-delay: 0s;
}
.hs-21__p2 {
top: 35%;
right: 0;
animation-delay: -1.3s;
}
.hs-21__p3 {
bottom: 12%;
left: 12%;
animation-delay: -2.6s;
}
@keyframes hs-21-bob {
0%,
100% {
transform: translateY(0);
}
50% {
transform: translateY(-6px);
}
}
.hs-21__copy {
padding: 12px 0;
}
.hs-21 h2 {
margin: 0 0 22px;
font-size: clamp(30px, 4.5vw, 48px);
font-weight: 700;
letter-spacing: -0.025em;
line-height: 1.05;
color: #1a2840;
}
.hs-21 h2 em {
background: linear-gradient(90deg, #6b85a5, #b8c8d8);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
font-style: italic;
font-weight: 800;
}
.hs-21__cta {
display: inline-block;
padding: 13px 24px;
background: #1a2840;
color: #f8fafc;
border-radius: 999px;
text-decoration: none;
font-weight: 600;
font-size: 14.5px;
transition: transform 0.15s;
}
.hs-21__cta:hover {
transform: translateY(-1px);
}
@media (max-width: 720px) {
.hs-21 {
grid-template-columns: 1fr;
}
}
@media (prefers-reduced-motion: reduce) {
.hs-21__pulse {
animation: none;
}
.hs-21__cta {
transition: none;
}
}
```How this works
The product hero section is a two-column CSS grid — grid-template-columns: 1.2fr 1fr — with the painted device stage on the left and the copy block on the right, collapsed to a single column below 720px for responsive hero section behaviour. The .hs-21__stage container uses position: relative plus display: grid; place-items: center so the CSS-painted laptop sits centred while the three .hs-21__pulse feature badges anchor absolutely at top: 10%; left: 4%, top: 35%; right: 0, and bottom: 12%; left: 12%. Each badge floats on a shared hs-21-bob keyframe (4s ease-in-out, translateY 0 → -6px → 0) with staggered animation-delay values of 0s, -1.3s, and -2.6s so no two badges peak together — the eye reads motion, not a synchronised bounce.
The palette is Apple-keynote chrome: two soft radial gradients (#d8e8f0 at 30% 30%, #e8eef2 at 80% 70%) painted over a warm-white #f8fafc base, so the stage feels lit rather than filled. The device body uses a diagonal linear-gradient #b8c8d8 → #8090a8 → #607080 with paired inset shadows (rgba(255,255,255,0.5) top, rgba(0,0,0,0.18) bottom) that fake brushed-aluminium bevel in pure CSS. Inter drives the sans-serif body; JetBrains Mono 10px labels the badge micro-copy in the exact tech-spec register buyers expect. The <em> in the h2 uses background-clip: text with a chrome gradient #6b85a5 → #b8c8d8 — the same visual language as a spec-page reveal.
Why it converts: object-forward product hero section framing triggers fusiform-recognition dwell, and NN-group eye-tracking shows above-the-fold dwell doubles when a rendered product replaces a stock lifestyle shot. The single pill CTA From $1,499 → puts price transparency in the hero — a Baymard-validated pattern for landing-page hero conversion rate optimization — while the three floating spec badges pre-answer the top objections (chip, battery, weight) before the fold breaks.
Make it yours
- Recolor to your brand by swapping four values: the warm-white base
#f8fafc, the two radial-gradient tints (#d8e8f0,#e8eef2), and the deep-navy accent#1a2840used on the h2, the CTA fill, and the screen. Keep the chrome gradient#b8c8d8 → #607080intact — that is the device. - Swap the device silhouette: change
.hs-21__devicewidth/height/border-radius to reshape it (420px × 260px, radius 20pxreads as a tablet;200px × 320px, radius 28pxreads as a phone;320px × 180px, radius 6pxreads as a hardware box). The chrome gradient carries any silhouette. - Change the CTA shape:
border-radius: 999pxis the Apple/keynote pill. Drop toborder-radius: 8pxfor a Stripe-style rectangle, or0for brutalist. If you switch to a rectangle, addbox-shadow: 0 2px 0 #0a1428so the button keeps visual weight — pills don't need it, rectangles do. - For dark mode: invert to
background: #0a1428with radial tints ofrgba(216,232,240,0.08)andrgba(232,238,242,0.06), flip body text to#f8fafc, and swap the CTA tobackground: #f8fafc; color: #0a1428. The chrome device gradient stays — brushed aluminium reads on either canvas. - For Tailwind:
bg-slate-50 grid grid-cols-[1.2fr_1fr] min-h-[480px]on the section,text-[#1a2840] text-5xl font-bold tracking-tight leading-[1.05]on the h2,bg-[#1a2840] text-slate-50 rounded-full px-6 py-3 hover:-translate-y-pxon the CTA. In React/Next, wrap the stage in a component and map the three badges from an array so you can A/B-test which specs earn the pulse.
Gotchas — read before shipping
- The three
hs-21-bobanimations run indefinitely ontransform: translateY, which is composited — but three infinite animations still keep the GPU awake. On battery-powered devices this shows up as a measurable idle-power draw. Consider pausing them viaIntersectionObserveronce the hero scrolls out of view, or gate them behind@media (min-width: 720px)so mobile skips the animation entirely for a cleaner INP profile. - The badge positions use percentage-based absolute placement inside
.hs-21__stage. If yourmin-height: 320pxis honoured but the stage grows taller than intended (a long h2 wraps and the grid row stretches), the badges drift off the device. Lock the stage height withheight: 320pxin production or the pulses lose their orbit. - The chrome
<em>uses-webkit-background-clip: text; color: transparent. In Windows High Contrast Mode the italicised word vanishes entirely — Forced Colors overridescolor: transparentto system foreground but the gradient stays, producing invisible text. Add@media (forced-colors: active) { .hs-21__h2 em { color: CanvasText; background: none; } }to keep WCAG 1.4.3 contrast intact. - The CTA hover uses
transform: translateY(-1px)— cheap and composited — but the0.15stransition duration is on the edge of WCAG 2.3.3 (Animation from Interactions). It's fine here because the movement is 1px, but if you scale it up to 3-4px, wrap it in@media (prefers-reduced-motion: no-preference)rather than only guarding the reduced case. - Watch CLS on the badges: they're painted with
font-size: 12.5pxand depend on Inter loading. If Inter arrives after first paint the badge widths reflow, and the shadow (0 8px 22px) causes visible layout thrash. Preload Inter with<link rel="preload" as="font" crossorigin>or setfont-display: optionalon the badge selector so system-ui holds the position. - In React/Vue/Next, be careful with SSR + the
animation-delay: -1.3snegative values. Some CSS-in-JS pipelines strip leading minus signs when serialising numeric-looking strings; verify the compiled output in devtools. If the delays are dropped, all three badges bob in unison and the hero looks like a bug, not a feature.