fix(mobile): hero — картинка как фон секции, текст поверх
- HeroImage: на мобилке картинка позиционируется фоном за текстом, opacity 0.45 - Сильный mask-gradient к левому-нижнему углу, чтобы заголовок читался - Софт-вуаль поверх фона (background var(--bg) с убывающей прозрачностью) - Секция hero: min-h-[88vh] на мобиле, текст по центру по вертикали - В тёмной теме мобильная opacity ещё ниже (0.32) - Десктоп без изменений
This commit is contained in:
+2
-2
@@ -31,9 +31,9 @@ export default async function HomePage() {
|
|||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
{/* Hero */}
|
{/* Hero */}
|
||||||
<section className="relative overflow-hidden">
|
<section className="relative overflow-hidden min-h-[88vh] sm:min-h-0 flex items-center sm:block">
|
||||||
<HeroImage />
|
<HeroImage />
|
||||||
<div className="container-wide pt-8 pb-12 sm:pt-20 sm:pb-24 lg:pt-28 lg:pb-32 relative">
|
<div className="container-wide pt-6 pb-10 sm:pt-20 sm:pb-24 lg:pt-28 lg:pb-32 relative z-10 w-full">
|
||||||
<Reveal>
|
<Reveal>
|
||||||
<div className="max-w-xl lg:max-w-2xl reveal">
|
<div className="max-w-xl lg:max-w-2xl reveal">
|
||||||
<div
|
<div
|
||||||
|
|||||||
+44
-26
@@ -2,8 +2,9 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hero иллюстрация с лёгким parallax при скролле + плавный fade с левого края,
|
* Hero иллюстрация — фон секции. Поверх неё рендерится текст.
|
||||||
* чтобы картинка органично «вытаивала» в фон под текстом.
|
* Desktop: справа, fade к центру, parallax при скролле.
|
||||||
|
* Mobile: фон ВО ВСЮ секцию, текст поверх с дополнительным фейдом.
|
||||||
*/
|
*/
|
||||||
export default function HeroImage() {
|
export default function HeroImage() {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
@@ -15,7 +16,6 @@ export default function HeroImage() {
|
|||||||
cancelAnimationFrame(raf);
|
cancelAnimationFrame(raf);
|
||||||
raf = requestAnimationFrame(() => {
|
raf = requestAnimationFrame(() => {
|
||||||
const y = window.scrollY;
|
const y = window.scrollY;
|
||||||
// едет вверх медленнее, чем страница
|
|
||||||
const offset = Math.min(60, y * 0.15);
|
const offset = Math.min(60, y * 0.15);
|
||||||
if (ref.current) ref.current.style.transform = `translateY(-${offset}px)`;
|
if (ref.current) ref.current.style.transform = `translateY(-${offset}px)`;
|
||||||
});
|
});
|
||||||
@@ -29,7 +29,7 @@ export default function HeroImage() {
|
|||||||
<picture>
|
<picture>
|
||||||
<source
|
<source
|
||||||
srcSet="/uploads/hero-1920.webp 1920w, /uploads/hero-1280.webp 1280w, /uploads/hero-800.webp 800w"
|
srcSet="/uploads/hero-1920.webp 1920w, /uploads/hero-1280.webp 1280w, /uploads/hero-800.webp 800w"
|
||||||
sizes="(min-width: 1024px) 65vw, 100vw"
|
sizes="(min-width: 768px) 70vw, 100vw"
|
||||||
type="image/webp"
|
type="image/webp"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
@@ -46,11 +46,10 @@ export default function HeroImage() {
|
|||||||
<style jsx>{`
|
<style jsx>{`
|
||||||
.hero-image-wrap {
|
.hero-image-wrap {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0; right: 0; bottom: 0;
|
inset: 0;
|
||||||
width: 100%;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
z-index: -1;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
.hero-image {
|
.hero-image {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -63,8 +62,6 @@ export default function HeroImage() {
|
|||||||
object-position: right top;
|
object-position: right top;
|
||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
transition: opacity 0.4s ease;
|
|
||||||
/* плавный фейд от центра к левому краю — картинка тает */
|
|
||||||
-webkit-mask-image: linear-gradient(
|
-webkit-mask-image: linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
transparent 0%,
|
transparent 0%,
|
||||||
@@ -93,27 +90,48 @@ export default function HeroImage() {
|
|||||||
background: linear-gradient(to bottom, transparent, rgb(var(--bg)));
|
background: linear-gradient(to bottom, transparent, rgb(var(--bg)));
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
/* На мобилке картинка сверху, под ней — текст */
|
|
||||||
|
/* === MOBILE: картинка фоном, текст поверх === */
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
.hero-image-wrap {
|
|
||||||
position: relative;
|
|
||||||
width: 100vw;
|
|
||||||
margin-left: -1rem;
|
|
||||||
margin-right: -1rem;
|
|
||||||
height: 240px;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
.hero-image {
|
.hero-image {
|
||||||
top: 0;
|
top: -20px;
|
||||||
right: 0;
|
right: -30%; /* выезжает за правый край — видна только часть */
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: auto;
|
||||||
object-position: right center;
|
max-width: 160%;
|
||||||
opacity: 0.95;
|
opacity: 0.45; /* приглушаем, чтобы текст читался */
|
||||||
-webkit-mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
|
-webkit-mask-image: linear-gradient(
|
||||||
mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
|
to bottom right,
|
||||||
|
transparent 0%,
|
||||||
|
rgba(0,0,0,0.15) 30%,
|
||||||
|
rgba(0,0,0,0.6) 60%,
|
||||||
|
black 100%
|
||||||
|
);
|
||||||
|
mask-image: linear-gradient(
|
||||||
|
to bottom right,
|
||||||
|
transparent 0%,
|
||||||
|
rgba(0,0,0,0.15) 30%,
|
||||||
|
rgba(0,0,0,0.6) 60%,
|
||||||
|
black 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
:global(.dark) .hero-image {
|
||||||
|
opacity: 0.32;
|
||||||
|
}
|
||||||
|
/* софт-вуаль для контраста заголовка */
|
||||||
|
.hero-image-wrap::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: linear-gradient(
|
||||||
|
to bottom,
|
||||||
|
rgb(var(--bg) / 0.4) 0%,
|
||||||
|
rgb(var(--bg) / 0.2) 40%,
|
||||||
|
rgb(var(--bg)) 100%
|
||||||
|
);
|
||||||
|
z-index: 1;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
.hero-image-wrap::after { display: none; }
|
|
||||||
}
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user