如何实现点击时始终沿同一方向旋转的CSS翻转卡片?
实现点击始终沿X轴同向旋转的CSS翻转卡片
我想制作一个CSS翻转卡片,要求点击时始终沿X轴同一方向旋转,但目前的代码只能实现首次点击旋转180°,再次点击反向转回,不符合预期。之前找到过依赖jQuery的方案,但不够简洁,想要纯CSS或更直接的实现方式。
现有代码如下:
JavaScript
function flip(id) { document.getElementById(id).querySelector(".flip-content").classList.toggle("flipped"); }
CSS
.flip-card { background: transparent; perspective: 1000px; width: 200px; height: 200px; transition: transform 0.3s; transform: scale(90%); } .flip-content { width: 100%; height: 100%; transform-style: preserve-3d; transition: all 0.6s; box-shadow: 0 20px 32px 0 rgba(0, 0, 0, 0.2); } .flip-content.flipped { transform: rotateX(180deg); box-shadow: 0 -20px 32px 0 rgba(0, 0, 0, 0.2); }
HTML
<div id="flip" class="flip-card" onclick="flip('flip')"> <div class="flip-content"> </div> </div>
解决方案
方案一:简化JavaScript实现(推荐)
核心思路是累加旋转角度,而非切换类名。每次点击时读取当前旋转角度,叠加180°后重新设置,同时同步调整阴影方向:
修改后的代码
JavaScript
function flip(id) { const content = document.getElementById(id).querySelector(".flip-content"); // 从自定义属性读取当前旋转角度,初始为0 let currentRotate = parseInt(content.dataset.rotateX || 0); // 累加180° const newRotate = currentRotate + 180; // 设置新的旋转值 content.style.transform = `rotateX(${newRotate}deg)`; // 更新自定义属性记录当前角度 content.dataset.rotateX = newRotate; // 根据角度奇偶性切换阴影方向 content.style.boxShadow = newRotate % 360 >= 180 ? "0 -20px 32px 0 rgba(0, 0, 0, 0.2)" : "0 20px 32px 0 rgba(0, 0, 0, 0.2)"; }
CSS(移除.flipped类)
.flip-card { background: transparent; perspective: 1000px; width: 200px; height: 200px; transition: transform 0.3s; transform: scale(90%); cursor: pointer; /* 添加点击光标提示 */ } .flip-content { width: 100%; height: 100%; transform-style: preserve-3d; transition: all 0.6s; box-shadow: 0 20px 32px 0 rgba(0, 0, 0, 0.2); }
HTML(无需修改)
<div id="flip" class="flip-card" onclick="flip('flip')"> <div class="flip-content"> </div> </div>
方案二:纯CSS Hack(局限性说明)
纯CSS无法直接实现角度累加,可通过checkbox结合动画模拟,但需注意:此方案依赖动画触发时机,无法真正记录累计角度,多次点击后可能出现状态不一致。
代码示例
HTML
<input type="checkbox" id="flip-trigger" class="flip-trigger"> <label for="flip-trigger" class="flip-card"> <div class="flip-content"></div> </label>
CSS
.flip-trigger { display: none; } .flip-card { background: transparent; perspective: 1000px; width: 200px; height: 200px; transform: scale(90%); display: block; cursor: pointer; } .flip-content { width: 100%; height: 100%; transform-style: preserve-3d; transition: box-shadow 0.6s; box-shadow: 0 20px 32px 0 rgba(0, 0, 0, 0.2); } @keyframes flip-forward { to { transform: rotateX(180deg); box-shadow: 0 -20px 32px 0 rgba(0, 0, 0, 0.2); } } @keyframes flip-forward-again { from { transform: rotateX(180deg); } to { transform: rotateX(360deg); box-shadow: 0 20px 32px 0 rgba(0, 0, 0, 0.2); } } .flip-trigger:checked + .flip-card .flip-content { animation: flip-forward 0.6s forwards; } .flip-trigger:checked:active + .flip-card .flip-content { animation: flip-forward-again 0.6s forwards; }
内容的提问来源于stack exchange,提问作者julcs
相关产品推荐
相关产品推荐

