用 SortableJS 实现拖拽排序时,为什么列表项拖动后位置不对?

欧阳文君 阅读 10

我用 SortableJS 做一个简单的拖拽排序功能,但拖完之后元素位置乱了,有时候还重叠。明明结构看起来没问题啊?

下面是我的 HTML 结构:

<ul id="sortable-list">
  <li class="item">Item 1</li>
  <li class="weird-item">Item 2</li>
  <li class="item">Item 3</li>
</ul>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.15.0/Sortable.min.js"></script>
<script>
  new Sortable(document.getElementById('sortable-list'));
</script>

是不是因为第二个 li 的 class 不一样导致的?但我试过统一 class 还是不行……

我来解答 赞 7 收藏
二维码
手机扫码查看
2 条解答
上官颖昕
我之前也遇到过这问题,不是 class 的锅,是 SortableJS 默认用的是元素的索引做排序依据,但你没指定 grouphandle,而且 HTML 里没写 draggable 属性——关键是你用的是原生 li,它本身不支持拖拽,得靠 SortableJS 加上,但如果你没设置 draggable 或者有 CSS 把 pointer-events 给禁了,就容易乱套。

最简单的 fix 是加个 draggable 属性,或者确保每个 li 是可拖拽的,比如这样:

new Sortable(document.getElementById('sortable-list'), {
draggable: '.item, .weird-item'
});


或者更省事点,直接把 draggable 加到 HTML 上:

<ul id="sortable-list">
<li class="item" draggable="true">Item 1</li>
<li class="weird-item" draggable="true">Item 2</li>
<li class="item" draggable="true">Item 3</li>
</ul>


要是还不行,八成是你页面里有其他 CSS 把 overflowpositiontransform 乱设了,导致占位符位置算错,建议先关掉所有自定义 CSS 试试。
点赞
2026-02-26 23:10
端木照涵
你这个问题我太熟悉了,当年我也踩过这个坑。SortableJS 默认是按 DOM 顺序拖拽的,但如果你的列表项里有隐藏元素、display:none 的块、或者高度计算异常(比如浮动没清除、flex 布局没处理好),它内部计算的 placeholder 位置就会偏移,拖完自然乱套。

不过你贴的这段 HTML 看起来确实没问题——那问题大概率出在 CSS 上,特别是 li 元素有没有设置 display: blockflex,或者有没有全局样式把 li 当作 inline 处理了?还有就是:你有没有给 ul 设置 padding-left: 0?有时候浏览器默认样式会让 ul 有缩进,拖拽时视觉上就“飘”了。

更关键的一点:你是不是在拖拽过程中动态增删了 DOM 节点?或者 li 里嵌套了其他可拖拽区域(比如里面又有 div 是 Sortable 的容器)?这种嵌套会直接导致 SortableJS 的内部索引错乱。

先试试这个最稳妥的初始化方式,把关键选项都写清楚:

new Sortable(document.getElementById('sortable-list'), {
animation: 150,
ghostClass: 'sortable-ghost', // 拖拽时的占位样式
chosenClass: 'sortable-chosen', // 选中项样式
dragClass: 'sortable-drag',
fallbackClass: 'sortable-fallback',
fallbackOnBody: true,
fallbackTolerance: 0
});


再配上点基础样式(避免布局错乱):

#sortable-list {
list-style: none;
padding-left: 0;
margin: 0;
}
#sortable-list .item,
#sortable-list .weird-item {
display: block;
padding: 10px;
margin-bottom: 5px;
background: #fff;
border: 1px solid #ddd;
cursor: move;
}


如果还是乱,打开浏览器开发者工具,看拖拽时生成的 <li class="sortable-ghost"> 元素是不是在正确位置——如果它停在了错误位置,那八成是高度计算问题。

对了,顺便说一句:插件可以,但别太依赖 CDN 版本,有时候缓存了旧版会出奇效(不是,是出 bug)……建议本地装个 npm i sortablejs 用模块化版本,可控性高不少。
点赞 3
2026-02-24 06:09