Skip to content

[BUG] Animation is not smooth in Low Power Mode #3760

@TKhawns

Description

@TKhawns

1. Describe the Bug

I implemented a slide modal using Framer Motion's spring animation.

The animation works smoothly on desktop browsers. However, when testing on Safari iOS with Low Power Mode enabled, the slide animation becomes noticeably laggy and stutters during the transition.

I investigated the issue and considered reducing the animation complexity when Low Power Mode is enabled. Unfortunately, as far as I know, Safari does not provide a Web API that allows websites to detect whether Low Power Mode is currently enabled.

2. Steps to Reproduce

The following simplified example demonstrates the issue:

"use client";

import { AnimatePresence, motion } from "framer-motion";
import { type ReactNode, useEffect } from "react";

interface Props {
  isVisible: boolean;
  onClose: () => void;
  children: ReactNode;
  height?: string;
}

export function SlideModal({
  isVisible,
  onClose,
  children,
  height = "86%",
}: Props) {
  useEffect(() => {
    if (isVisible) {
      const originalBodyOverflow = document.body.style.overflow;
      document.body.style.overflow = "hidden";

      return () => {
        document.body.style.overflow = originalBodyOverflow;
        if (layoutContainer) {
          layoutContainer.style.overflow = originalLayoutOverflow;
        }
      };
    }
  }, [isVisible]);

  return (
    <AnimatePresence>
      {isVisible && (
        <>
          <motion.div
            key="backdrop"
            initial={{ opacity: 0 }}
            animate={{ opacity: 0.4 }}
            exit={{ opacity: 0 }}
            transition={{ duration: 0.25 }}
            className="fixed inset-0 bg-black z-50"
            onClick={onClose}
          />
          <motion.div
            key="sheet"
            initial={{ y: "100%" }}
            animate={{ y: 0 }}
            exit={{ y: "100%" }}
            transition={{ type: "spring", damping: 25, stiffness: 300 }}
            className="fixed bottom-0 inset-x-0 lg:absolute z-50 bg-white rounded-t-[32px] lg:rounded-t-2xl lg:rounded-b-2xl shadow-2xl flex flex-col overflow-hidden max-w-[500px] m-auto"
            style={{ height }}
          >
            <div className="flex justify-center py-3 shrink-0">
              <div className="w-12 h-1.5 bg-gray-200 rounded-full" />
            </div>
            <div className="grow flex flex-col min-h-0">{children}</div>
          </motion.div>
        </>
      )}
    </AnimatePresence>
  );
}

3. Expected Behavior

It would be great if the library could handle this scenario automatically and provide a smoother experience when Safari iOS enters Low Power Mode.

Alternatively, could you recommend a temporary workaround or best practice for handling this situation?

Many thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions