使用Jekyll和Bootstrap的模态弹窗仅显示最后一项内容的问题排查
问题根源分析
你遇到的核心问题一眼就能看出来——循环生成的所有弹窗和触发按钮都共用了相同的类名,点击任意一个「Open」按钮时,jQuery会给所有.popup-content和.popup-overlay添加active类。由于DOM中后面的元素会覆盖前面的,所以你看到的永远是最后一个stone的内容。
修复方案
我们需要给每个弹窗和对应的触发按钮绑定唯一标识,让点击事件只作用于对应的弹窗,一步步来改:
1. 修正HTML结构(添加唯一标识)
先调整循环里的代码,给每个弹窗容器加唯一ID,同时给触发按钮添加data-target属性关联对应的弹窗:
{% for stone in site.data.stones %} <!-- 每个stone对应唯一的遮罩层 --> <div class="popup-overlay" id="overlay-{{ stone.gem | slugify }}"> <!-- 每个stone对应唯一的弹窗内容 --> <div class="popup-content" id="content-{{ stone.gem | slugify }}"> <h1>{{ stone.color }}</h1> <button class="close" data-target="{{ stone.gem | slugify }}">Close</button> </div> </div> <!-- 触发弹窗的卡片 --> <div class="popup-hold"> <h1>{{ stone.gem }}</h1> <button class="open" data-target="{{ stone.gem | slugify }}">Open</button> </div> {% endfor %}
这里用stone.gem | slugify生成安全的唯一标识(自动把特殊字符转成连字符,避免ID格式问题),每个按钮的data-target对应弹窗的ID前缀。
2. 修改jQuery逻辑(关联按钮与对应弹窗)
更新JS代码,点击按钮时通过data-target精准找到对应的弹窗,而不是操作所有同类别名的元素:
$(document).ready(function(e) { // 打开弹窗:获取当前按钮的target,只激活对应弹窗和遮罩 $(".open").on("click", function(){ const target = $(this).data('target'); $(`#overlay-${target}, #content-${target}`).addClass("active"); }); // 关闭弹窗:获取当前按钮的target,只移除对应弹窗和遮罩的active类 $(".close").on("click", function(){ const target = $(this).data('target'); $(`#overlay-${target}, #content-${target}`).removeClass("active"); }); // 点击遮罩关闭当前弹窗 $(".popup-overlay").on("click", function(){ $(this).removeClass("active"); $(this).find(".popup-content").removeClass("active"); }); });
这里的关键改动:
- 用
$(this).data('target')拿到当前点击按钮对应的唯一标识 - 通过模板字符串
$(#overlay-${target})精准定位到对应弹窗元素 - 点击遮罩时直接操作当前遮罩及其子元素,不需要额外标识
3. CSS优化(可选,提升体验)
你的基础CSS没问题,建议把遮罩层改成固定定位,让弹窗始终居中显示:
.popup-overlay { visibility: hidden; position: fixed; /* 替换absolute为fixed */ top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); /* 半透明灰更友好 */ display: flex; align-items: center; justify-content: center; } .popup-content { visibility: hidden; background: white; padding: 2rem; border-radius: 8px; } /* 保留你原来的其他样式 */ .popup-content.active { visibility: visible; z-index: 1; } .popup-hold { height: 330px; border: 2px solid black; }
为什么原来的代码不行?
原来的$(".popup-overlay, .popup-content").addClass("active")会选中DOM中所有带这些类名的元素,循环生成的3个弹窗会同时被激活,而最后一个弹窗在DOM树最下方,会显示在最上层,看起来就像所有按钮都打开同一个弹窗。
内容的提问来源于stack exchange,提问作者RottenZulu
相关产品推荐
相关产品推荐

