Как сделать плавный переход карусели?CSS

Разбираемся в CSS
Ответить
Anonymous
 Как сделать плавный переход карусели?

Сообщение Anonymous »

Я создаю карусель, которая показывает:
  • Центральную «активную» карточку
  • Вид слева и справа соседних карточек (обрезанных/замаскированных)
  • Кнопки «Предыдущий/следующий» + точки
Это работает функционально, но анимация не такая плавная, как карусель «Тысячи преобразованных предприятий» на этой странице. Как я могу имитировать такое поведение?

https://www.ramseysolutions.com/busines ... leadership
Сейчас мой JS заменяет внутренний HTML внутри слотов при каждой навигации. Это вызывает «щелканье»/дерганье, и я не могу добиться плавного скольжения/перехода между старой и новой картой. Я также иногда вижу краткий эффект «дополнительной карты ниже», если во время перехода существуют два элемента .ts-slot-inner.


Код: Выделить всё

function initCarousel(root) {
const articles = Array.from(root.querySelectorAll(".slides > article"));
const prevSlot = root.querySelector('[data-slot="prev"]');
const currSlot = root.querySelector('[data-slot="current"]');
const nextSlot = root.querySelector('[data-slot="next"]');
const prevBtn = root.querySelector("[data-prev]");
const nextBtn = root.querySelector("[data-next]");
const dotsWrap = root.querySelector("[data-dots]");

const slides = articles.map(a => ({
title: a.dataset.title || "Slide",
html: a.innerHTML
}));

const mod = (n, m) => ((n % m) + m) % m;

const wrapSlot = (html) => `${html}`;
const wrapPeek = (html) =>
`${html}`;

let index = 0;

function renderDots() {
dotsWrap.innerHTML = slides.map((s, i) => `

${s.title}

`).join("");

dotsWrap.querySelectorAll("[data-dot]").forEach(btn => {
btn.addEventListener("click", () => {
index = Number(btn.dataset.dot);
update();
});
});
}

function update() {
const prevIndex = mod(index - 1, slides.length);
const nextIndex = mod(index + 1, slides.length);

prevSlot.innerHTML = wrapPeek(slides[prevIndex].html);
currSlot.innerHTML = wrapSlot(slides[index].html);
nextSlot.innerHTML = wrapPeek(slides[nextIndex].html);

renderDots();
}

prevBtn.addEventListener("click", () => {
index = mod(index - 1, slides.length);
update();
});

nextBtn.addEventListener("click", () => {
index = mod(index + 1, slides.length);
update();
});

update();
}

document.querySelectorAll(".carousel").forEach(initCarousel);

Код: Выделить всё

.carousel-row {
display: grid;
grid-template-columns: 2fr 6fr 2fr;
gap: 16px;
align-items: stretch;
}

/* slots clip their contents */
.peek, .center {
position: relative;
overflow: hidden;
min-height: 1px;
}

/* if multiple inner wrappers exist, they should overlap */
.peek .slot-inner,
.center .slot-inner {
position: absolute;
inset: 0;
width: 100%;
}

/* keep first one in-flow to preserve height */
.peek > .slot-inner:first-child,
.center > .slot-inner:first-child {
position: relative;
}

/* side peek masks */
.peek-inner { width: 300%; }
.peek-left  .peek-inner { transform: translateX(-66.6667%); }
.peek-right .peek-inner { transform: translateX(0); }

.card {
background: white;
padding: 16px;
border-radius: 16px;
box-shadow: 0 0 8px rgba(0,0,0,.15);
text-align: center;
}

.card-green  { color: #2b6b45; }
.card-blue   { color: #3aa7c9; }
.card-yellow { color: #f1953a; }

.quote { font-size: 18px; line-height: 1.6;  }
.meta::before {
content: "";
display: block;
width: 180px;
height: 4px;
background: currentColor;
margin: 16px auto;
border-radius: 2px;
}

/* I *want* to animate between slides, but this currently doesn't work well */
.slot-inner {
transition: transform 0.9s ease, opacity 0.9s ease;
}

Код: Выделить всё






‹



›






“Generic quote text for slide one.”

Person One
Category A






“Generic quote text for slide two.”

Person Two
Category B






“Generic quote text for slide three.”

Person Three
Category C







Подробнее здесь: https://stackoverflow.com/questions/798 ... ion-smooth
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «CSS»