awwwards-animations

Professional React animation skill for creating Awwwards/FWA-level animations using GSAP (useGSAP), Motion (Framer Motion), Anime.js, and Lenis. Use when building premium scroll experiences, custom cursors, page transitions, text animations, parallax effects, micro-interactions, or any animation that needs to be 60fps and award-worthy. Triggers on requests for smooth scroll, ScrollTrigger, magnetic effects, reveal animations, horizontal scroll, pin sections, stagger effects, useScroll, useTransform, integration with Three.js/WebGL, algorithmic art, mathematical art, generative art, fractals, L-systems, flow fields, strange attractors, sacred geometry, geometric puzzles, Dudeney dissections, tangram, tessellations, Penrose tiles, kinetic typography, glitch effects, text explosion, morphing text, circular text, brutalist design, minimalist animation, neo-brutalism, or design philosophy mixing. React-first approach with proper cleanup and hooks.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "awwwards-animations" with this command: npx skills add devmartinese/awwwards-animations-skill/devmartinese-awwwards-animations-skill-awwwards-animations

Awwwards Animations

Create premium web animations at Awwwards/FWA quality level. React-first approach. 60fps non-negotiable.

Decision Matrix

TaskLibraryWhy
Scroll-driven animationsGSAP + ScrollTrigger + useGSAPIndustry standard, best control
Smooth scrollLenis + ReactLenisBest performance, works with ScrollTrigger
React-native animationsMotion (Framer Motion)Native React, useScroll/useTransform
Simple/lightweight effectsAnime.js 4.0Small footprint, clean API
Complex timelinesGSAPUnmatched timeline control
SVG morphingGSAP MorphSVG or Anime.jsBoth excellent
3D + animationThree.js + GSAPGSAP controls Three.js objects
Page transitionsAnimatePresence or GSAPMotion for React, GSAP for complex
Geometric shapes (vector)SVG + GSAP/MotionNative, animable
Geometric shapes (canvas)Canvas 2D APIProgrammatic, performant
Pseudo-3D shapesZdogFlat design 3D, ~2kb
Creative coding/generativep5.jsRich ecosystem
Audio reactiveTone.jsWeb Audio, synths, effects
Physics 2DMatter.jsGravity, collisions, constraints
Algorithmic/generative artCanvas 2D + p5.jsMath-driven visuals
Fractals/L-systemsCanvas 2D recursivoRecursive rendering
Tessellations/geometric puzzlesSVG + GSAPPrecise animated transforms
Kinetic typography advancedGSAP SplitText + CanvasPer-char control
Glitch effectsCSS + GSAPLayered RGB split, clip-path
Brutalist animationCSS raw + MotionHard cuts, no easing
Minimalist animationMotion springsSubtle, purposeful motion

Installation (Latest Stable - 2025)

# GSAP + React hook (v3.14.1)
npm install gsap @gsap/react

# Lenis (v1.3.17) - includes React components
npm install lenis

# Motion (Framer Motion)
npm install motion

# Anime.js (v4.0.0)
npm install animejs

React Setup

1. GSAP Configuration (app-wide)

// lib/gsap.ts
'use client' // Next.js App Router

import gsap from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { useGSAP } from '@gsap/react'

// Register plugins once
gsap.registerPlugin(ScrollTrigger, useGSAP)

export { gsap, ScrollTrigger, useGSAP }

2. Lenis + GSAP ScrollTrigger Integration (Critical)

// components/SmoothScroll.tsx
'use client'
import { ReactLenis, useLenis } from 'lenis/react'
import { useEffect } from 'react'
import { gsap, ScrollTrigger } from '@/lib/gsap'

