jQuery Sortable不同高度区块网格布局空白填充问题求助
jQuery Sortable 仪表盘:解决大区块左侧空白无法填充的问题
我正在制作一个包含不同尺寸区块的jQuery Sortable仪表盘,目前遇到问题:小区块移动到大区块右侧时排序正常,但在大区块左侧操作时无法正常排序,希望让Item 6这类小区块能填充大区块旁的空白空间。
预览效果:
原代码
HTML
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> <section> <h2>Sortable Grid</h2> <ul class="grid"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li style="height: 200px;">Item 4</li> <li>Item 5</li> <li>Item 6</li> <li style="height: 200px;">Item 7</li> <li>Item 8</li> </ul> </section>
CSS
body { background: #20262E; padding: 20px; font-family: Helvetica; } .grid { margin: auto; padding: 0; width: 555px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; overflow: hidden; } .grid li { list-style: none; border: 1px solid #CCC; background: #F6F6F6; font-family: "Tahoma"; color: #1C94C4; margin: 5px; padding: 5px; line-height: 80px; float: left; width: 254px; height: 80px; text-align: center; }
JavaScript
$(".grid") .sortable({ connectWith: "li", tolerance: "intersect", opacity: 0.8, dropOnEmpty: true, revert: true, placeholder: "placeholder", forcePlaceholderSize: true, refreshPositions: true, forceHelperSize: true, }) .disableSelection()
解决方案
问题根源是jQuery UI Sortable默认的tolerance: intersect判断逻辑,加上float布局下大区块占据纵向空间,导致左侧空白区域无法被识别为可插入位置。通过以下调整解决:
修改Sortable参数与事件逻辑
将tolerance改为pointer,让拖拽时根据鼠标指针位置判断插入点,提升精准度;同时通过start和change事件动态调整占位符的尺寸与位置,适配大区块旁的空白。优化占位符样式
给占位符添加明确的样式,确保在拖拽时能清晰显示插入位置。规范元素样式(可选)
把内联高度样式改为类,提升代码可维护性。
修改后的完整代码
HTML
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> <section> <h2>Sortable Grid</h2> <ul class="grid"> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li class="large-item">Item 4</li> <li>Item 5</li> <li>Item 6</li> <li class="large-item">Item 7</li> <li>Item 8</li> </ul> </section>
CSS
body { background: #20262E; padding: 20px; font-family: Helvetica; } .grid { margin: auto; padding: 0; width: 555px; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; overflow: hidden; } .grid li { list-style: none; border: 1px solid #CCC; background: #F6F6F6; font-family: "Tahoma"; color: #1C94C4; margin: 5px; padding: 5px; line-height: 80px; float: left; width: 254px; height: 80px; text-align: center; } .large-item { height: 200px; } .placeholder { border: 1px dashed #666; background: rgba(255,255,255,0.3); margin: 5px; float: left; }
JavaScript
$(".grid") .sortable({ tolerance: "pointer", opacity: 0.8, dropOnEmpty: true, revert: 200, placeholder: "placeholder", forcePlaceholderSize: true, refreshPositions: true, forceHelperSize: true, start: function(event, ui) { // 同步占位符与拖拽元素的尺寸 ui.placeholder.height(ui.item.height()); ui.placeholder.width(ui.item.width()); }, change: function(event, ui) { const $placeholder = ui.placeholder; const $prevItem = $placeholder.prev(); // 若前一个元素是大区块,调整占位符不清除浮动,填充空白 if ($prevItem.length && $prevItem.hasClass("large-item")) { $placeholder.css("clear", "none"); } else { $placeholder.css("clear", "both"); } } }) .disableSelection();
说明
tolerance: pointer:让Sortable根据鼠标指针位置判断插入点,比intersect更适合不规则布局的场景。start事件:确保占位符和拖拽元素尺寸一致,避免占位符大小错乱。change事件:动态调整占位符的clear属性,当拖拽到高区块左侧时,允许占位符浮动到空白区域,而不是强制换行。
内容的提问来源于stack exchange,提问作者Germ Knol
相关产品推荐
相关产品推荐

