CSS Grid 本身不支持拖拽,排序依赖 DOM 顺序或 order/grid-row-column 动态调整;order 适合简单线性排序,grid-row/column 适合精准行列定位;需注意 placeholder、兼容性及 dragend 清理 transform。
原生 CSS Grid 本身不提供拖拽能力,grid-template-areas 和 grid-area 是静态声明式布局,无法响应拖拽时的实时位置变化。真正起作用的是 DOM 元素顺序 + grid-auto-flow + order 属性或显式 grid-row/grid-column 定位。拖拽排序的本质是动态调整元素在 DOM 中的顺序或其 CSS 排序权重,而非“移动 grid 单元格”。
order 实现轻量级拖拽排序适用于项目数量不多、不需要跨行/列复杂定位的场景。关键点在于:所有网格项需设置 display: grid 的父容器启用 grid-auto-flow: row(或 column),并统一设置 order 值,再通过 JS 动态交换 order 值触发重排。
order(如按 DOM 顺序设为 0, 1, 2…),否则默认值都是 0,交换无效pointer-events: none 到被拖元素,避免干扰 dragover 事件grid-row/grid-column 配合 order —— 二者冲突时后者可能被忽略const items = document.querySelectorAll('.grid-item');
items.forEach((item, i) => item.style.order = i);
// 拖拽结束时,根据目标索引更新所有 order
function updateOrder(newIndex) {
const orders = Array.from(items).map((_, i) => i);
// 简单示例:把 draggedItem 插入 newIndex 位置
const draggedIndex = Array.from(items).indexOf(draggedItem);
orders.splice(draggedIndex, 1);
orders.splice(newIndex, 0, draggedIndex);
items.forEach((item, i) => item.style.order = orders[i]);
}
grid-row/grid-column 实现精准定位拖拽适合需要固定行列位置、支持跨区域(grid-column: span 2)或与 grid-template-areas 配合的场景。此时不能依赖 order,而是直接读写 grid-row-start 和 grid-column-start 的内联样式。
grid-row: auto / auto 或 grid-row: 1 / -1 等显式值,避免 grid-row: span 1 导致计算混乱dragover 元素的 getBoundingClientRect() + 网格单元尺寸反推)grid-row 的解析比 Chrome 更严格,推荐统一用 grid-row-start + grid-row-end
// 假设已知目标单元格行列为 (row, col)
draggedItem.style.gridColumnStart = col;
draggedItem.style.gridRowStart = row;
// 若需跨格,再设 end 值
if (spanCol > 1) draggedItem.style.gridColumnEnd = `span ${spanCol}`;
if (spanRow > 1) draggedItem.style.gridRowEnd = `span ${spanRow}`;
用户拖动时若无视觉提示,会误以为操作失败。但 CSS Grid 本身不支持 “占位符” 元素(placeholder),必须手动插入一个空 并设置 visibility: hidden 或 opacity: 0,同时用 grid-row/grid-column 占据目标位置。

display: none —— 这会让 Grid 认为它不存在,布局塌陷dragstart 的 setData 支持有限,建议降级为 touchstart + 手动模拟grid,且 drag 事件行为异常,必须检测 CSS.supports('display', 'grid') 并提供 fallback最易被忽略的是:拖拽结束后未重置 transform: translate,导致后续点击事件偏移 —— 务必在 dragend 中清除所有临时 transform 样式。