Files
homepage_relaunch/src/components/home/Hero.astro
T
2026-10-02 21:33:40 +02:00

93 lines
2.4 KiB
Plaintext

---
import { Picture } from 'astro:assets';
import background from '../../assets/images/background.png';
import { t, type Lang } from '../../i18n/ui';
interface Props { lang: Lang }
const { lang } = Astro.props;
const ui = t(lang);
---
<section class="hero night" aria-labelledby="hero-title">
<div class="hero__media">
<!-- Abstract and decorative, so it carries no alt text. -->
<Picture
src={background}
alt=""
quality={70}
formats={['avif']}
fallbackFormat="webp"
widths={[640, 960, 1440, 1920, 2400]}
sizes="100vw"
loading="eager"
fetchpriority="high"
decoding="async"
class="hero__img img-cover"
pictureAttributes={{ class: 'hero__picture' }}
/>
<div class="hero__overlay"></div>
</div>
<div class="container hero__content">
<h1 id="hero-title" class="display hero__title">
{ui.hero.lines.map((line, i) => (
<span class="hero__line" style={`--i: ${i}`}>{line}</span>
))}
</h1>
</div>
</section>
<style>
.hero {
position: relative;
display: flex;
align-items: flex-end;
/* Runs up under the floating header so the glass bar sits on the image, fills the screen,
and is never less than the headline needs. */
margin-top: calc(-1 * var(--header-height));
min-height: max(28rem, 100svh);
overflow: hidden;
}
.hero__media { position: absolute; inset: 0; }
:global(.hero__picture) { display: block; width: 100%; height: 100%; }
.hero__img,
:global(.hero__img) {
width: 100%;
height: 100%;
object-fit: cover;
object-position: 50% 50%;
transform-origin: 50% 60%;
animation: hero-settle var(--dur-hero) var(--ease) both;
}
.hero__overlay {
position: absolute;
inset: 0;
background: var(--overlay);
}
.hero__content {
position: relative;
width: 100%;
padding-block: var(--space-9);
}
.hero__title { max-width: 12em; }
.hero__line {
display: block;
opacity: 0;
animation: hero-rise 700ms var(--ease) forwards;
animation-delay: calc(240ms + var(--i) * 160ms);
}
@keyframes hero-settle {
from { transform: scale(1.045); }
to { transform: none; }
}
@keyframes hero-rise {
from { opacity: 0; transform: translateY(0.18em); }
to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
.hero__img, :global(.hero__img), .hero__line { animation: none; opacity: 1; transform: none; }
}
</style>