You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 11:05:31