Files

3.3 KiB
Raw Permalink Blame History

name, title, description, tags, source
name title description tags source
motion/parallax-scroll Parallax Depth Effect Multi-layer scrolling with different speeds. Creates 3D depth perception.
motion
parallax
depth
scroll
3d
premium
apple.com, linear.app, amppz.com, brad.co

Parallax Depth Effect

Что это

Многослойный скролл с разной скоростью — создаёт ощущение глубины и 3D-пространства.

Параметры

Параметр Значение
Foreground speed 1x (обычный скролл)
Midground speed 0.5x–0.7x
Background speed 0.1x–0.3x

CSS-реализация (простая)

.parallax-section {
  position: relative;
  height: 100vh;
  overflow: hidden;
}

.parallax-layer {
  position: absolute;
  width: 100%;
  height: 120%;
  top: -10%;
}

.parallax-layer.background {
  z-index: 1;
}
.parallax-layer.midground {
  z-index: 2;
  transform: translateY(10%);
}
.parallax-layer.foreground {
  z-index: 3;
  transform: translateY(20%);
}

GSAP ScrollTrigger (рекомендуется)

import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';

gsap.registerPlugin(ScrollTrigger);

// Background slow
gsap.to('.parallax-bg', {
  yPercent: 30,
  ease: 'none',
  scrollTrigger: {
    trigger: '.parallax-section',
    start: 'top bottom',
    end: 'bottom top',
    scrub: true
  }
});

// Midground medium
gsap.to('.parallax-mid', {
  yPercent: 50,
  ease: 'none',
  scrollTrigger: {
    trigger: '.parallax-section',
    start: 'top bottom',
    end: 'bottom top',
    scrub: true
  }
});

// Foreground fast
gsap.to('.parallax-fg', {
  yPercent: 80,
  ease: 'none',
  scrollTrigger: {
    trigger: '.parallax-section',
    start: 'top bottom',
    end: 'bottom top',
    scrub: true
  }
});

Intersection Observer (лёгкий вариант)

const layers = document.querySelectorAll('.parallax-layer');
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    const speed = parseFloat(entry.target.dataset.speed || 0.1);
    const rect = entry.target.getBoundingClientRect();
    const scrollPercent = window.scrollY / (window.innerHeight + rect.height);
    entry.target.style.transform = `translateY(${scrollPercent * speed * 100}%)`;
  });
}, { threshold: 0.1 });

layers.forEach(layer => observer.observe(layer));

Anti-patterns

❌ Плохо ✅ Хорошо
Без prefers-reduced-motion Уважать настройки пользователя
yPercent: 100 — слишком резко yPercent: 30–50
Без scrub: true scrub: 1 для плавности
太重ых элементов SVG/градиенты вместо фото

Mobile

@media (prefers-reduced-motion: reduce) {
  .parallax-layer {
    transform: none !important;
  }
}

CV Service Validation

curl -s -X POST http://localhost:8001/design/analyze \
  -H "Content-Type: application/json" \
  -d '{"image_base64": "...", "full_analysis": false}' | python3 -c "
import sys, json
d = json.load(sys.stdin)
motion = d['dimensions'].get('motion_quality', {})
print(f\"Motion Quality: {motion.get('score', 'N/A')}/10\")
"