feat(hero): fade-in hero после готовности фона-шэйдера

- .hero стартует скрытым, проявляется при html.mesh-bg-ready
- markMeshReady ставится во всех ветках (успех/ошибка/reduced-motion/нет хоста)
- reduced-motion: hero виден сразу без анимации
This commit is contained in:
root committed 2026-09-24 21:42:41 +02:00
1 parent daa623fe73
commit 6d064e53b9
2 files changed
+32 -3

No files matched your search

+21
View File
@@ -1349,6 +1349,27 @@ a.fab--secondary:visited {
padding: calc(2 * clamp(2.5rem, 6vw, 4.5rem)) calc(2 * max(var(--space), env(safe-area-inset-right, 0px))) calc(2 * clamp(2rem, 5vw, 3.5rem)) calc(2 * max(var(--space), env(safe-area-inset-left, 0px)));
}
/* Hero проявляется только после готовности фона-шэйдера (html.mesh-bg-ready),
чтобы текст не вскакивал раньше, чем подгрузится живой фон. */
.hero {
opacity: 0;
transform: translateY(14px);
transition: opacity 0.8s ease 0.2s, transform 0.8s ease 0.2s;
}
html.mesh-bg-ready .hero {
opacity: 1;
transform: none;
}
@media (prefers-reduced-motion: reduce) {
.hero {
opacity: 1;
transform: none;
transition: none;
}
}
.hero__grid {
max-width: var(--max);
margin: 0 auto;
+11 -3
View File
@@ -42,8 +42,8 @@ function colorVec4Array(colors) {
export function initPageMeshShader() {
const host = document.querySelector(".page-mesh-bg");
if (!host) return;
if (prefersReducedMotion()) return; // статичный CSS-fallback остаётся виден
if (!host) return markMeshReady(); // нет хоста — hero всё равно проявляем
if (prefersReducedMotion()) return markMeshReady(); // статичный CSS-fallback, hero сразу виден
const sizing = () => ({
u_fit: ShaderFitOptions[defaultObjectSizing.fit],
@@ -86,10 +86,12 @@ export function initPageMeshShader() {
try { mount.intersectionObserver?.disconnect(); } catch {}
// Первый кадр уже отрисован в конструкторе — отмечаем готовность,
// чтобы CSS плавно проявил canvas (fade-in), без рывка.
// чтобы CSS плавно проявил canvas (fade-in) и hero.
host.classList.add("is-ready");
markMeshReady();
} catch (e) {
console.warn("Mesh shader mount failed, fallback to static bg", e);
markMeshReady();
return;
}
@@ -110,3 +112,9 @@ export function initPageMeshShader() {
try { mount.dispose(); } catch {}
}, { once: true });
}
// Сигнал готовности фона: проявляем hero (см. .hero в main.css).
// Ставится во всех ветках инициализации, чтобы hero никогда не висел скрытым.
function markMeshReady() {
document.documentElement.classList.add("mesh-bg-ready");
}