求助:JavaScript多Toast通知自定义消失时间及层级问题修复
修复Toast通知的问题及代码优化建议
问题修复方案
1. 解决多个Toast被覆盖的问题
- 为每个Toast添加垂直间距,避免堆叠重叠
- 容器的
z-index仅在所有Toast都移除后才调整,确保后续Toast始终处于顶层
2. 所有Toast消失后再隐藏容器
移除单个Toast时检查容器内剩余元素数量,只有当容器为空时才隐藏容器(调整z-index)
3. 支持独立设置每个Toast的消失时间
修改toastNotification函数,新增duration参数(默认值5000ms),允许调用时自定义单条Toast的显示时长
4. 解决容器遮挡按钮的问题
- 给容器添加
pointer-events: none,仅让Toast本身响应点击事件,下方按钮可正常触发点击 - 调整容器
bottom值,避开页面底部的按钮区域
优化后的完整代码
JavaScript
function toastNotification(msg, duration = 5000) { const alertContainer = document.querySelector(".container-alert"); // 克隆模板元素,避免重复创建DOM节点 const toastTemplate = document.querySelector(".alert-template"); const newAlert = toastTemplate.cloneNode(true); newAlert.classList.remove("alert-template", "hide"); newAlert.classList.add("alert", "show"); // 设置提示消息文本 newAlert.querySelector(".msg").textContent = msg; // 统一Toast移除逻辑 const removeToast = () => { newAlert.classList.remove("show"); newAlert.classList.add("hide"); setTimeout(() => { alertContainer.removeChild(newAlert); // 容器只剩模板元素时,隐藏容器 if (alertContainer.children.length === 1) { alertContainer.style.zIndex = "-1"; } }, 300); // 匹配动画过渡时长 }; // 手动关闭按钮事件 const closeBtn = newAlert.querySelector(".close-btn"); closeBtn.addEventListener("click", removeToast); // 自动消失定时器 setTimeout(removeToast, duration); alertContainer.appendChild(newAlert); alertContainer.style.zIndex = "9999"; } // 测试调用示例 toastNotification("商品已加入购物车", 4000); setTimeout(() => toastNotification("库存不足,请选择其他规格", 6000), 1000);
CSS
.container-alert { width: 30rem; position: fixed; right: 20px; bottom: 80px; /* 调整位置避开底部按钮 */ display: flex; flex-direction: column; gap: 12px; /* Toast之间的垂直间距 */ padding: 20px; z-index: -1; pointer-events: none; /* 容器不拦截点击,下方元素可正常交互 */ } .alert { overflow: hidden; opacity: 0; transform: translateY(20px); transition: all 0.3s ease; width: 27rem; height: 5rem; font-weight: 500; box-shadow: 0 0 20px rgba(0, 0, 0, 0.15); display: flex; align-items: center; padding: 0 16px; background-color: #fff; pointer-events: auto; /* 仅Toast本身响应点击 */ } .alert.show { opacity: 1; transform: translateY(0); } .alert.hide { opacity: 0; transform: translateY(20px); } .alert-template { display: none; /* 隐藏模板元素,仅用于克隆 */ } .close-btn { margin-left: auto; cursor: pointer; color: #666; font-size: 1.2rem; } .close-btn:hover { color: #333; }
HTML
<div class="container-alert"> <!-- Toast模板,仅用于克隆生成新通知 --> <div class="alert alert-template hide"> <svg xmlns="http://www.w3.org/2000/svg" width="1.5rem" height="1.5rem" viewBox="0 0 48 48"> <defs> <mask id="ipSCheckOne0"> <g fill="none" stroke-linejoin="round" stroke-width="4"> <path fill="#fff" stroke="#fff" d="M24 44a19.937 19.937 0 0 0 14.142-5.858A19.937 19.937 0 0 0 44 24a19.938 19.938 0 0 0-5.858-14.142A19.937 19.937 0 0 0 24 4A19.938 19.938 0 0 0 9.858 9.858A19.938 19.938 0 0 0 4 24a19.937 19.937 0 0 0 5.858 14.142A19.938 19.938 0 0 0 24 44Z"/> <path stroke="#000" stroke-linecap="round" d="m16 24l6 6l12-12"/> </g> </mask> </defs> <path fill="#30d300" d="M0 0h48v48H0z" mask="url(#ipSCheckOne0)"/> </svg> <span class="msg"></span> <div class="close-btn"> <span class="fas fa-times"></span> </div> </div> </div> <!-- 示例底部按钮 --> <button style="position: fixed; bottom: 20px; right: 20px; padding: 12px 24px;">加入购物车</button>
额外优化说明
- 使用模板克隆替代手动创建DOM元素,代码更简洁易维护
- 添加平滑的显隐动画(
translateY+opacity),提升视觉体验 - 统一动画过渡时长为300ms,避免定时器时间不一致导致的逻辑混乱
- 容器使用
gap控制Toast间距,布局更规整
内容的提问来源于stack exchange,提问作者Senshi04
相关产品推荐
相关产品推荐

