award-flip-images
Галерея·Шаблон: Davies - Personal Portfolio HTML Template·Складність анімації: heavy·Адаптивний: Так

Файли-джерела
- index.html
section.section-award
Бібліотеки
gsapscrolltriggerswiper
Summary
The Award section opens with a vertical award-count swiper (Behance x28, Awwwards x41, CSS Design Awards x67) cycling on autoplay. Below it, six photos start stacked at the parent's centre, then a GSAP timeline first lifts them to centre and then fans them out along an arc with per-index x/y offsets, rotation, rotateX and rotateY for a faux-3D shuffle.
HTML structure (minimal)
<section class="section-award flat-spacing">
<div class="container">
<div class="row">
<div class="col-md-5 ms-auto">
<div class="col-right">
<h6 class="mini-title text-caption text-white-64">AWARDS</h6>
<h5 class="text-color-change">Since 2020, my work has been honored…</h5>
</div>
</div>
</div>
<div class="row">
<div class="col-md-5">
<p class="desc text-white-64 mini-title">157 industry awards.<br>Bold ideas. Flawless execution.</p>
<div dir="ltr" class="swiper tf-swiper" data-preview="3" data-loop="true" data-auto="true" data-delay="1000" data-direction="vertical" data-space="4">
<div class="swiper-wrapper">
<div class="swiper-slide"><div class="award-item h4">Behance <span class="text-body-1">x28</span></div></div>
<div class="swiper-slide"><div class="award-item h4">Awwwards <span class="text-body-1">x41</span></div></div>
<!-- … -->
</div>
</div>
</div>
</div>
</div>
<div class="wrap-flip-image flat-spacing">
<div class="container">
<div class="flip-image-list gsap-anime-2">
<div class="flip-image"><img src="assets/images/section/award-1.jpg" alt=""></div>
<div class="flip-image"><img src="assets/images/section/award-2.jpg" alt=""></div>
<!-- 6 total -->
</div>
</div>
</div>
</section>
Key SCSS tokens
.flip-image-list {
position: relative;
height: 360px;
perspective: 1200px;
}
.flip-image {
width: 325px;
height: 325px;
border-radius: 12px;
overflow: hidden;
opacity: 0;
img { width: 100%; height: 100%; object-fit: cover; }
}
Animation logic
// assets/js/gsapAnimation.js — gsapA2()
const cards = document.querySelectorAll('.flip-image');
function animate() {
const isMobile = window.innerWidth < 767;
const cardW = isMobile ? 150 : 325;
const parent = cards[0].parentElement;
const centerX = parent.clientWidth / 2 - cardW / 2;
const centerY = parent.clientHeight / 2 - cardW / 2;
cards.forEach((card, i) => { card.style.position = 'absolute'; card.style.zIndex = i + 1; });
const tl = gsap.timeline({
defaults: { ease: 'power3.out' },
scrollTrigger: { trigger: '.gsap-anime-2', start: 'top 80%', toggleActions: 'play none none reverse' },
});
tl.to(cards, { x: centerX, y: centerY, opacity: 1, duration: 1, stagger: 0.1 })
.to(cards, {
x: (i) => centerX + [-400, -240, -80, 80, 240, 400][i],
y: (i) => centerY + [-300, -180, -60, 60, 180, 300][i],
rotation: -10,
rotateX: 4,
rotateY: 10,
duration: 1,
ease: 'power2.out',
delay: 0.3,
});
}
animate();
window.addEventListener('resize', () => { gsap.killTweensOf('.flip-image'); animate(); });
Notable details
- Two-stage timeline: gather to centre, then explode in an arc — the second tween's per-index values give the cards a subtle physical "fan" instead of a uniform spread.
rotateX: 4, rotateY: 10plus the parent'sperspective: 1200pxgive a faux-3D shuffle without actually doing CSS 3D layout.- Function-based tween values let one timeline drive different per-index destinations without unrolling six tweens.
- Resize handler kills tweens and re-runs
animate()— preventing stuck offsets if the user resizes mid-animation.
Use when
- Award walls, image showcases, or "deck of cards" reveals where the cards should fan from a stack as the user scrolls.
- Galleries with a fixed small count (4–8) where per-index positioning is acceptable.
Caveats
- The exploded positions are hardcoded for six cards — adding or removing cards requires editing the offset arrays.
parent.style.position = 'relative'is set imperatively — works but mutates DOM style; consider doing this in CSS.- ScrollTrigger relies on the
.gsap-anime-2parent reachingtop 80%; very tall headers above can defer this trigger longer than expected.