export function SmoothScroll({ children }: { children: React.ReactNode }) {
  const lenis = useLenis()
  useEffect(() => {
    if (!lenis) return
    lenis.on('scroll', ScrollTrigger.update)
    gsap.ticker.add((time) => lenis.raf(time * 1000))
    gsap.ticker.lagSmoothing(0)
    return () => { gsap.ticker.remove(lenis?.raf) }
  }, [lenis])

  return (
    <ReactLenis root options={{ lerp: 0.1, duration: 1.2, smoothWheel: true }}>
      {children}
    </ReactLenis>
  )
}
// Wrap in layout: <SmoothScroll>{children}</SmoothScroll>

Core Patterns (React)

Detailed implementations in references:

Quick Patterns (React)

1. Magnetic Cursor (GSAP + useGSAP)

'use client'
import { useRef, useEffect } from 'react'
import { gsap, useGSAP } from '@/lib/gsap'

export function MagneticCursor() {
  const cursorRef = useRef<HTMLDivElement>(null)
  const pos = useRef({ x: 0, y: 0, cx: 0, cy: 0 })
  useEffect(() => {
    const h = (e: MouseEvent) => { pos.current.x = e.clientX; pos.current.y = e.clientY }
    window.addEventListener('mousemove', h)
    return () => window.removeEventListener('mousemove', h)
  }, [])
  useGSAP(() => {
    gsap.ticker.add(() => {
      const p = pos.current
      p.cx += (p.x - p.cx) * 0.15; p.cy += (p.y - p.cy) * 0.15
      gsap.set(cursorRef.current, { x: p.cx, y: p.cy })
    })
  })
  return <div ref={cursorRef} className="fixed w-10 h-10 border border-white rounded-full pointer-events-none mix-blend-difference z-[9999] -translate-x-1/2 -translate-y-1/2" />
}

2. Magnetic Button (Motion)

'use client'
import { useRef, useState } from 'react'
import { motion } from 'motion/react'

export function MagneticButton({ children }: { children: React.ReactNode }) {
  const ref = useRef<HTMLButtonElement>(null)
  const [pos, setPos] = useState({ x: 0, y: 0 })
  const onMove = (e: React.MouseEvent) => {
    const { left, top, width, height } = ref.current!.getBoundingClientRect()
    setPos({ x: (e.clientX - left - width / 2) * 0.3, y: (e.clientY - top - height / 2) * 0.3 })
  }
  return (
    <motion.button ref={ref} onMouseMove={onMove} onMouseLeave={() => setPos({ x: 0, y: 0 })}
      animate={pos} transition={{ type: 'spring', stiffness: 150, damping: 15 }}
      className="px-8 py-4 bg-white text-black rounded-full">{children}</motion.button>
  )
}

3. Parallax Hero (GSAP + useGSAP)

'use client'
import { useRef } from 'react'
import { gsap, ScrollTrigger, useGSAP } from '@/lib/gsap'

export function ParallaxHero() {
  const containerRef = useRef<HTMLDivElement>(null)

  useGSAP(() => {
    gsap.to('.parallax-bg', {
      yPercent: 50,
      ease: 'none',
      scrollTrigger: {
        trigger: containerRef.current,
        start: 'top top',
        end: 'bottom top',
        scrub: true,
      },
    })

    gsap.to('.hero-title', {
      yPercent: 100,
      opacity: 0,
      scrollTrigger: {
        trigger: containerRef.current,
        start: 'top top',
        end: '50% top',
        scrub: true,
      },
    })
  }, { scope: containerRef })

  return (
    <div ref={containerRef} className="relative h-screen overflow-hidden">
      <div className="parallax-bg absolute inset-0 bg-cover bg-center" />
      <h1 className="hero-title absolute inset-0 flex items-center justify-center text-6xl">
        Hero Title
      </h1>
    </div>
  )
}

4. Text Character Reveal (Motion)

'use client'
import { motion } from 'motion/react'

const container = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: { staggerChildren: 0.02 },
  },
}

const child = {
  hidden: { opacity: 0, y: 50, rotateX: -90 },
  visible: {
    opacity: 1,
    y: 0,
    rotateX: 0,
    transition: { type: 'spring', damping: 12 },
  },
}

