Журнал Тильды
/
Библиотека промптов
/
5 карточек с эффектом поворота по наведению
5 карточек с эффектом поворота по наведению
Объёмная интерактивная галерея, которая привлекает внимание и заставляет провести больше времени на сайте.
Промпт
Вы можете скопировать промпт и вставить его в вайб блок в поле ввода. Подробнее в инструкции.
Создай интерактивную 3D-полку из 5 квадратных книг-проектов. Фон #08090b во всю ширину экрана, Arial/Helvetica, белый текст, подписи белые с opacity .5. Без общего заголовка, рамок, скруглений и теней под книгами.

Название | подпись | ссылка | обложка:
Soft Light | Project 1 | #book-1 | https://static.tildacdn.com/tild3464-6330-4137-a434-626638636261/11.png
Warm Wood | Project 2 | #book-2 | https://static.tildacdn.com/tild3034-3536-4034-a438-356161353438/12.png
Quiet Morning | Project 3 | #book-3 | https://static.tildacdn.com/tild3136-3131-4339-a531-326662363036/13.png
Textures | Project 4 | #book-4 | https://static.tildacdn.com/tild3932-3235-4466-b738-653636303339/14.png
Private Retreat | Project 5 | #book-5 | https://static.tildacdn.com/tild3138-6365-4238-b866-663935623763/15.png

≥768px: ряд flex по центру, gap 18px, padding 80px 32px 110px (до 1100px поля 20px). Сторона книги S=clamp(240px, 27vw, 440px), закрытые слоты 52−108px. Всё помещается без горизонтального скролла. Сцена SxS, margin-top:112px, perspective:1400px. Книга — CSS-параллелепипед из 6 граней, preserve-3d, backface-visibility:hidden, толщина .035S. Обложка object-fit:cover; задник #0d0e10, тёмный корешок с градиентным бликом, торцы #e9e3d6 с полосами страниц, низ затемнён.

Изначально книги почти ребром: rotateY(82deg), translateZ(-24px). Над каждой на top:22px текст по центру: название 16px/1.2 regular, подпись 11px, gap 4px.

Hover/фокус ссылки разворачивает книгу: слот расширяется до S, rotateY(10deg), translateZ(64px); остальные opacity .52. Поворот .78s, расширение и перемещение текста .72s, easing cubic-bezier(.16,1,.3,1). Активная книга наклоняется за мышью: Y ±8°, X ±5°. Затемнение обложки .28→.03. Снизу градиент чёрный .8→прозрачный, высота 46%. Текст плавно переезжает на обложку, по центру, 24px от низа: название bold clamp(22px, 2.2vw, 34px)/1.08, трекинг -.025em; подпись 12px, gap 6px. Текст не вращается с книгой. Уход из блока закрывает все.

≤767px: вертикальный список, gap 52px, padding 48px 20px 72px; S=min(78vw, 360px), толщина .04S, perspective:1050px, без margin-top. ≤420px: S=min(82vw, 330px), gap 44px, поля 16px. Текст внизу на обложке: название clamp(20px, 7vw, 28px) bold, подпись 12px. Без hover и затухания соседей. При скролле разворачивай каждую книгу: когда точка top+34% высоты сцены проходит от 92% до 50% высоты окна, progress=smoothstep(0…1), rotateY 82°→6°, translateZ -18px→36px, scale .96→1, затемнение .30→.03. Эффект обратимый.

Изолируй CSS/JS, используй rAF, пересчёт при resize, учти reduced-motion. Текст редактируется отдельно от ссылки.

Контент должен легко редактироваться в Тильде: все карточки, фото и тексты сразу в HTML, без генерации через JS, массивы, innerHTML или canvas. Фото — img с data-tilda-img="y", тексты — с data-tilda-edit="y". JS только для анимации и синхронизации декоративных фрагментов с главным img. В редакторе покажи главное фото и все обороты статично для выбора и замены контента; не перехватывай клики.
Скопировать промпт
Код
Вы можете скопировать код и вставить его в вайб блок в раздел код. Подробнее в инструкции.
<section class="vbs-root" aria-label="Book shelf">

