QCM选项点击时Div尺寸异常波动及Check切换平滑优化问题
QCM选项点击抖动与勾选平滑过渡的解决方案
解决点击时的布局抖动问题
你遇到的点击选项先变大再恢复的问题,根源是动态添加.check元素时,.rep容器的宽度会被新增内容临时撑开,之后受限于max-width又收缩,造成视觉上的抖动。解决办法很简单:给.rep设置固定宽度,彻底避免内容变化影响容器尺寸:
- 将
.rep的max-width:15%替换为width:170px(和你设置的min-width一致,保证布局稳定) - 或者用
flex: 0 0 170px,明确固定元素的基准宽度,不随内容伸缩
实现勾选标记的平滑过渡
动态创建/删除DOM元素不仅容易导致布局波动,也很难做平滑过渡。换个思路:预先在每个选项里放好.check,通过CSS类控制显示状态,配合过渡动画:
- 每个
.rep里提前加入.check元素,初始设为透明+偏移状态 - 给
.check添加过渡属性,让显示/隐藏有动画效果 - 点击时只需要给目标选项加类,移除其他选项的类即可
修改后的完整代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.3/jquery.min.js" integrity="sha512-STof4xm1wgkfm7heWqFJVn58Hm3EtS31XFaagaa8VMReCXAkQnJZ+jEy8PCC/iT18dFy95WcExNHFTqLyp72eQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <div class="container"> <div class="question_title"> <p>Je suis une Question, quelle est votre reponse ?</p> </div> <div class="container_reps"> <div class="rep"> <span class="dot_rep">A</span> <p class="text_rep">Reponse 1</p> <div class="check"><object data="check.svg" width="20" > </object></div> </div> <div class="rep"> <span class="dot_rep">B</span> <p class="text_rep">Reponse 2</p> <div class="check"><object data="check.svg" width="20" > </object></div> </div> <div class="rep"> <span class="dot_rep">C</span> <p class="text_rep">Reponse 3</p> <div class="check"><object data="check.svg" width="20" > </object></div> </div> <div class="rep"> <span class="dot_rep">D</span> <p class="text_rep">Reponse 4</p> <div class="check"><object data="check.svg" width="20" > </object></div> </div> </div> </div>
CSS
.container { padding: 5%; display: grid; gap: 20px; grid-template-columns: 1fr; } .question_title { font-size: 18px; font-weight: 500; text-align: center; } .container_reps { display: grid; justify-items: center; gap: 10px; } .rep { display: flex; align-items: center; border: 1px solid black; padding: 0 10px; width: 170px; /* 固定宽度,解决布局抖动 */ border-radius: 10px; cursor: pointer; overflow: hidden; } .dot_rep { background-color: black; color: white; margin-right: 7px; padding: 5px 10px; border-radius: 5px; } .text_rep { font-weight: 700; flex-grow: 1; /* 让文本占满剩余空间,自动把.check推到右侧 */ } .check { opacity: 0; transform: translateX(10px); /* 初始向右偏移一点 */ transition: opacity 0.3s ease, transform 0.3s ease; /* 过渡动画 */ } .rep.active .check { opacity: 1; transform: translateX(0); /* 选中时回到原位 */ }
JavaScript
const reps = document.getElementsByClassName('rep'); [].forEach.call(reps, function(rep) { $(rep).click(function() { // 移除所有选项的激活状态 [].forEach.call(reps, item => $(item).removeClass('active')); // 给当前点击的选项添加激活状态 $(rep).addClass('active'); }) })
关键修改点说明
- 固定
.rep宽度后,无论内容怎么变,容器尺寸都不会波动,彻底解决抖动问题 - 预先嵌入
.check元素,用CSS类切换状态,避免DOM增删操作带来的性能损耗和布局波动 - 用
opacity+transform实现平滑过渡,比直接display:none/block的生硬切换更自然 flex-grow:1让文本自动占据剩余空间,替代原来的margin-left:20%,布局更稳定,适配不同长度的文本
内容的提问来源于stack exchange,提问作者Wlid El Bahdja
相关产品推荐
相关产品推荐