export function TextReveal({ text }: { text: string }) {
  return (
    <motion.span
      variants={container}
      initial="hidden"
      whileInView="visible"
      viewport={{ once: true }}
      className="inline-block"
    >
      {text.split('').map((char, i) => (
        <motion.span key={i} variants={child} className="inline-block">
          {char === ' ' ? '\u00A0' : char}
        </motion.span>
      ))}
    </motion.span>
  )
}

5. Image Reveal (GSAP)

'use client'
import { useRef } from 'react'
import { gsap, useGSAP } from '@/lib/gsap'

export function ImageReveal({ src, alt }: { src: string; alt: string }) {
  const containerRef = useRef<HTMLDivElement>(null)

  useGSAP(() => {
    gsap.from(containerRef.current, {
      clipPath: 'inset(100% 0% 0% 0%)',
      duration: 1.2,
      ease: 'power4.inOut',
      scrollTrigger: {
        trigger: containerRef.current,
        start: 'top 80%',
      },
    })

    gsap.from('.reveal-img', {
      scale: 1.3,
      duration: 1.5,
      ease: 'power2.out',
      scrollTrigger: {
        trigger: containerRef.current,
        start: 'top 80%',
      },
    })
  }, { scope: containerRef })

  return (
    <div ref={containerRef} className="overflow-hidden">
      <img src={src} alt={alt} className="reveal-img w-full h-full object-cover" />
    </div>
  )
}

6. Glitch Text Effect (CSS + GSAP)

'use client'
import { useRef, useEffect } from 'react'
import { gsap } from '@/lib/gsap'

export function GlitchText({ text }: { text: string }) {
  const ref = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const layers = ref.current!.querySelectorAll('.g-layer')
    const tl = gsap.timeline({ repeat: -1, repeatDelay: 3 })
    tl.to(layers[0], { x: -5, duration: 0.05, ease: 'none' }, 0)
      .to(layers[0], { x: 5, duration: 0.05 }, 0.05)
      .to(layers[0], { x: 0, duration: 0.05 }, 0.1)
      .to(layers[1], { x: 5, duration: 0.05 }, 0.02)
      .to(layers[1], { x: -5, duration: 0.05 }, 0.07)
      .to(layers[1], { x: 0, duration: 0.05 }, 0.12)
    return () => { tl.kill() }
  }, [])

  return (
    <div ref={ref} className="relative font-mono text-5xl font-black">
      <span className="relative z-10">{text}</span>
      <span className="g-layer absolute inset-0 text-cyan-400 mix-blend-multiply" aria-hidden>{text}</span>
      <span className="g-layer absolute inset-0 text-red-400 mix-blend-multiply" aria-hidden>{text}</span>
    </div>
  )
}

7. Fractal Tree (Canvas 2D)

'use client'
import { useRef, useEffect } from 'react'

export function FractalTree({ depth = 10, angle = 25 }: { depth?: number; angle?: number }) {
  const canvasRef = useRef<HTMLCanvasElement>(null)

  useEffect(() => {
    const canvas = canvasRef.current!
    const ctx = canvas.getContext('2d')!
    canvas.width = canvas.offsetWidth * 2; canvas.height = canvas.offsetHeight * 2; ctx.scale(2, 2)
    let progress = 0, raf = 0

    function branch(x: number, y: number, len: number, a: number, d: number) {
      if (d > depth || len < 2) return
      const dp = Math.max(0, Math.min(1, progress * depth - d))
      if (dp <= 0) return
      const ex = x + Math.cos(a * Math.PI / 180) * len * dp
      const ey = y - Math.sin(a * Math.PI / 180) * len * dp
      ctx.beginPath(); ctx.moveTo(x, y); ctx.lineTo(ex, ey)
      ctx.strokeStyle = `hsl(${120 + d * 15}, 60%, ${30 + d * 5}%)`
      ctx.lineWidth = Math.max(1, (depth - d) * 1.5); ctx.stroke()
      branch(ex, ey, len * 0.72, a + angle, d + 1)
      branch(ex, ey, len * 0.72, a - angle, d + 1)
    }
    const animate = () => {
      progress = Math.min(1, progress + 0.008)
      ctx.clearRect(0, 0, canvas.offsetWidth, canvas.offsetHeight)
      branch(canvas.offsetWidth / 2, canvas.offsetHeight, canvas.offsetHeight * 0.28, 90, 0)
      if (progress < 1) raf = requestAnimationFrame(animate)
    }
    animate()
    return () => cancelAnimationFrame(raf)
  }, [depth, angle])
  return <canvas ref={canvasRef} className="w-full h-full bg-gray-950" />
}

