使用slideToggle()逐步减少容器边距无效问题排查
为什么slideToggle的progress回调中修改margin不生效?
这个问题我之前也碰到过,核心原因其实是jQuery的slideToggle动画本身就会自动管理元素的margin、padding这些间距属性,你的自定义修改会被它的内部动画逻辑直接覆盖掉。
具体原因拆解:
- slideToggle(包括slideUp/slideDown)的本质是通过逐步修改元素的
height,同时自动调整margin-top、margin-bottom、padding-top、padding-bottom来实现平滑的收起/展开效果。 - 在动画的每一个进度步骤中,jQuery都会重新计算并设置这些样式属性,你在
progress回调里用container.css()设置的margin值,刚设置完就会被jQuery紧接着的动画步骤给覆盖,所以页面上看不到变化,complete回调里自然也保留的是动画最终的默认margin值。 - 你打印的
newMarginTop值正常,是因为那只是你计算的变量值,并不是实际DOM上已经生效的样式。
解决方案:自定义动画替代slideToggle
要实现“收起/展开时按比例减少margin”的效果,我们可以放弃slideToggle,改用animate()直接同时控制height和margin的变化,这样能完全掌控动画过程:
$(document).ready(function() { $("#btn").click(function() { doIt(); }); }); function doIt() { var container = $("#c2"); // 用parseInt更安全,避免单位解析问题 var maxMarginTop = parseInt(container.css("marginTop"), 10); var maxMarginBottom = parseInt(container.css("marginBottom"), 10); var originalHeight = container.height(); // 判断元素当前状态,确定动画目标值 var isVisible = container.is(":visible"); var targetHeight = isVisible ? 0 : originalHeight; var targetMarginTop = isVisible ? 0 : maxMarginTop; var targetMarginBottom = isVisible ? 0 : maxMarginBottom; container.animate({ height: targetHeight, marginTop: targetMarginTop, marginBottom: targetMarginBottom }, { duration: 2000, complete: function() { // 只有收起后才移除元素 if (isVisible) { container.remove(); } } }); }
.container { margin-top: 20px; margin-bottom: 20px; height: 20px; width: 100px; background: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <button id="btn">Do it</button> <div class="container" id="c1"></div> <div class="container" id="c2"></div> <div class="container" id="c3"></div>
这样修改后,动画过程中height和margin会同步按比例变化,完全符合你的需求,而且不会被内部逻辑覆盖。
内容的提问来源于stack exchange,提问作者peterHasemann
相关产品推荐
相关产品推荐

