返回动效库
离场入门

右侧滑出

元素向右侧滑出视口并消失,适合侧面板关闭、抽屉菜单收起等退场效果。

点击时400ms

交互预览

动效定义与代码

{
  "slug": "slide-out-right",
  "name": "右侧滑出",
  "nameEn": "Slide Out Right",
  "description": "元素向右侧滑出视口并消失,适合侧面板关闭、抽屉菜单收起等退场效果。",
  "descriptionEn": "Element slides out to the right and disappears. Perfect for closing side panels, drawers, and split-screen exits.",
  "category": "exit",
  "tags": [
    "slide",
    "exit",
    "horizontal",
    "panel"
  ],
  "trigger": "on-click",
  "difficulty": "beginner",
  "duration": "400ms",
  "easing": "cubic-bezier(0.4, 0, 1, 1)",
  "cssProperties": [
    "opacity",
    "transform"
  ],
  "isGPUAccelerated": true,
  "previewBg": "light",
  "keywords": [
    "slide out",
    "right",
    "exit",
    "panel close",
    "drawer",
    "dismiss"
  ],
  "useCases": [
    "Side panel closing",
    "Drawer menu dismiss",
    "Card swipe-to-dismiss",
    "Page transition exit"
  ],
  "relatedAnimations": [
    "slide-in-left",
    "slide-in-right",
    "fade-out-down"
  ],
  "recommendedStyles": [
    "minimalist-flat",
    "corporate-clean",
    "soft-ui"
  ],
  "codeSnippets": [
    {
      "label": "CSS Keyframes",
      "language": "css",
      "code": "@keyframes slide-out-right {\n  from {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  to {\n    opacity: 0;\n    transform: translateX(100%);\n  }\n}\n\n.slide-out-right {\n  --sk-duration: 400ms;\n  --sk-delay: 0ms;\n  --sk-ease: cubic-bezier(0.4, 0, 1, 1);\n  will-change: transform, opacity;\n  animation: slide-out-right var(--sk-duration) var(--sk-ease) var(--sk-delay) both;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .slide-out-right {\n    animation: none;\n    opacity: 0;\n    transform: none;\n  }\n}"
    },
    {
      "label": "Tailwind CSS",
      "language": "css",
      "code": "@keyframes slide-out-right {\n  from {\n    opacity: 1;\n    transform: translateX(0);\n  }\n  to {\n    opacity: 0;\n    transform: translateX(100%);\n  }\n}\n\n@utility animate-slide-out-right {\n  --sk-duration: 400ms;\n  --sk-delay: 0ms;\n  --sk-ease: cubic-bezier(0.4, 0, 1, 1);\n  will-change: transform, opacity;\n  animation: slide-out-right var(--sk-duration) var(--sk-ease) var(--sk-delay) both;\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .slide-out-right {\n    animation: none;\n    opacity: 0;\n    transform: none;\n  }\n}"
    },
    {
      "label": "AnimeJS",
      "language": "tsx",
      "code": "\"use client\";\n\nimport { useEffect, useRef, type ReactNode } from \"react\";\n\ntype AnimeAnimation = {\n  cancel(): unknown;\n};\n\nfunction prefersReducedMotion() {\n  return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\nfunction resetElement(element: HTMLElement) {\n  element.style.opacity = \"\";\n  element.style.transform = \"\";\n}\n\nexport function SlideOutPanel({ children }: { children: ReactNode }) {\n  const panelRef = useRef<HTMLDivElement>(null);\n  const animationRef = useRef<AnimeAnimation | null>(null);\n\n  useEffect(() => {\n    return () => {\n      animationRef.current?.cancel();\n    };\n  }, []);\n\n  async function closePanel() {\n    const panel = panelRef.current;\n    if (!panel || prefersReducedMotion()) return;\n\n    const { animate } = await import(\"animejs\");\n    if (panelRef.current !== panel) return;\n\n    animationRef.current?.cancel();\n    resetElement(panel);\n\n    animationRef.current = animate(panel, {\n      opacity: [1, 0],\n      x: [\"0%\", \"100%\"],\n      duration: 400,\n      ease: \"in(2)\",\n      onComplete: () => resetElement(panel),\n    });\n  }\n\n  return (\n    <div>\n      <button type=\"button\" onClick={() => void closePanel()}>\n        Close\n      </button>\n      <div ref={panelRef} className=\"will-change-transform\">\n        {children}\n      </div>\n    </div>\n  );\n}"
    },
    {
      "label": "Framer Motion",
      "language": "tsx",
      "code": "import { motion } from \"framer-motion\";\n\n<motion.div\n  initial={{ opacity: 1, x: 0 }}\n  exit={{ opacity: 0, x: \"100%\" }}\n  transition={{ duration: 0.4, ease: [0.4, 0, 1, 1] }}\n>\n  Content\n</motion.div>"
    }
  ]
}