See references/algorithmic-art.md for L-systems, flow fields, attractors, noise, sacred geometry.

8. Geometric Dissection (SVG + GSAP)

'use client'
import { useRef, useState } from 'react'
import { gsap } from '@/lib/gsap'

const P = [
  { id: 'A', tri: 'M 0,173 L 50,87 L 100,173 Z', sq: 'M 0,0 L 100,0 L 100,87 L 0,87 Z', c: '#f43f5e' },
  { id: 'B', tri: 'M 50,87 L 100,0 L 150,87 Z', sq: 'M 100,0 L 200,0 L 200,87 L 100,87 Z', c: '#8b5cf6' },
  { id: 'C', tri: 'M 100,173 L 150,87 L 200,173 Z', sq: 'M 0,87 L 100,87 L 100,173 L 0,173 Z', c: '#06b6d4' },
  { id: 'D', tri: 'M 50,87 L 100,173 L 150,87 L 100,0 Z', sq: 'M 100,87 L 200,87 L 200,173 L 100,173 Z', c: '#f59e0b' },
]
export function GeometricDissection() {
  const svg = useRef<SVGSVGElement>(null)
  const [isSq, setSq] = useState(false)
  const morph = () => {
    const t = !isSq
    P.forEach((p, i) => {
      const el = svg.current!.querySelector(`#d-${p.id}`)
      if (el) gsap.to(el, { attr: { d: t ? p.sq : p.tri }, duration: 1.5, ease: 'power2.inOut', delay: i * 0.15 })
    }); setSq(t)
  }
  return (
    <div className="flex flex-col items-center gap-4">
      <svg ref={svg} viewBox="-10 -10 220 200" className="w-64 h-64">
        {P.map(p => <path key={p.id} id={`d-${p.id}`} d={p.tri} fill={p.c} stroke="#000" strokeWidth="1.5" />)}
      </svg>
      <button onClick={morph} className="px-6 py-2 bg-white text-black font-mono text-sm">{isSq ? '△' : '□'}</button>
    </div>
  )
}

See references/geometric-puzzles.md for tangram, tessellations, Penrose tiles, polyominoes.

9. Brutalist Grid (Motion)

'use client'
import { motion } from 'motion/react'

export function BrutalistGrid({ items }: { items: string[] }) {
  return (
    <div className="grid grid-cols-3 border-2 border-black">
      {items.map((item, i) => (
        <motion.div key={i}
          className="border-2 border-black p-6 font-mono font-black uppercase text-2xl"
          style={{ mixBlendMode: i % 2 === 0 ? 'normal' : 'difference' }}
          initial={{ opacity: 0 }} whileInView={{ opacity: 1 }} viewport={{ once: true }}
          transition={{ duration: 0, delay: i * 0.1 }}
          whileHover={{ backgroundColor: '#000', color: '#BAFF39', transition: { duration: 0 } }}
        >{item}</motion.div>
      ))}
    </div>
  )
}

Design Philosophy (Quick Reference)

StyleMotion FeelEasingTypographyKey Trait
BrutalistHard, instant, jarringnone / steps()Mono, 15-30vwRaw honesty
MinimalistSmooth, subtle, slowpower2.outSans-serif lightPurposeful restraint
AbstractNoise-driven, parametricOrganic/sineVariesMathematical beauty
Neo-BrutalistBold but controlledpower1.outMono + colorBrutalism + restraint