<div class="vbs-books">

<article class="vbs-book" aria-label="Book 1">
<div class="vbs-book__copy" aria-label="Book information">
<p class="vbs-book__copy-title" data-tilda-edit="y">Soft Light</p>
<p class="vbs-book__copy-meta" data-tilda-edit="y">Project 1</p>
</div>

<a class="vbs-book__link" href="#book-1">
<div class="vbs-book__scene" aria-label="Book cover">
<div class="vbs-book__object">
<div class="vbs-book__face vbs-book__face--front">
<img class="vbs-book__cover" data-tilda-img="y" src="https://static.tildacdn.com/tild3464-6330-4137-a434-626638636261/11.png" alt="Dark moody forest at night, mist between tall trees">
<div class="vbs-book__shade" aria-hidden="true"></div>
</div>
<div class="vbs-book__face vbs-book__face--spine">
<div class="vbs-book__spine-light"></div>
</div>
<div class="vbs-book__face vbs-book__face--pages"></div>
<div class="vbs-book__face vbs-book__face--top"></div>
<div class="vbs-book__face vbs-book__face--bottom"></div>
<div class="vbs-book__face vbs-book__face--back"></div>
</div>
<div class="vbs-book__floor" aria-hidden="true"></div>
</div></a>
</article>

<article class="vbs-book" aria-label="Book 2">
<div class="vbs-book__copy" aria-label="Book information">
<p class="vbs-book__copy-title" data-tilda-edit="y">Warm Wood</p>
<p class="vbs-book__copy-meta" data-tilda-edit="y">Project 2</p>
</div>

<a class="vbs-book__link" href="#book-2">
<div class="vbs-book__scene" aria-label="Book cover">
<div class="vbs-book__object">
<div class="vbs-book__face vbs-book__face--front">
<img class="vbs-book__cover" data-tilda-img="y" src="https://static.tildacdn.com/tild3034-3536-4034-a438-356161353438/12.png" alt="Minimal urban architecture, clean geometric lines in monochrome">
<div class="vbs-book__shade" aria-hidden="true"></div>
</div>
<div class="vbs-book__face vbs-book__face--spine">
<div class="vbs-book__spine-light"></div>
</div>
<div class="vbs-book__face vbs-book__face--pages"></div>
<div class="vbs-book__face vbs-book__face--top"></div>
<div class="vbs-book__face vbs-book__face--bottom"></div>
<div class="vbs-book__face vbs-book__face--back"></div>
</div>
<div class="vbs-book__floor" aria-hidden="true"></div>
</div></a>
</article>

<article class="vbs-book" aria-label="Book 3">
<div class="vbs-book__copy" aria-label="Book information">
<p class="vbs-book__copy-title" data-tilda-edit="y">Quiet Morning</p>
<p class="vbs-book__copy-meta" data-tilda-edit="y">Project 3</p>
</div>

<a class="vbs-book__link" href="#book-3">



<div class="vbs-book__scene" aria-label="Book cover">
<div class="vbs-book__object">

<div class="vbs-book__face vbs-book__face--front">
<img class="vbs-book__cover" data-tilda-img="y" src="https://static.tildacdn.com/tild3136-3131-4339-a531-326662363036/13.png" alt="Vast travel landscape with distant horizon and warm golden light">

<div class="vbs-book__shade" aria-hidden="true"></div>
</div>

<div class="vbs-book__face vbs-book__face--spine">
<div class="vbs-book__spine-light"></div>
</div>

<div class="vbs-book__face vbs-book__face--pages"></div>
<div class="vbs-book__face vbs-book__face--top"></div>
<div class="vbs-book__face vbs-book__face--bottom"></div>
<div class="vbs-book__face vbs-book__face--back"></div>

</div>

<div class="vbs-book__floor" aria-hidden="true"></div>
</div>

