无jQuery实现图片追加至模态查看器后放回原容器的方法
问题排查
两个bug的直接诱因:
- 事件绑定范围错误:
document.querySelector("img")仅匹配DOM中第一个<img>节点,其余图片未绑定点击监听,自然无法触发查看逻辑;同时代码中判断模态框显隐时误用赋值符=代替全等判断符===,导致显隐判断逻辑完全失效。 - 节点还原逻辑缺失:关闭模态框时仅将图片节点从查看器中移除,未记录图片原始位置信息,无法将节点插回原位置,直接导致画廊出现空位。
修复逻辑
- 遍历所有图片节点统一绑定点击事件,不再只选中第一张图
- 打开模态框时,记录当前点击的图片、图片的原始父容器、图片在原位置的下一个相邻兄弟节点,用于后续精准归位
- 修复显隐判断的符号错误,关闭模态框时将图片按记录的位置插回原容器,同时重置图片样式,避免样式污染
- 全程使用原生DOM API实现,无jQuery依赖
修复后完整代码
JS部分
// 选中所有图片、模态框、关闭按钮 const allImgs = document.querySelectorAll(".container img"); const viewer = document.getElementById("viewer"); const closeBtn = document.getElementById("closeViewer"); // 全局存储当前激活的图片和位置信息 let activeImg = null; let originalParent = null; let originalNextSibling = null; // 给所有图片绑定点击事件 allImgs.forEach(img => { img.addEventListener("click", viewImg); }); function viewImg(e) { // 修正判断逻辑:全等判断模态框是否隐藏,单等号是赋值不是比较 if (viewer.style.visibility !== "visible") { activeImg = e.target; originalParent = activeImg.parentNode; originalNextSibling = activeImg.nextSibling; // 把图片移到查看器 viewer.appendChild(activeImg); activeImg.style.width = "60%"; viewer.style.visibility = "visible"; } } function closeViewer() { if (viewer.style.visibility === "visible") { viewer.style.visibility = "hidden"; // 把图片插回原位置:如果原来有下一个兄弟节点,就插在它前面,否则直接追加到原容器末尾 if (originalNextSibling) { originalParent.insertBefore(activeImg, originalNextSibling); } else { originalParent.appendChild(activeImg); } // 重置图片样式,回到画廊里的默认尺寸 activeImg.style.width = "100%"; // 清空临时存储的节点信息 activeImg = null; originalParent = null; originalNextSibling = null; } } // 绑定关闭按钮事件 closeBtn.addEventListener("click", closeViewer); // 可选:点击模态框遮罩层也能关闭,不需要可以删除 viewer.addEventListener("click", (e) => { if (e.target === viewer) { closeViewer(); } });
CSS部分(修正了原代码无效属性和颜色写法错误)
.container { line-height: 0; column-count: 3; column-gap: 0; column-fill: balance; } .container img { width: 100%; } .container img:hover { scale: 1.1; transition: 0.5s; cursor: pointer; } .viewer { visibility: hidden; display: flex; justify-content: center; align-items: center; position: fixed; top: 0; left: 0; height: 100%; width: 100%; /* 修正原代码颜色值写法,透明背景需用rgba */ background: rgba(255, 0, 0, 0.5); } .closeViewer { color: #000; background: rgba(255, 255, 255, 0.5); position: absolute; top: 100px; right: 100px; font-family: Arial, Helvetica, sans-serif; font-size: 3rem; padding: 0 10px; cursor: pointer; border: none; }
HTML部分(移除冗余内联事件,其余结构保持不变)
<html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>simple gallery</title> <link rel="stylesheet" href="test.css"> </head> <body> <div class="container" id="container"> <img class="img" src="https://images.freeimages.com/images/large-previews/a31/colorful-umbrella-1176220.jpg"> <img class="img" src="https://images.freeimages.com/images/large-previews/9e6/abstract-polygonal-low-poly-photos-texture-3-636190.jpg"> <img class="img" src="https://images.freeimages.com/images/large-previews/aa8/evening-01-1055813.jpg"> <img class="img" src="https://live.staticflickr.com/3437/3403778548_15f48ab99e_b.jpg"> <img class="img" src="https://cdn.pixabay.com/photo/2017/07/25/01/22/cat-2536662_960_720.jpg"> <img class="img" src="https://cdn.pixabay.com/photo/2018/08/01/19/35/wolf-3577956_960_720.jpg"> <img class="img" src="https://live.staticflickr.com/3437/3403778548_15f48ab99e_b.jpg"> <img class="img" src="https://cdn.pixabay.com/photo/2017/07/25/01/22/cat-2536662_960_720.jpg"> <img class="img" src="https://cdn.pixabay.com/photo/2018/08/01/19/35/wolf-3577956_960_720.jpg"> <img class="img" src="https://images.freeimages.com/images/large-previews/a31/colorful-umbrella-1176220.jpg"> <img class="img" src="https://images.freeimages.com/images/large-previews/9e6/abstract-polygonal-low-poly-photos-texture-3-636190.jpg"> <img class="img" src="https://images.freeimages.com/images/large-previews/aa8/evening-01-1055813.jpg"> </div> <div class="viewer" id="viewer"> <button class="closeViewer" id="closeViewer">X</button> </div> <script src="./test.js"></script> </body> </html>
关键实现说明
- 用
nextSibling记录原位置的参考节点,配合insertBefore可以100%还原图片在瀑布流中的原始位置,不会出现排序错乱 - 图片移回原容器后主动重置width样式,避免模态框里设置的60%宽度被带回画廊,导致布局错乱
- 删掉了原CSS中无效的
left:120%属性(未给img设置定位时left属性不生效),给模态框补充left:0避免fixed定位偏移
内容的提问来源于stack exchange,提问作者MaDragon7
相关产品推荐
相关产品推荐