See references/design-philosophy.md for full guide with color palettes and mixing strategies.

Easing Reference

FeelGSAPMotion
Smoothpower2.out[0.16, 1, 0.3, 1]
Snappypower4.out[0.87, 0, 0.13, 1]
Bouncyback.out(1.7){ type: 'spring', stiffness: 300, damping: 20 }
Dramaticpower4.inOut[0.76, 0, 0.24, 1]

Timing

  • Micro-interactions: 150-300ms
  • UI transitions: 300-500ms
  • Page transitions: 500-800ms
  • Stagger: 0.02-0.1s per item

Accessibility

// Motion: useReducedMotion() → conditionally disable/reduce animations
import { useReducedMotion } from 'motion/react'
const reduced = useReducedMotion() // true if prefers-reduced-motion: reduce
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

Performance Rules

  1. Only animate transform and opacity
  2. Use will-change sparingly
  3. Always cleanup: useGSAP handles it automatically
  4. Scope GSAP selectors to container refs
  5. Use contextSafe() for event handlers with GSAP
  6. Memoize Motion variants objects

Common Pitfalls

  1. Not integrating Lenis with ScrollTrigger
  2. Missing scope in useGSAP
  3. Not using contextSafe() for click handlers
  4. React 18 Strict Mode calling effects twice
  5. Forgetting 'use client' in Next.js App Router
  6. Not calling ScrollTrigger.refresh() after dynamic content

Testing Checklist

  • 60fps on scroll (Chrome DevTools Performance)
  • Keyboard navigation works
  • Respects prefers-reduced-motion
  • No layout shifts (CLS)
  • Mobile touch works
  • ScrollTrigger markers removed in prod
  • No memory leaks on unmount

Inspiration

Active Theory, Studio Freight, Locomotive, Resn, Aristide Benoist, Immersive Garden

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

arxiv-paper-writer

Use this skill whenever the user wants Claude Code to write, scaffold, compile, debug, or review an arXiv-style academic paper, especially survey papers with LaTeX, BibTeX citations, TikZ figures, tables, and PDF output. This skill should trigger for requests like writing a full paper, creating an arXiv paper project, turning a research topic into a LaTeX manuscript, reproducing the Paper-Write-Skill-Test agent-survey workflow, or setting up a Windows/Linux Claude Code paper-writing loop.

Archived SourceRecently Updated
Coding

cli-proxy-troubleshooting

排查 CLI Proxy API(codex-api-proxy)的配置、认证、模型注册和请求问题。适用场景包括:(1) AI 请求报错 unknown provider for model, (2) 模型列表中缺少预期模型, (3) codex-api-key/auth-dir 配置不生效, (4) CLI Proxy 启动后 AI 无法调用, (5) 认证成功但请求失败或超时。包含源码级排查方法:模型注册表架构、认证加载链路、 SanitizeCodexKeys 规则、常见错误的真实根因。

Archived SourceRecently Updated
Coding

visual-summary-analysis

Performs AI analysis on input video clips/image content and generates a smooth, natural scene description. | 视觉摘要智述技能,对传入的视频片段/图片内容进行AI分析,生成一段通顺自然的场景描述内容

Archived SourceRecently Updated
Coding

frontend-skill

全能高级前端研发工程师技能。擅长AI时代前沿技术栈(React最新 + shadcn/ui + Tailwind CSS v4 + TypeScript + Next.js),精通动效库与交互特效开发。采用Glue Code风格快速实现代码,强调高质量产品体验与高度友好的UI视觉规范。在组件调用、交互特效、全局Theme上保持高度规范:绝不重复造轮子,相同逻辑出现两次即封装为组件。具备安全意识,防范各类注入攻击。开发页面具有高度自适应能力,响应式设计贯穿始终。当用户无特殊技术栈要求时,默认采用主流前沿技术栈。

Archived SourceRecently Updated