You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React登录页组件滑动切换问题:内容滑出页面

登录页面滑动动画内容滑出页面问题

我正在开发一个登录页面,用户先输入用户名,点击“Next”按钮后触发流畅的滑动动画,密码输入区域从右侧滑入。动画可正常运行,但切换后出现内容滑出页面的问题。

  • 点击Next前:显示用户名输入界面,包含Logo、“Sign In”标题、邮箱/手机号输入框,以及「没有账号?创建一个」的链接。
  • 点击Next后:密码输入区域滑入时,整体内容偏移过度,部分内容超出白色卡片容器范围。

原代码

import React from 'react'
import {useEffect, useState} from 'react'
import {useRef} from 'react'
import {motion} from 'framer-motion'
import PageTransition from '../components/PageTransition'

const Auth = () => {

    const [count, setCount] = useState(0);

    const pageComponents = [
        <>
        <div>
            <div className="flex inline-block">
                <img src={require("../images/Logo.jpg")} alt="logo" className=" w-12 h-12 mb-4" />
                <h1 className="text-primary font-CreteRoundRegular text-4xl ml-2 mt-1 ">TEST</h1>
            </div>

            <div className="flex flex-col mr-auto w-full">
                <p className="font-CreteRoundRegular text-xl text-primary mt-2">Sign In</p>
                <input id="input-username" type="text" placeholder="Email or Phone" className="border-b-2 py-2 w-full border-gray-300 focus:outline-none focus:border-green-500 mb-4 mt-2" />
            </div>

            <div className="flex inline-block">
                <p className="font-CreteRoundRegular text-sm text-black">Don't have an account?</p>
                <a href="/auth"><p className="font-CreteRoundRegular text-sm text-primary ml-1">Create one!</p></a>
            </div>
            </div>

        </>,
        <>
            <div>
                <div className="flex inline-block ">
                    <img src={require("../images/Logo.jpg")} alt="logo" className=" w-12 h-12 mb-4" />
                    <h1 className="text-primary font-CreteRoundRegular text-4xl ml-2 mt-1 ">TEST</h1>
                </div>

                <div className="flex flex-col mr-auto w-full">
                    <p className="font-CreteRoundRegular text-xl text-primary mt-2">Enter password</p>
                    <input type="text" placeholder="Your password" className="border-b-2 py-2 w-full border-gray-300 focus:outline-none focus:border-green-500 mb-4 mt-2" />
                </div>

                <div className="flex inline-block">
                    <p className="font-CreteRoundRegular text-sm text-black">Forgot password?</p>
                    <a href="/auth"><p className="font-CreteRoundRegular text-sm text-primary ml-1">Reset password</p></a>
                </div>
            </div>

        </>
    ];
    

  return (
    <section className="flex h-screen bg-primary items-center justify-center">

        <div id="outerlayer" className="flex flex-col mobile:w-9/12 tablet:w-3/12 mobile:mb-32 tablet:mb-0 rounded-2xl w-full h-auto bg-white shadow-black shadow-md p-10 overflow-hidden relative">

        
        // fade in animation style
        <div id="layer" className="flex flex-col">

            <motion.div className="ease-in-out duration-500 transition-all" style={{transform: `translateX(-${count * 150}%)`}}>
                {
                    pageComponents[count]
                }
            </motion.div>

        </div>
        

        {count > 0 ?
            <div className="flex inline-block">
                <button id="previous" className="mt-10 mr-auto bg-primary text-white font-CreteRoundRegular px-5 py-2 rounded-full hover:bg-green-800" onClick={() => setCount(count - 1)}>Previous</button> 
                <button id="signin" className="mt-10 ml-auto bg-primary text-white font-CreteRoundRegular px-5 py-2 rounded-full hover:bg-green-800" onClick={() => setCount(count - 1)}>Sign in</button> 
            </div>
             : null}
            {count < pageComponents.length - 1 ? <button id="next" className="mt-10 ml-auto bg-primary text-white font-CreteRoundRegular px-5 py-2 rounded-full hover:bg-green-800" onClick={() => setCount(count + 1)}>Next</button> : null}


        </div>

    </section>
  )
}

export default Auth

修复方案

1. 修正偏移百分比

当前使用translateX(-${count * 150}%),150%的偏移量会让内容直接滑出容器(容器宽度为100%),将数值改为100%即可:

<motion.div className="ease-in-out duration-500 transition-all" style={{transform: `translateX(-${count * 100}%)`}}>
  {pageComponents[count]}
</motion.div>

2. 优化动画容器结构(推荐)

将两个登录步骤组件放在同一容器内,利用Framer Motion的原生动画属性实现滑动,布局更稳定:

// 替换原代码中#layer及内部的motion.div部分
<div id="layer" className="flex overflow-hidden">
  <motion.div 
    className="flex"
    animate={{ x: `-${count * 100}%` }}
    transition={{ duration: 0.5, ease: "easeInOut" }}
  >
    {pageComponents.map((component, idx) => (
      <div key={idx} className="w-full flex-shrink-0">
        {component}
      </div>
    ))}
  </motion.div>
</div>

这种方式让两个组件并排排列,通过整体偏移实现切换,避免单个组件偏移导致的布局溢出问题,同时更贴合Framer Motion的使用规范。

3. 修复Sign In按钮逻辑

当前Sign In按钮点击后会返回上一步,不符合登录流程,修改为触发登录逻辑:

<button id="signin" className="mt-10 ml-auto bg-primary text-white font-CreteRoundRegular px-5 py-2 rounded-full hover:bg-green-800" onClick={() => {
  // 这里添加登录逻辑,比如表单校验、接口请求
  console.log("执行登录操作")
}}>Sign in</button>

内容的提问来源于stack exchange,提问作者Matthew Masody

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:19:51