Hero Cover
A cover hero: a full-width picture under a monochrome veil with the title at the bottom left. The picture opens from the top edge and settles, the title lines rise. CSS only.
View codeA centred hero with an announcement pill, a headline whose lines rise out of their masks, one sentence and two pill buttons. CSS only, the entrance plays on load.
With your AI
Say it to your AI. It gets the exact code below, not its best guess, and knows where it goes.
Add the Kodza Hero Centered to my page.
claude mcp add -t http kodza https://kodza.dev/api/mcp
<section class="kodza-hero-centered">
<div class="kodza-hero-centered__inner">
<p class="kodza-hero-centered__news"><a class="kodza-hero-centered__badge" href="#"><span class="kodza-hero-centered__badge-label">v2 is out</span><span class="kodza-hero-centered__badge-more">See what changed</span><svg class="kodza-hero-centered__badge-arrow" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 8h10.5M9 3.5 13.5 8 9 12.5" /></svg></a></p>
<h1 class="kodza-hero-centered__title"><span class="kodza-hero-centered__line"><span class="kodza-hero-centered__rise">It's just HTML.</span></span> <span class="kodza-hero-centered__line"><span class="kodza-hero-centered__rise">That's the feature.</span></span></h1>
<p class="kodza-hero-centered__lead">Three pieces, zero dependencies. Paste it into the theme you already have, then deploy.</p>
<div class="kodza-hero-centered__actions">
<a class="kodza-hero-centered__button kodza-hero-centered__button--ink" href="#">Get the code<svg class="kodza-hero-centered__arrow" viewBox="0 0 16 16" aria-hidden="true"><path d="M2.5 8h10.5M9 3.5 13.5 8 9 12.5" /></svg></a>
<a class="kodza-hero-centered__button kodza-hero-centered__button--soft" href="#">See it live</a>
</div>
</div>
</section>
/* Kodza License: free to use, client work included. Not to resell or redistribute, ported or not: https://kodza.dev/docs/#print-license */
/* Kodza — Hero Centered
A centred hero: an announcement pill, a tight headline, one sentence and two pill buttons.
On load the pill and the title lines rise out of their masks, then the rest settles in.
CSS only. Everything is tuned with the --kz-hero-centered-* variables. */
.kodza-hero-centered {
--kz-hero-centered-ink: #0a0a0a;
--kz-hero-centered-paper: #f2f2f0;
--kz-hero-centered-dim: rgba(10, 10, 10, 0.62);
--kz-hero-centered-soft: rgba(10, 10, 10, 0.07);
--kz-hero-centered-bg: transparent;
--kz-hero-centered-width: 1040px;
--kz-hero-centered-pad-y: clamp(88px, 11vw, 168px);
--kz-hero-centered-gutter: clamp(16px, 4vw, 40px);
--kz-hero-centered-ease: cubic-bezier(0.22, 1, 0.36, 1);
--kz-hero-centered-glide: cubic-bezier(0.6, 0, 0.1, 1);
--kz-hero-centered-soft-ease: cubic-bezier(0.25, 1, 0.5, 1);
container: kodza-hero-centered / inline-size;
box-sizing: border-box;
width: 100%;
padding-block: var(--kz-hero-centered-pad-y);
padding-left: max(var(--kz-hero-centered-gutter), env(safe-area-inset-left, 0px));
padding-right: max(var(--kz-hero-centered-gutter), env(safe-area-inset-right, 0px));
background: var(--kz-hero-centered-bg);
color: var(--kz-hero-centered-ink);
text-align: center;
}
.kodza-hero-centered__inner {
max-width: var(--kz-hero-centered-width);
margin: 0 auto;
}
/* The pill's own mask, padded so the focus ring is never cut */
.kodza-hero-centered__news {
display: flex;
justify-content: center;
overflow: hidden;
margin: -6px 0 22px;
padding: 6px;
}
.kodza-hero-centered__badge {
display: inline-flex;
align-items: center;
gap: 10px;
box-sizing: border-box;
max-width: 100%;
height: 34px;
padding: 0 14px;
border-radius: 999px;
background: var(--kz-hero-centered-soft);
color: var(--kz-hero-centered-ink);
font-family: inherit;
font-size: 13.5px;
font-weight: 500;
line-height: 1;
white-space: nowrap;
text-decoration: none;
transition: background-color 0.25s var(--kz-hero-centered-ease);
}
.kodza-hero-centered__badge:focus-visible {
outline: 2px solid var(--kz-hero-centered-ink);
outline-offset: 3px;
}
/* A hairline between the news and its link */
.kodza-hero-centered__badge-more {
display: inline-flex;
align-items: center;
gap: 10px;
color: var(--kz-hero-centered-dim);
}
.kodza-hero-centered__badge-more::before {
content: "";
width: 1px;
height: 12px;
background: currentColor;
opacity: 0.45;
}
.kodza-hero-centered__badge-arrow {
flex: none;
width: 14px;
height: 14px;
margin-left: -2px;
fill: none;
stroke: currentColor;
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
transition: transform 0.3s var(--kz-hero-centered-ease);
}
.kodza-hero-centered__title {
margin: 0 0 26px;
font-size: clamp(42px, 7.4vw, 104px);
font-weight: 700;
line-height: 1;
letter-spacing: -0.05em;
color: var(--kz-hero-centered-ink);
}
/* Each line is its own mask: the words rise from behind its bottom edge */
.kodza-hero-centered__line {
display: block;
overflow: hidden;
padding-bottom: 0.08em;
margin-bottom: -0.08em;
text-wrap: balance;
}
.kodza-hero-centered__rise {
display: block;
}
.kodza-hero-centered__lead {
max-width: 34ch;
margin: 0 auto 36px;
font-size: clamp(17px, 1.45vw, 20px);
line-height: 1.55;
color: var(--kz-hero-centered-dim);
text-wrap: pretty;
}
.kodza-hero-centered__actions {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px;
}
.kodza-hero-centered__button {
position: relative;
isolation: isolate;
overflow: hidden;
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 10px;
height: 52px;
padding: 0 26px;
border: 0;
border-radius: 999px;
font-family: inherit;
font-size: 15px;
font-weight: 500;
line-height: 1;
white-space: nowrap;
text-decoration: none;
cursor: pointer;
}
.kodza-hero-centered__button:focus-visible {
outline: 2px solid var(--kz-hero-centered-ink);
outline-offset: 3px;
}
/* Solid: the arrow steps forward on hover */
.kodza-hero-centered__button--ink {
background: var(--kz-hero-centered-ink);
color: var(--kz-hero-centered-paper);
}
.kodza-hero-centered__arrow {
flex: none;
width: 16px;
height: 16px;
fill: none;
stroke: currentColor;
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
transition: transform 0.3s var(--kz-hero-centered-ease);
}
/* Soft: ink rises from the bottom edge on hover */
.kodza-hero-centered__button--soft {
background: var(--kz-hero-centered-soft);
color: var(--kz-hero-centered-ink);
transition: color 0.4s var(--kz-hero-centered-ease);
}
.kodza-hero-centered__button--soft::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
border-radius: inherit;
background: var(--kz-hero-centered-ink);
transform: translateY(101%);
transition: transform 0.4s var(--kz-hero-centered-ease);
}
@media (hover: hover) {
.kodza-hero-centered__badge:hover {
background: color-mix(in srgb, var(--kz-hero-centered-soft), var(--kz-hero-centered-ink) 5%);
}
.kodza-hero-centered__badge:hover .kodza-hero-centered__badge-arrow,
.kodza-hero-centered__button--ink:hover .kodza-hero-centered__arrow {
transform: translateX(3px);
}
.kodza-hero-centered__button--soft:hover {
color: var(--kz-hero-centered-paper);
}
.kodza-hero-centered__button--soft:hover::before {
transform: none;
}
}
/* Narrow: the link half of the pill goes, and the buttons share the row */
@container kodza-hero-centered (max-width: 420px) {
.kodza-hero-centered__badge-more {
display: none;
}
.kodza-hero-centered__button {
flex: 1 1 auto;
}
}
/* The entrance, on load: the pill, then the title lines one after the other, then the rest */
@media (prefers-reduced-motion: no-preference) {
.kodza-hero-centered__badge {
animation: kodza-hero-centered-pill 1000ms var(--kz-hero-centered-glide) both;
}
.kodza-hero-centered__rise {
animation: kodza-hero-centered-rise 1170ms var(--kz-hero-centered-glide) 110ms both;
}
.kodza-hero-centered__line:nth-child(2) .kodza-hero-centered__rise {
animation-delay: 235ms;
}
.kodza-hero-centered__line:nth-child(3) .kodza-hero-centered__rise {
animation-delay: 360ms;
}
.kodza-hero-centered__line:nth-child(4) .kodza-hero-centered__rise {
animation-delay: 485ms;
}
.kodza-hero-centered__lead {
animation: kodza-hero-centered-in 900ms var(--kz-hero-centered-soft-ease) 700ms both;
}
.kodza-hero-centered__actions {
animation: kodza-hero-centered-in 900ms var(--kz-hero-centered-soft-ease) 810ms both;
}
}
@keyframes kodza-hero-centered-pill {
from {
transform: translateY(calc(100% + 8px));
}
}
@keyframes kodza-hero-centered-rise {
from {
transform: translateY(105%);
}
}
@keyframes kodza-hero-centered-in {
from {
opacity: 0;
transform: translateY(20px);
}
}
@media (prefers-reduced-motion: reduce) {
.kodza-hero-centered *,
.kodza-hero-centered *::before,
.kodza-hero-centered *::after {
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
}
}
/* kodza-guard ec8354de1ebd — generated by Kodza, do not edit.
Theme guard: keeps a site's own CSS (WordPress themes, Bootstrap, CSS resets…) off this
component. :not(#_) is always true and weighs as much as an id, so these lines win over
theme rules made of classes and tags. Customise the component through its --kz-* variables. */
/* What the browser gives, where the component sets it only in some states: at the lowest weight, so its own rules below put it back */
:where(.kodza-hero-centered__news):not(#_),
:where(.kodza-hero-centered__title):not(#_),
:where(.kodza-hero-centered__lead):not(#_) {
transition-duration: revert;
}
:where(.kodza-hero-centered__badge):not(#_) {
outline: revert;
outline-offset: revert;
}
:where(.kodza-hero-centered__button):not(#_) {
outline: revert;
transition: revert;
outline-offset: revert;
}
/* What the browser gives, on everything the component leaves to it */
.kodza-hero-centered__inner:not(#_),
.kodza-hero-centered__badge-label:not(#_),
.kodza-hero-centered__badge-more:not(#_),
.kodza-hero-centered__line:not(#_),
.kodza-hero-centered__rise:not(#_),
.kodza-hero-centered__actions:not(#_) {
box-sizing: revert;
}
.kodza-hero-centered__news:not(#_) {
border: revert;
border-radius: revert;
outline: revert;
text-decoration: revert;
list-style: revert;
box-sizing: revert;
float: revert;
position: revert;
background-color: revert;
background-image: revert;
box-shadow: revert;
outline-offset: revert;
appearance: revert;
max-width: revert;
max-height: revert;
color: revert;
font-family: revert;
font-size: revert;
font-weight: revert;
font-style: revert;
line-height: revert;
letter-spacing: revert;
text-transform: revert;
text-underline-offset: revert;
text-align: revert;
text-indent: revert;
text-shadow: revert;
vertical-align: revert;
transition-property: revert;
transition-timing-function: revert;
transition-delay: revert;
}
.kodza-hero-centered__badge:not(#_) {
border: revert;
margin: revert;
list-style: revert;
float: revert;
position: revert;
box-shadow: revert;
appearance: revert;
max-height: revert;
font-style: revert;
letter-spacing: revert;
text-transform: revert;
text-underline-offset: revert;
text-align: revert;
text-indent: revert;
text-shadow: revert;
vertical-align: revert;
}
.kodza-hero-centered__badge-arrow:not(#_) {
border: revert;
padding: revert;
border-radius: revert;
outline: revert;
text-decoration: revert;
list-style: revert;
box-sizing: revert;
float: revert;
position: revert;
margin-top: revert;
margin-right: revert;
margin-bottom: revert;
background-color: revert;
background-image: revert;
box-shadow: revert;
outline-offset: revert;
appearance: revert;
max-width: revert;
max-height: revert;
color: revert;
font-family: revert;
font-size: revert;
font-weight: revert;
font-style: revert;
line-height: revert;
letter-spacing: revert;
text-transform: revert;
text-underline-offset: revert;
text-align: revert;
text-indent: revert;
text-shadow: revert;
vertical-align: revert;
}
.kodza-hero-centered__title:not(#_) {
border: revert;
padding: revert;
border-radius: revert;
outline: revert;
text-decoration: revert;
list-style: revert;
box-sizing: revert;
float: revert;
position: revert;
background-color: revert;
background-image: revert;
box-shadow: revert;
outline-offset: revert;
appearance: revert;
max-width: revert;
max-height: revert;
font-family: revert;
font-style: revert;
text-transform: revert;
text-underline-offset: revert;
text-align: revert;
text-indent: revert;
text-shadow: revert;
vertical-align: revert;
transition-property: revert;
transition-timing-function: revert;
transition-delay: revert;
}
.kodza-hero-centered__lead:not(#_) {
border: revert;
padding: revert;
border-radius: revert;
outline: revert;
text-decoration: revert;
list-style: revert;
box-sizing: revert;
float: revert;
position: revert;
background-color: revert;
background-image: revert;
box-shadow: revert;
outline-offset: revert;
appearance: revert;
max-height: revert;
font-family: revert;
font-weight: revert;
font-style: revert;
letter-spacing: revert;
text-transform: revert;
text-underline-offset: revert;
text-align: revert;
text-indent: revert;
text-shadow: revert;
vertical-align: revert;
transition-property: revert;
transition-timing-function: revert;
transition-delay: revert;
}
.kodza-hero-centered__button:not(#_) {
margin: revert;
list-style: revert;
float: revert;
box-shadow: revert;
appearance: revert;
max-width: revert;
max-height: revert;
font-style: revert;
letter-spacing: revert;
text-transform: revert;
text-underline-offset: revert;
text-align: revert;
text-indent: revert;
text-shadow: revert;
vertical-align: revert;
}
.kodza-hero-centered__arrow:not(#_) {
border: revert;
margin: revert;
padding: revert;
border-radius: revert;
outline: revert;
text-decoration: revert;
list-style: revert;
box-sizing: revert;
float: revert;
position: revert;
background-color: revert;
background-image: revert;
box-shadow: revert;
outline-offset: revert;
appearance: revert;
max-width: revert;
max-height: revert;
color: revert;
font-family: revert;
font-size: revert;
font-weight: revert;
font-style: revert;
line-height: revert;
letter-spacing: revert;
text-transform: revert;
text-underline-offset: revert;
text-align: revert;
text-indent: revert;
text-shadow: revert;
vertical-align: revert;
}
.kodza-hero-centered__badge-arrow:not(#_):where(:not([hidden])),
.kodza-hero-centered__title:not(#_):where(:not([hidden])),
.kodza-hero-centered__lead:not(#_):where(:not([hidden])),
.kodza-hero-centered__arrow:not(#_):where(:not([hidden])) {
display: revert;
}
.kodza-hero-centered__badge-arrow:not(#_):where([hidden]),
.kodza-hero-centered__title:not(#_):where([hidden]),
.kodza-hero-centered__lead:not(#_):where([hidden]),
.kodza-hero-centered__arrow:not(#_):where([hidden]) {
display: none;
}
.kodza-hero-centered__badge-more:not(#_)::before {
box-sizing: revert;
}
/* The component's own rules, one step stronger: real buttons and fields, what it sets on tags themes style (links, lists, headings, images…), and the root width (a theme may narrow it, never widen it) */
.kodza-hero-centered__news:not(#_) {
display: flex;
margin: -6px 0 22px;
padding: 6px;
}
.kodza-hero-centered__badge:not(#_) {
display: inline-flex;
box-sizing: border-box;
max-width: 100%;
padding: 0 14px;
border-radius: 999px;
background: var(--kz-hero-centered-soft);
color: var(--kz-hero-centered-ink);
font-family: inherit;
font-size: 13.5px;
font-weight: 500;
line-height: 1;
text-decoration: none;
transition: background-color 0.25s var(--kz-hero-centered-ease);
}
.kodza-hero-centered__badge:focus-visible:not(#_) {
outline: 2px solid var(--kz-hero-centered-ink);
outline-offset: 3px;
}
.kodza-hero-centered__badge-arrow:not(#_) {
margin-left: -2px;
transition: transform 0.3s var(--kz-hero-centered-ease);
}
.kodza-hero-centered__title:not(#_) {
margin: 0 0 26px;
font-size: clamp(42px, 7.4vw, 104px);
font-weight: 700;
line-height: 1;
letter-spacing: -0.05em;
color: var(--kz-hero-centered-ink);
}
.kodza-hero-centered__lead:not(#_) {
max-width: 34ch;
margin: 0 auto 36px;
font-size: clamp(17px, 1.45vw, 20px);
line-height: 1.55;
color: var(--kz-hero-centered-dim);
}
.kodza-hero-centered__button:not(#_) {
position: relative;
box-sizing: border-box;
display: inline-flex;
padding: 0 26px;
border: 0;
border-radius: 999px;
font-family: inherit;
font-size: 15px;
font-weight: 500;
line-height: 1;
text-decoration: none;
}
.kodza-hero-centered__button:focus-visible:not(#_) {
outline: 2px solid var(--kz-hero-centered-ink);
outline-offset: 3px;
}
.kodza-hero-centered__button--ink:not(#_) {
background: var(--kz-hero-centered-ink);
color: var(--kz-hero-centered-paper);
}
.kodza-hero-centered__arrow:not(#_) {
transition: transform 0.3s var(--kz-hero-centered-ease);
}
.kodza-hero-centered__button--soft:not(#_) {
background: var(--kz-hero-centered-soft);
color: var(--kz-hero-centered-ink);
transition: color 0.4s var(--kz-hero-centered-ease);
}
@media (hover: hover) {
.kodza-hero-centered__badge:hover:not(#_) {
background: color-mix(in srgb, var(--kz-hero-centered-soft), var(--kz-hero-centered-ink) 5%);
}
}
@media (hover: hover) {
.kodza-hero-centered__button--soft:hover:not(#_) {
color: var(--kz-hero-centered-paper);
}
}
@media (prefers-reduced-motion: reduce) {
.kodza-hero-centered *:where(p, a, svg, h1):not(#_) {
transition-duration: 0.01ms !important;
}
}
'use client';
// Kodza — Hero Centered, for React. From https://kodza.dev/components/hero-centered/
// Kodza License: free to use, client work included. Not to resell or redistribute, ported or not: https://kodza.dev/docs/#print-license
// Next to this file: hero-centered.css, the component's CSS from Kodza, as they are.
// Yours to edit: the markup is plain JSX below.
import { useRef, type ComponentPropsWithoutRef, type ComponentRef, type CSSProperties } from 'react';
import './hero-centered.css';
export type HeroCenteredProps = Omit<ComponentPropsWithoutRef<'section'>, "children" | "vars"> & {
/** Settings, as CSS variables on the root */
vars?: {
/** default: #0a0a0a */
"--kz-hero-centered-ink"?: string | number;
/** default: #f2f2f0 */
"--kz-hero-centered-paper"?: string | number;
/** default: rgba(10, 10, 10, 0.62) */
"--kz-hero-centered-dim"?: string | number;
/** default: rgba(10, 10, 10, 0.07) */
"--kz-hero-centered-soft"?: string | number;
/** default: transparent */
"--kz-hero-centered-bg"?: string | number;
/** default: 1040px */
"--kz-hero-centered-width"?: string | number;
/** default: clamp(88px, 11vw, 168px) */
"--kz-hero-centered-pad-y"?: string | number;
/** default: clamp(16px, 4vw, 40px) */
"--kz-hero-centered-gutter"?: string | number;
/** default: cubic-bezier(0.22, 1, 0.36, 1) */
"--kz-hero-centered-ease"?: string | number;
/** default: cubic-bezier(0.6, 0, 0.1, 1) */
"--kz-hero-centered-glide"?: string | number;
/** default: cubic-bezier(0.25, 1, 0.5, 1) */
"--kz-hero-centered-soft-ease"?: string | number;
};
className?: string;
};
export function HeroCentered({ vars, className, style, ...rest }: HeroCenteredProps) {
const ref = useRef<ComponentRef<'section'>>(null);
const classes = ["kodza-hero-centered", className].filter(Boolean).join(' ');
// Everything the markup is made of: when it changes, React gets a fresh element (see the top)
const key = JSON.stringify([classes, vars, style, rest]);
return (
<section key={key} {...rest} className={classes} style={{ ...vars, ...style } as CSSProperties} ref={ref}>
<div className="kodza-hero-centered__inner">
<p className="kodza-hero-centered__news">
<a className="kodza-hero-centered__badge" href="#">
<span className="kodza-hero-centered__badge-label">v2 is out</span>
<span className="kodza-hero-centered__badge-more">See what changed</span>
<svg className="kodza-hero-centered__badge-arrow" viewBox="0 0 16 16" aria-hidden="true">
<path d="M2.5 8h10.5M9 3.5 13.5 8 9 12.5" />
</svg>
</a>
</p>
<h1 className="kodza-hero-centered__title">
<span className="kodza-hero-centered__line">
<span className="kodza-hero-centered__rise">It's just HTML.</span>
</span>
{' '}
<span className="kodza-hero-centered__line">
<span className="kodza-hero-centered__rise">That's the feature.</span>
</span>
</h1>
<p className="kodza-hero-centered__lead">Three pieces, zero dependencies. Paste it into the theme you already have, then deploy.</p>
<div className="kodza-hero-centered__actions">
<a className="kodza-hero-centered__button kodza-hero-centered__button--ink" href="#">Get the code<svg className="kodza-hero-centered__arrow" viewBox="0 0 16 16" aria-hidden="true"> <path d="M2.5 8h10.5M9 3.5 13.5 8 9 12.5" /> </svg></a>
{' '}
<a className="kodza-hero-centered__button kodza-hero-centered__button--soft" href="#">See it live</a>
</div>
</div>
</section>
);
}
Checked
Robots poked at it before you did. Every component goes through the same checks, and again each time it changes.