Sync: implement scroll-reveal animations for cards with responsive visibility adjustments
This commit is contained in:
@@ -97,6 +97,17 @@ img, video { max-width: 100%; display: block; }
|
||||
a { color: inherit; text-decoration: none; transition: color var(--transition); }
|
||||
a:hover { color: var(--color-primary); }
|
||||
|
||||
/* ── Scroll-reveal animation classes ───────────────────────── */
|
||||
.scroll-hidden {
|
||||
opacity: 0;
|
||||
transform: translateY(24px);
|
||||
}
|
||||
.scroll-visible {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
transition: opacity .5s ease, transform .5s ease;
|
||||
}
|
||||
|
||||
/* Smooth theme transition */
|
||||
body,
|
||||
.site-header,
|
||||
@@ -4128,6 +4139,14 @@ p:last-child { margin-bottom: 0; }
|
||||
50% { transform: translateY(-50%) scale(1.08); }
|
||||
}
|
||||
|
||||
/* ── Responsive scale-down ── */
|
||||
@media (max-width: 900px) {
|
||||
.cam-stage { transform: scale(0.85); transform-origin: center center; }
|
||||
}
|
||||
@media (max-width: 640px) {
|
||||
.cam-stage { transform: scale(0.72); transform-origin: center center; }
|
||||
}
|
||||
|
||||
/* ── Reduced-motion ── */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.cam-subject--2, .cam-subject--3,
|
||||
|
||||
@@ -134,17 +134,31 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const cards = document.querySelectorAll('.oribi-card, .feature-card, .industry-card, .pricing-card, .value-card, .platform-row');
|
||||
if (cards.length && 'IntersectionObserver' in window &&
|
||||
!window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
|
||||
cards.forEach(c => { c.style.opacity = '0'; c.style.transform = 'translateY(24px)'; c.style.transition = 'opacity .5s ease, transform .5s ease'; });
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.style.opacity = '1';
|
||||
entry.target.style.transform = 'translateY(0)';
|
||||
io.unobserve(entry.target);
|
||||
cards.forEach(c => c.classList.add('scroll-hidden'));
|
||||
/* Use rAF to ensure the class is applied before observing – avoids
|
||||
Safari quirk where elements already in-viewport don't fire. */
|
||||
requestAnimationFrame(() => {
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.classList.remove('scroll-hidden');
|
||||
entry.target.classList.add('scroll-visible');
|
||||
io.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.05, rootMargin: '0px 0px 80px 0px' });
|
||||
cards.forEach(c => io.observe(c));
|
||||
});
|
||||
/* Safety net: reveal any still-hidden elements after 4 s so content
|
||||
is never permanently invisible (e.g. iOS Safari edge-cases). */
|
||||
setTimeout(() => {
|
||||
cards.forEach(c => {
|
||||
if (c.classList.contains('scroll-hidden')) {
|
||||
c.classList.remove('scroll-hidden');
|
||||
c.classList.add('scroll-visible');
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.1, rootMargin: '0px 0px 60px 0px' });
|
||||
cards.forEach(c => io.observe(c));
|
||||
}, 4000);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user