--- name: motion/animated-gradient title: Animated Gradient Background description: Smoothly shifting color gradients for backgrounds, buttons, and text. Creates premium, living feel. tags: [motion, gradient, animation, background, glassmorphism] source: stripe.com, raycast.com, resend.com, linear.app --- # Animated Gradient Background ## Что это Анимированные градиентные фоны, которые плавно перетекают друг в друга. Один из ключевых паттернов Stripe.com и современных SaaS-лендингов. Создаёт ощущение "живого" дизайна. ## Типы анимированных градиентов ### 1. Stripe-Style (shifting color flow) ```css .gradient-bg { background: linear-gradient( 135deg, #6366f1, #8b5cf6, #ec4899, #f43f5e, #6366f1 ); background-size: 400% 400%; animation: gradient-shift 15s ease infinite; } @keyframes gradient-shift { 0% { background-position: 0% 50%; } 25% { background-position: 100% 50%; } 50% { background-position: 100% 100%; } 75% { background-position: 0% 100%; } 100% { background-position: 0% 50%; } } ``` ### 2. Radial Pulse (расширяющийся круг) ```css .gradient-pulse { background: radial-gradient( circle at 30% 30%, rgba(99, 102, 241, 0.15), transparent 50% ); animation: pulse 8s ease-in-out infinite; } @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 0.5; } 50% { transform: scale(1.2); opacity: 0.8; } } ``` ### 3. Mesh Gradient (несколько источников) ```css .mesh-gradient { background: radial-gradient(ellipse at 20% 80%, rgba(99, 102, 241, 0.15), transparent 50%), radial-gradient(ellipse at 80% 20%, rgba(236, 72, 153, 0.15), transparent 50%), radial-gradient(ellipse at 50% 50%, rgba(139, 92, 246, 0.1), transparent 50%); background-size: 100% 100%; animation: mesh-move 20s ease-in-out infinite alternate; } @keyframes mesh-move { 0% { background-position: 0% 0%, 100% 100%, 50% 50%; } 100% { background-position: 100% 100%, 0% 0%, 60% 40%; } } ``` ### 4. Gradient Border (подвижная рамка) ```css .gradient-border { position: relative; border-radius: 20px; padding: 2px; /* border width */ background: linear-gradient(90deg, #6366f1, #ec4899, #f43f5e, #6366f1); background-size: 300% 100%; animation: border-gradient 4s linear infinite; } .gradient-border::before { content: ''; position: absolute; inset: 0; border-radius: 18px; background: #0a0a0a; z-index: -1; } @keyframes border-gradient { 0% { background-position: 0% 50%; } 100% { background-position: 100% 50%; } } ``` ## Glassmorphism Card (Stripe style) ```css .glass-card { position: relative; background: rgba(255, 255, 255, 0.03); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 20px; overflow: hidden; } .glass-card::before { content: ''; position: absolute; inset: 0; background: linear-gradient( 135deg, rgba(255, 255, 255, 0.05) 0%, transparent 50% ); pointer-events: none; } ``` ## Hero Gradient Background (Stripe.com style) ```html

Your text here

``` ```css .hero-gradient { position: relative; min-height: 60vh; overflow: hidden; background: #0a0a0a; } .gradient-orb { position: absolute; border-radius: 50%; filter: blur(80px); opacity: 0.4; animation: orb-float 20s ease-in-out infinite; } .orb-1 { width: 600px; height: 600px; background: radial-gradient(circle, #6366f1, transparent 70%); top: -20%; left: -10%; animation-delay: 0s; } .orb-2 { width: 500px; height: 500px; background: radial-gradient(circle, #ec4899, transparent 70%); bottom: -20%; right: -5%; animation-delay: -5s; } .orb-3 { width: 400px; height: 400px; background: radial-gradient(circle, #10b981, transparent 70%); top: 50%; left: 50%; transform: translate(-50%, -50%); animation-delay: -10s; } @keyframes orb-float { 0%, 100% { transform: translate(0, 0) scale(1); } 25% { transform: translate(50px, -30px) scale(1.1); } 50% { transform: translate(-30px, 50px) scale(0.95); } 75% { transform: translate(30px, 30px) scale(1.05); } } ``` ## Animated Button Gradient ```css .btn-gradient-animated { position: relative; padding: 14px 28px; border: none; border-radius: 12px; font-weight: 600; color: white; cursor: pointer; overflow: hidden; transition: transform 0.3s ease, box-shadow 0.3s ease; } .btn-gradient-animated::before { content: ''; position: absolute; inset: 0; background: linear-gradient( 120deg, #6366f1, #8b5cf6, #ec4899, #f43f5e, #6366f1 ); background-size: 300% 100%; animation: btn-gradient 6s ease infinite; } .btn-gradient-animated:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(99, 102, 241, 0.3); } @keyframes btn-gradient { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } ``` ## Color Palettes ### Indie/SaaS (Stripe/Linear style) ```css --grad-indigo: #6366f1; --grad-purple: #8b5cf6; --grad-pink: #ec4899; --grad-rose: #f43f5e; --grad-cyan: #06b6d4; ``` ### Warm (Resend style) ```css --grad-orange: #f97316; --grad-yellow: #eab308; --grad-red: #ef4444; --grad-pink: #ec4899; ``` ### Cool (Raycast style) ```css --grad-blue: #3b82f6; --grad-cyan: #06b6d4; --grad-teal: #14b8a6; --grad-green: #10b981; ``` ## Anti-patterns | ❌ Плохо | ✅ Хорошо | |----------|-----------| | `animation: 3s` — слишком быстро (мозг не успевает) | `animation: 15–30s` — медленное плавное движение | | Яркие цвета `#ff0000` | Приглушённые `rgba(99,102,241,0.15)` | | Без `filter: blur()` на орбах | `blur(80–120px)` для мягких переходов | | Без `prefers-reduced-motion` | Уважать настройки пользователя | | Градиент на тексте без fallback | Всегда `-webkit-background-clip` | ## Performance ```css /* ✅ Good — CSS animation (GPU accelerated) */ .gradient-bg { animation: gradient-shift 15s ease infinite; will-change: background-position; } /* ❌ Bad — JS animation (main thread) */ element.animate([ { backgroundPosition: '0% 50%' }, { backgroundPosition: '100% 50%' } ], { duration: 15000, iterations: Infinity }); ``` ## CV Service Validation ```bash # Проверить визуальную гармонию градиентов 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) color = d['dimensions'].get('color_harmony', {}) print(f\"Color Harmony: {color.get('score', 'N/A')}/10\") print(f\" Palette: {color.get('palette', 'N/A')}\") " ``` Ожидается: `color_harmony` > 6.