</a>
</article>

<article class="vbs-book" aria-label="Book 4">
<div class="vbs-book__copy" aria-label="Book information">
<p class="vbs-book__copy-title" data-tilda-edit="y">Textures</p>
<p class="vbs-book__copy-meta" data-tilda-edit="y">Project 4</p>
</div>

<a class="vbs-book__link" href="#book-4">



<div class="vbs-book__scene" aria-label="Book cover">
<div class="vbs-book__object">

<div class="vbs-book__face vbs-book__face--front">
<img class="vbs-book__cover" data-tilda-img="y" src="https://static.tildacdn.com/tild3932-3235-4466-b738-653636303339/14.png" alt="City lights at night with deep blue tones">

<div class="vbs-book__shade" aria-hidden="true"></div>
</div>

<div class="vbs-book__face vbs-book__face--spine">
<div class="vbs-book__spine-light"></div>
</div>

<div class="vbs-book__face vbs-book__face--pages"></div>
<div class="vbs-book__face vbs-book__face--top"></div>
<div class="vbs-book__face vbs-book__face--bottom"></div>
<div class="vbs-book__face vbs-book__face--back"></div>

</div>

<div class="vbs-book__floor" aria-hidden="true"></div>
</div>

</a>
</article>

<article class="vbs-book" aria-label="Book 5">
<div class="vbs-book__copy" aria-label="Book information">
<p class="vbs-book__copy-title" data-tilda-edit="y">Private Retreat</p>
<p class="vbs-book__copy-meta" data-tilda-edit="y">Project 5</p>
</div>

<a class="vbs-book__link" href="#book-5">



<div class="vbs-book__scene" aria-label="Book cover">
<div class="vbs-book__object">

<div class="vbs-book__face vbs-book__face--front">
<img class="vbs-book__cover" data-tilda-img="y" src="https://static.tildacdn.com/tild3138-6365-4238-b866-663935623763/15.png" alt="Modern city architecture in atmospheric light">

<div class="vbs-book__shade" aria-hidden="true"></div>
</div>

<div class="vbs-book__face vbs-book__face--spine">
<div class="vbs-book__spine-light"></div>
</div>

<div class="vbs-book__face vbs-book__face--pages"></div>
<div class="vbs-book__face vbs-book__face--top"></div>
<div class="vbs-book__face vbs-book__face--bottom"></div>
<div class="vbs-book__face vbs-book__face--back"></div>

</div>

<div class="vbs-book__floor" aria-hidden="true"></div>
</div>

</a>
</article>

</div>

<style>
.vbs-root,
.vbs-root * {
box-sizing: border-box;
}

.vbs-root {
--vbs-bg: #08090b;
--vbs-text: #ffffff;
--vbs-muted: rgba(255,255,255,0.5);
--vbs-paper: #e9e3d6;

--vbs-card: clamp(300px, 30vw, 440px);
--vbs-depth: calc(var(--vbs-card) * 0.035);
--vbs-slot-rest: clamp(76px, 7vw, 108px);
--vbs-slot-open: var(--vbs-card);
--vbs-gap: clamp(18px, 2vw, 32px);
--vbs-rest-y: 82deg;
--vbs-open-y: 10deg;

position: relative;
width: 100vw;
max-width: none;
margin-left: calc(50% - 50vw);
overflow: hidden;
background: var(--vbs-bg);
color: var(--vbs-text);
font-family: Arial, Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
}

.vbs-books {
display: flex;
align-items: flex-start;
justify-content: center;
gap: var(--vbs-gap);
width: 100%;
padding: 80px 32px 110px;
}

.vbs-book {
position: relative;
flex: 0 0 var(--vbs-slot-rest);
width: var(--vbs-slot-rest);
transition:
flex-basis 0.72s cubic-bezier(0.16,1,0.3,1),
width 0.72s cubic-bezier(0.16,1,0.3,1),
opacity 0.35s ease;
}

