返回动效库
微交互进阶

子元素错开动画

子元素依次错开执行入场动画,通过延迟差营造流畅的序列感。

加载时500ms

交互预览

动效定义与代码

{
  "slug": "stagger-children",
  "name": "子元素错开动画",
  "nameEn": "Stagger Children",
  "description": "子元素依次错开执行入场动画,通过延迟差营造流畅的序列感。",
  "descriptionEn": "Child elements animate in sequence with staggered delays, creating a smooth cascading effect.",
  "category": "micro-interaction",
  "tags": [
    "stagger",
    "sequence",
    "children",
    "cascade",
    "list"
  ],
  "trigger": "on-mount",
  "difficulty": "intermediate",
  "duration": "500ms",
  "easing": "cubic-bezier(0.16, 1, 0.3, 1)",
  "cssProperties": [
    "opacity",
    "transform"
  ],
  "isGPUAccelerated": true,
  "previewBg": "light",
  "keywords": [
    "stagger",
    "cascade",
    "sequence",
    "children",
    "list animation",
    "delay"
  ],
  "useCases": [
    "List item entrance",
    "Grid card reveal",
    "Navigation menu items",
    "Dashboard widget loading"
  ],
  "relatedAnimations": [
    "fade-in-up",
    "scroll-reveal"
  ],
  "recommendedStyles": [
    "bento-grid",
    "masonry-flow",
    "card-stack"
  ],
  "codeSnippets": [
    {
      "label": "CSS Keyframes",
      "language": "css",
      "code": "@keyframes stagger-fade-in {\n  from {\n    opacity: 0;\n    transform: translateY(15px);\n  }\n  to {\n    opacity: 1;\n    transform: translateY(0);\n  }\n}\n\n.stagger-children > * {\n  will-change: transform, opacity;\n  opacity: 0;\n  animation: stagger-fade-in 500ms cubic-bezier(0.16, 1, 0.3, 1) both;\n  animation-delay: calc(var(--stagger-index, 0) * var(--stagger-delay, 75ms));\n}\n\n/* Usage: set --stagger-index on each child via inline style\n   <div class=\"stagger-children\">\n     <div style=\"--stagger-index: 0\">...</div>\n     <div style=\"--stagger-index: 1\">...</div>\n     <div style=\"--stagger-index: 2\">...</div>\n   </div>\n   Override delay: style=\"--stagger-delay: 100ms\" on parent */\n\n@media (prefers-reduced-motion: reduce) {\n  .stagger-children {\n    animation: none;\n    opacity: 1;\n    transform: none;\n  }\n}"
    },
    {
      "label": "Tailwind CSS",
      "language": "tsx",
      "code": "// React + Tailwind approach with inline delay\nfunction StaggerList({ items }: { items: string[] }) {\n  return (\n    <ul className=\"space-y-2\">\n      {items.map((item, i) => (\n        <li\n          key={item}\n          className=\"animate-fade-in-up opacity-0\"\n          style={{ animationDelay: `${i * 75}ms`, animationFillMode: \"both\" }}\n        >\n          {item}\n        </li>\n      ))}\n    </ul>\n  );\n}\n\n/* Requires this in your CSS: */\n// @keyframes fade-in-up {\n//   from { opacity: 0; transform: translateY(15px); }\n//   to { opacity: 1; transform: translateY(0); }\n// }\n// @utility animate-fade-in-up {\n//   animation: fade-in-up 500ms cubic-bezier(0.16, 1, 0.3, 1);\n// }"
    },
    {
      "label": "Framer Motion",
      "language": "tsx",
      "code": "import { motion } from \"framer-motion\";\n\n// Tip: respect user's motion preferences\n// import { useReducedMotion } from \"framer-motion\";\n// const reduced = useReducedMotion();\n// Use reduced ? { opacity: 0 } : { opacity: 0, y: 15 } for initial\n\nconst container = {\n  hidden: { opacity: 0 },\n  show: {\n    opacity: 1,\n    transition: { staggerChildren: 0.075 },\n  },\n};\n\nconst item = {\n  hidden: { opacity: 0, y: 15 },\n  show: { opacity: 1, y: 0 },\n};\n\n<motion.ul variants={container} initial=\"hidden\" animate=\"show\">\n  {items.map((text) => (\n    <motion.li key={text} variants={item}>\n      {text}\n    </motion.li>\n  ))}\n</motion.ul>"
    }
  ]
}