实现点击后居中展开的Todo卡片(不影响其他卡片布局)
实现点击展开并居中的Todo卡片(无卡顿版)
核心优化思路
放弃position: relative+transform的方案,改用原元素留占位 + 克隆元素固定定位动画的方式:
- 原卡片展开时仅保留占位(高度不变、内容透明),完全不影响bento board的布局稳定性
- 克隆的卡片脱离文档流(
position: fixed),单独在GPU层执行动画,避免触发全局重排导致卡顿跳帧
代码实现
1. CSS 样式调整
/* 基础卡片样式 */ .ticket { background-color: rgb(25, 25, 25); max-width: 300px; border-radius: 25px; padding: 10px; display: flex; flex-direction: column; cursor: pointer; /* 初始缩小状态 */ transform: scale(0.9); transition: transform 0.2s ease; } /* 初始隐藏body内容 */ .ticket__body { max-height: 0; overflow: hidden; opacity: 0; transition: all 0.2s ease; } /* 原卡片展开时的占位状态 */ .ticket--expanded { transform: scale(1); opacity: 0; /* 透明占位,不占用视觉空间但保留布局位置 */ } /* 展开的全屏卡片样式 */ .ticket__expanded-overlay { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: rgb(25, 25, 25); border-radius: 25px; padding: 20px; width: 90%; max-width: 600px; z-index: 1000; animation: expandIn 0.3s ease forwards; } .ticket__expanded-overlay .ticket__body { max-height: 1000px; opacity: 1; margin-top: 15px; } /* 展开动画关键帧 */ @keyframes expandIn { from { transform: translate(-50%, -50%) scale(0.9); opacity: 0; } to { transform: translate(-50%, -50%) scale(1); opacity: 1; } }
2. React 组件逻辑修改
import { useState } from 'react'; function Ticket() { const [isExpanded, setIsExpanded] = useState(false); // 切换展开/收起状态 const handleToggleExpand = () => { setIsExpanded(!isExpanded); }; return ( <> {/* 原卡片:展开时仅作为占位 */} <div className={`ticket ${isExpanded ? 'ticket--expanded' : ''}`} onClick={handleToggleExpand} > <div className="ticket__header">Lorem ipsum dolor sit.</div> <div className="ticket__body"> <div className="ticket__tag">Emergent</div> <div className="ticket__text">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Asperiores enim assumenda incidunt esse repellat ipsa aliquid cum quam? Eveniet ullam suscipit ducimus eligendi blanditiis! Doloribus.</div> </div> </div> {/* 展开的弹窗卡片 */} {isExpanded && ( <div className="ticket__expanded-overlay" onClick={handleToggleExpand} > <div className="ticket__header">Lorem ipsum dolor sit.</div> <div className="ticket__body"> <div className="ticket__tag">Emergent</div> <div className="ticket__text">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Asperiores enim assumenda incidunt esse repellat ipsa aliquid cum quam? Eveniet ullam suscipit ducimus eligendi blanditiis! Doloribus.</div> </div> </div> )} </> ); }
关键优化点说明
- 消除布局抖动:原卡片保持高度不变,仅透明化,确保bento board中其他卡片位置完全不受影响
- GPU加速动画:固定定位的弹窗脱离文档流,动画仅触发自身图层渲染,避免全局重排
- 分层过渡效果:初始缩小、body隐藏用过渡动画,展开弹窗用关键帧动画,视觉衔接更自然
内容的提问来源于stack exchange,提问作者Punk1503
相关产品推荐
相关产品推荐