.vbs-book.is-open {
flex-basis: var(--vbs-slot-open);
width: var(--vbs-slot-open);
}

.vbs-books.has-open .vbs-book:not(.is-open) {
opacity: 0.52;
}

.vbs-book__link {
position: relative;
display: block;
width: 100%;
color: inherit;
text-decoration: none;
}

.vbs-book__copy {
position: absolute;

z-index: 12;

top: 22px;
left: 50%;

display: flex;
flex-direction: column;
align-items: center;

gap: 4px;

width:
min(
220px,
var(--vbs-card)
);

transform:
translateX(-50%);

transform-origin:
center;

transition:
top
0.72s
cubic-bezier(0.16,1,0.3,1),

width
0.72s
cubic-bezier(0.16,1,0.3,1),

transform
0.72s
cubic-bezier(0.16,1,0.3,1);

pointer-events: auto;
}

.vbs-book__copy-title,
.vbs-book__copy-meta {
display: block;

width: 100%;

margin: 0;

text-align: center;

overflow-wrap: anywhere;

cursor: text;

user-select: text;
-webkit-user-select: text;

pointer-events: auto;
}

.vbs-book__copy-title {
font-size: 11px;
font-weight: 400;
line-height: 1.2;

color:
var(--vbs-text);
}

.vbs-book__copy-meta {
font-size: 11px;
line-height: 1.2;

color:
var(--vbs-muted);
}

.vbs-book.is-open
.vbs-book__copy {
top:
calc(
112px +
var(--vbs-card) -
24px
);

left: 50%;

align-items: center;

gap: 6px;

width:
calc(
var(--vbs-card) -
56px
);

transform:
translate(-50%,-100%);
}

.vbs-book.is-open
.vbs-book__copy-title,
.vbs-book.is-open
.vbs-book__copy-meta {
text-align: center;
}

.vbs-book.is-open
.vbs-book__copy-title {
font-size:
clamp(22px,2.2vw,34px);

font-weight: 700;

line-height: 1.08;

letter-spacing:
-0.025em;
}

.vbs-book.is-open
.vbs-book__copy-meta {
font-size: 12px;

line-height: 1.3;
}

.vbs-book__scene {
position: relative;
margin-top: 112px;
left: 50%;
width: var(--vbs-card);
height: var(--vbs-card);
margin-left: calc(var(--vbs-card) / -2);
perspective: 1400px;
pointer-events: none;
}

.vbs-book__object {
--vbs-rx: 0deg;
--vbs-ry: var(--vbs-rest-y);
position: absolute;
inset: 0;
transform-style: preserve-3d;
transform:
translateZ(-24px)
rotateX(var(--vbs-rx))
rotateY(var(--vbs-ry));
transform-origin: center;
transition: transform 0.78s cubic-bezier(0.16,1,0.3,1);
will-change: transform;
pointer-events: auto;
}

.vbs-book.is-open .vbs-book__object {
--vbs-ry: calc(var(--vbs-open-y) + var(--vbs-follow-y, 0deg));
--vbs-rx: var(--vbs-follow-x, 0deg);
transform:
translateZ(64px)
rotateX(var(--vbs-rx))
rotateY(var(--vbs-ry));
}

.vbs-book__face {
position: absolute;
top: 50%;
left: 50%;
overflow: hidden;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}

.vbs-book__face--front,
.vbs-book__face--back {
width: var(--vbs-card);
height: var(--vbs-card);
margin-top: calc(var(--vbs-card) / -2);
margin-left: calc(var(--vbs-card) / -2);
}

.vbs-book__face--front {
transform: translateZ(calc(var(--vbs-depth) / 2));
}

.vbs-book__face--back {
transform: rotateY(180deg) translateZ(calc(var(--vbs-depth) / 2));
background: #0d0e10;
}

.vbs-book__cover {
position: absolute;
inset: 0;
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
}

.vbs-book__shade {
position: absolute;
inset: 0;
background: #000;
opacity: 0.28;
pointer-events: none;
transition: opacity 0.55s ease;
}

