如何使用CSS实现弹窗从点击卡片位置弹出与缩回的开闭动画
实现方案
原代码无法实现平滑过渡的核心原因是.active类直接修改了position、宽高等布局属性,会触发布局突变,无法触发连贯的过渡动画。改为使用transform做位移和缩放即可实现需求效果,完整可运行代码如下:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="parent"> <div class="child">1</div> <div class="child">2</div> <div class="child">3</div> <div class="child">4</div> </div>
* { box-sizing: border-box; } .parent { margin: 40px auto; width: 400px; height: 600px; border: 1px solid #3b3b3b; border-radius: 20px; padding: 20px 40px; position: relative; display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; } .child { display: flex; justify-content: center; align-items: center; border: 1px solid #000; border-radius: 40px; cursor: pointer; transform-origin: 0 0; will-change: transform; transition: all 0.5s ease-in-out; } .child.active { transform: translate(var(--offset-x), var(--offset-y)) scale(var(--scale-x), var(--scale-y)); z-index: 10; border: 1px solid red; background: #000; border-radius: 20px; color: #fff; }
$(".child").on("click", function() { // 点击已激活卡片,直接关闭 if ($(this).hasClass('active')) { $(this).removeClass('active'); return; } // 先清空所有激活状态 $(".child").removeClass("active"); // 获取父容器和当前卡片的尺寸位置 const parentRect = $('.parent')[0].getBoundingClientRect(); const childRect = this.getBoundingClientRect(); // 计算位移偏移和缩放比例 const offsetX = childRect.left - parentRect.left; const offsetY = childRect.top - parentRect.top; const scaleX = parentRect.width / childRect.width; const scaleY = parentRect.height / childRect.height; // 写入CSS变量供动画使用 $(this).css({ '--offset-x': `${-offsetX}px`, '--offset-y': `${-offsetY}px`, '--scale-x': scaleX, '--scale-y': scaleY }); // 激活当前卡片 $(this).addClass('active'); })
效果说明
- 点击任意卡片,会从卡片当前位置平滑放大到铺满整个父容器
- 再次点击已放大的卡片,会平滑缩小回到原卡片所在位置
- 动画全程基于transform实现,不会触发布局重排,过渡效果流畅
内容的提问来源于stack exchange,提问作者Anil
相关产品推荐
相关产品推荐