.vbs-book.is-open .vbs-book__shade {
opacity: 0.03;
}

.vbs-book__face--spine {
width: var(--vbs-depth);
height: var(--vbs-card);
margin-top: calc(var(--vbs-card) / -2);
margin-left: calc(var(--vbs-depth) / -2);
transform: rotateY(-90deg) translateZ(calc(var(--vbs-card) / 2));
background: linear-gradient(to right, #0f1013, #34363b 38%, #17181c 70%, #090a0c);
}

.vbs-book__spine-light {
position: absolute;
inset: 0;
background: linear-gradient(to right, rgba(255,255,255,0.06), rgba(255,255,255,0.22) 35%, rgba(0,0,0,0.26));
pointer-events: none;
}

.vbs-book__face--pages {
width: var(--vbs-depth);
height: var(--vbs-card);
margin-top: calc(var(--vbs-card) / -2);
margin-left: calc(var(--vbs-depth) / -2);
transform: rotateY(90deg) translateZ(calc(var(--vbs-card) / 2));
background:
repeating-linear-gradient(to bottom, transparent 0, transparent 2px, rgba(0,0,0,0.07) 2px, rgba(0,0,0,0.07) 3px),
linear-gradient(to right, #d4cec0, var(--vbs-paper) 42%, #cdc9bc);
}

.vbs-book__face--top {
width: var(--vbs-card);
height: var(--vbs-depth);
margin-top: calc(var(--vbs-depth) / -2);
margin-left: calc(var(--vbs-card) / -2);
transform: rotateX(90deg) translateZ(calc(var(--vbs-card) / 2));
background:
repeating-linear-gradient(to right, transparent 0, transparent 2px, rgba(0,0,0,0.06) 2px, rgba(0,0,0,0.06) 3px),
linear-gradient(to bottom, #d4cec0, var(--vbs-paper));
}

.vbs-book__face--bottom {
width: var(--vbs-card);
height: var(--vbs-depth);
margin-top: calc(var(--vbs-depth) / -2);
margin-left: calc(var(--vbs-card) / -2);
transform: rotateX(-90deg) translateZ(calc(var(--vbs-card) / 2));
background: linear-gradient(to bottom, #b5b0a4, #a8a49a);
filter: brightness(0.58);
}

.vbs-book__face--front::after {
content: "";
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 46%;
background: linear-gradient(to top, rgba(0,0,0,0.80), transparent);
opacity: 0;
transition: opacity 0.48s ease 0.14s;
pointer-events: none;
}

.vbs-book.is-open .vbs-book__face--front::after {
opacity: 1;
}

.vbs-book__floor {
display: none !important;

position: absolute;
left: 50%;
bottom: -22px;
width: 92%;
height: 26px;
transform: translateX(-50%) scaleX(0.22);
transform-origin: center top;
background: radial-gradient(ellipse 80% 100% at 50% 0%, rgba(0,0,0,0.58), transparent);
opacity: 0.72;
transition:
transform 0.72s cubic-bezier(0.16,1,0.3,1),
opacity 0.35s ease;
pointer-events: none;
}

.vbs-book.is-open .vbs-book__floor {
transform: translateX(-50%) scaleX(0.92);
opacity: 0.9;
}

@media (max-width: 1100px) and (min-width: 768px) {
.vbs-root {
--vbs-card: min(38vw, 340px);
}

.vbs-books {
padding-left: 20px;
padding-right: 20px;
}
}

@media (max-width: 767px) {
.vbs-root {
--vbs-card: min(78vw, 360px);
--vbs-depth: calc(var(--vbs-card) * 0.04);
width: 100vw;
margin-left: calc(50% - 50vw);
}

.vbs-books {
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: 52px;
padding: 48px 20px 72px;
}

.vbs-book,
.vbs-book.is-open {
width: 100%;
flex: none;
opacity: 1;
}

.vbs-books.has-open .vbs-book:not(.is-open) {
opacity: 1;
}

.vbs-book__link {
width: 100%;
}

.vbs-book__copy,
.vbs-book.is-open
.vbs-book__copy {
top:
calc(
var(--vbs-card) -
24px
);

left: 50%;

align-items: center;

gap: 6px;

width:
calc(
var(--vbs-card) -
40px
);

transform:
translate(-50%,-100%);

transition: none;
}

.vbs-book__copy-title,
.vbs-book.is-open
.vbs-book__copy-title {
font-size:
clamp(20px,7vw,28px);

font-weight: 700;

line-height: 1.08;

letter-spacing:
-0.025em;

text-align: center;
}

.vbs-book__copy-meta,
.vbs-book.is-open
.vbs-book__copy-meta {
font-size: 12px;

line-height: 1.3;

text-align: center;
}

.vbs-book__scene {
left: auto;
width: var(--vbs-card);
height: var(--vbs-card);
margin: 0 auto;
perspective: 1050px;
overflow: visible;
pointer-events: auto;
}

.vbs-book__object,
.vbs-book.is-open .vbs-book__object {
--vbs-rx: 0deg;
--vbs-ry: 82deg;
transform:
translateZ(-18px)
rotateX(0deg)
rotateY(82deg)
scale(0.96);
transition: none;
}


.vbs-book__shade {
transition: none;
}

.vbs-book__floor {
transition: none;
}
}

@media (max-width: 420px) {
.vbs-root {
--vbs-card: min(82vw, 330px);
}

.vbs-books {
gap: 44px;
padding-left: 16px;
padding-right: 16px;
}

}

@media (prefers-reduced-motion: reduce) {
.vbs-book,
.vbs-book__object,
.vbs-book__copy,
.vbs-book__floor,
.vbs-book__face--front::after {
transition: none !important;
}
}
</style>

<script>
(function () {
'use strict';

var root = document.currentScript.closest('.vbs-root');
if (!root) return;

var booksWrap = root.querySelector('.vbs-books');
if (!booksWrap) return;

var mobileQuery = window.matchMedia('(max-width: 767px)');
var reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)');

var activeBook = null;
var mobileFrame = null;
var layoutFrame = null;

function getBooks() {
return Array.prototype.slice.call(
booksWrap.querySelectorAll('.vbs-book')
);
}

function clamp(value, min, max) {
return Math.max(min, Math.min(max, value));
}

function smoothStep(value) {
return value * value * (3 - 2 * value);
}

function updateAdaptiveLayout() {
layoutFrame = null;

if (mobileQuery.matches) {
root.style.removeProperty('--vbs-card');
root.style.removeProperty('--vbs-slot-rest');
root.style.removeProperty('--vbs-gap');
return;
}

var books = getBooks();
var count = books.length;

if (!count) {
root.style.removeProperty('--vbs-card');
root.style.removeProperty('--vbs-slot-rest');
root.style.removeProperty('--vbs-gap');
return;
}

var wrapStyle = getComputedStyle(booksWrap);
var width = booksWrap.clientWidth || root.clientWidth || window.innerWidth;
var paddingLeft = parseFloat(wrapStyle.paddingLeft) || 0;
var paddingRight = parseFloat(wrapStyle.paddingRight) || 0;

var gap;

if (count <= 4) {
gap = clamp(width * 0.02, 18, 32);
} else if (count <= 6) {
gap = 18;
} else if (count <= 8) {
gap = 12;
} else {
gap = 8;
}

var available = Math.max(
180,
width -
paddingLeft -
paddingRight -
gap * Math.max(0, count - 1)
);

var preferredCardFactor;

if (count <= 3) {
preferredCardFactor = 0.30;
} else if (count <= 5) {
preferredCardFactor = 0.27;
} else {
preferredCardFactor = 0.24;
}

var preferredCard = Math.min(
440,
Math.max(240, width * preferredCardFactor)
);

var card;
var rest;

if (count === 1) {
card = Math.min(440, Math.max(260, available * 0.78));
rest = Math.min(108, Math.max(72, card * 0.24));
} else {
rest = (available - preferredCard) / (count - 1);
rest = Math.min(108, rest);

var minRest = count <= 6 ? 52 : 30;

if (rest < minRest) {
rest = minRest;
}

card = available - rest * (count - 1);

if (card > preferredCard) {
card = preferredCard;
}

if (card < 200) {
card = Math.max(170, card);

rest = Math.max(
22,
(available - card) / (count - 1)
);
}
}

root.style.setProperty('--vbs-card', card.toFixed(2) + 'px');
root.style.setProperty('--vbs-slot-rest', rest.toFixed(2) + 'px');
root.style.setProperty('--vbs-gap', gap.toFixed(2) + 'px');
}

function requestAdaptiveLayout() {
if (layoutFrame) return;

layoutFrame = requestAnimationFrame(
updateAdaptiveLayout
);
}

function clearPointerTilt(book) {
if (!book) return;

var object = book.querySelector('.vbs-book__object');
if (!object) return;

object.style.removeProperty('--vbs-follow-x');
object.style.removeProperty('--vbs-follow-y');
}

function closeDesktopBooks() {
getBooks().forEach(function (book) {
book.classList.remove('is-open');
clearPointerTilt(book);
});

booksWrap.classList.remove('has-open');
activeBook = null;
}

function openDesktopBook(book) {
if (
!book ||
mobileQuery.matches ||
reduceMotion.matches
) {
return;
}

if (activeBook && activeBook !== book) {
activeBook.classList.remove('is-open');
clearPointerTilt(activeBook);
}

activeBook = book;
book.classList.add('is-open');
booksWrap.classList.add('has-open');
}

var editorMode = false;

try {
editorMode = window.self !== window.top;
}
catch (error) {
editorMode = true;
}

booksWrap.addEventListener('click', function (event) {
if (
editorMode &&
event.target.closest &&
event.target.closest(
'[data-tilda-img="y"]'
)
) {
event.preventDefault();
}
}, true);

booksWrap.addEventListener('mouseover', function (event) {
if (mobileQuery.matches) return;

if (
editorMode &&
event.target.closest &&
event.target.closest('[data-tilda-edit="y"]')
) {
return;
}

var book = event.target.closest('.vbs-book');
if (!book || !booksWrap.contains(book)) return;

if (
event.relatedTarget &&
book.contains(event.relatedTarget)
) {
return;
}

openDesktopBook(book);
});

booksWrap.addEventListener('focusin', function (event) {
var book = event.target.closest('.vbs-book');

if (book && booksWrap.contains(book)) {
openDesktopBook(book);
}
});

booksWrap.addEventListener('mousemove', function (event) {
if (
mobileQuery.matches ||
reduceMotion.matches ||
!activeBook
) {
return;
}

if (!activeBook.contains(event.target)) return;

var object = activeBook.querySelector('.vbs-book__object');
if (!object) return;

var rect = object.getBoundingClientRect();
if (!rect.width || !rect.height) return;

var x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
var y = ((event.clientY - rect.top) / rect.height) * 2 - 1;

x = clamp(x, -1, 1);
y = clamp(y, -1, 1);

object.style.setProperty(
'--vbs-follow-y',
(x * 8).toFixed(2) + 'deg'
);

object.style.setProperty(
'--vbs-follow-x',
(-y * 5).toFixed(2) + 'deg'
);
});

root.addEventListener('mouseleave', function () {
if (!mobileQuery.matches) {
closeDesktopBooks();
}
});

root.addEventListener('focusout', function (event) {
if (!root.contains(event.relatedTarget)) {
closeDesktopBooks();
}
});

function clearMobileStyles(book) {
var object = book.querySelector('.vbs-book__object');
var shade = book.querySelector('.vbs-book__shade');
var floor = book.querySelector('.vbs-book__floor');

if (object) object.style.transform = '';


if (shade) {
shade.style.opacity = '';
}

if (floor) {
floor.style.transform = '';
floor.style.opacity = '';
}
}

function updateMobileBooks() {
mobileFrame = null;

if (
!mobileQuery.matches ||
reduceMotion.matches
) {
return;
}

var books = getBooks();

var viewportHeight =
window.innerHeight ||
document.documentElement.clientHeight;

var startY = viewportHeight * 0.92;
var endY = viewportHeight * 0.50;

books.forEach(function (book) {
var scene = book.querySelector('.vbs-book__scene');
var object = book.querySelector('.vbs-book__object');
var shade = book.querySelector('.vbs-book__shade');
var floor = book.querySelector('.vbs-book__floor');

if (!scene || !object) return;

var rect = scene.getBoundingClientRect();
var anchorY = rect.top + rect.height * 0.34;
var raw = (startY - anchorY) / (startY - endY);
var progress = smoothStep(clamp(raw, 0, 1));

var angleY = 82 - progress * 76;
var translateZ = -18 + progress * 54;
var scale = 0.96 + progress * 0.04;
var floorScale = 0.18 + progress * 0.76;
var floorOpacity = 0.48 + progress * 0.42;
var shadeOpacity = 0.30 - progress * 0.27;


object.style.transform =
'translateZ(' + translateZ.toFixed(2) + 'px) ' +
'rotateX(0deg) ' +
'rotateY(' + angleY.toFixed(2) + 'deg) ' +
'scale(' + scale.toFixed(4) + ')';


if (shade) {
shade.style.opacity =
shadeOpacity.toFixed(3);
}

if (floor) {
floor.style.transform =
'translateX(-50%) scaleX(' +
floorScale.toFixed(3) +
')';

floor.style.opacity =
floorOpacity.toFixed(3);
}
});
}

function requestMobileUpdate() {
if (
!mobileQuery.matches ||
reduceMotion.matches ||
mobileFrame
) {
return;
}

mobileFrame =
requestAnimationFrame(
updateMobileBooks
);
}

function setMode() {
closeDesktopBooks();

getBooks().forEach(function (book) {
clearMobileStyles(book);
});

updateAdaptiveLayout();

if (mobileQuery.matches) {
updateMobileBooks();
}
}

window.addEventListener(
'scroll',
requestMobileUpdate,
{ passive: true }
);

window.addEventListener(
'resize',
function () {
requestAdaptiveLayout();
requestMobileUpdate();
},
{ passive: true }
);

if (mobileQuery.addEventListener) {
mobileQuery.addEventListener(
'change',
setMode
);
}
else if (mobileQuery.addListener) {
mobileQuery.addListener(setMode);
}

if (reduceMotion.addEventListener) {
reduceMotion.addEventListener(
'change',
setMode
);
}
else if (reduceMotion.addListener) {
reduceMotion.addListener(setMode);
}

if ('MutationObserver' in window) {
var observer = new MutationObserver(function (mutations) {
var structureChanged = mutations.some(function (mutation) {
return mutation.type === 'childList';
});

if (!structureChanged) return;

if (
activeBook &&
!root.contains(activeBook)
) {
activeBook = null;
booksWrap.classList.remove('has-open');
}

requestAdaptiveLayout();
requestMobileUpdate();
});

observer.observe(booksWrap, {
childList: true,
subtree: false
});
}

setMode();

})();
</script>

</section><style data-vb-overrides="true">
.vbs-book__copy-title {
font-size: 16px;
}
</style>
Скопировать код
Что выбрать, промпт или код?
Копируйте промпт, если хотите получить похожий результат, но ввести информацию о своём бизнесе и задать свои требования. Например, изменить кнопки, тексты, цвета, фотографии или другие элементы.
Копируйте код, если хотите получить точно такой же блок. Чтобы его изменить, придётся отредактировать html-код.
Начните создание сайта на Тильде с простой регистрации на платформе
Made on
Tilda