javascript - 使弹出 div 可堆叠

标签 javascript html css frontend

大家好,我有一个弹出窗口,我通过函数将其插入到主 div 中。如果我只调用它一次,一切都可以正常工作,但我想做的是在每个错误上调用它,以便每个错误都有自己的弹出窗口。如果我现在这样做,每个弹出窗口都会覆盖。

如何使此弹出窗口可堆叠,以便在有多个弹出窗口时它们可以位于彼此下方?

代码在这里

https://jsfiddle.net/s86nw4ct/6/

注意我没有使用任何前端框架

let timer1, timer2;
const wrapper = document.getElementById('wrapper')



function showPopUp(title, body) {
  const popup_data =
    `<div class="toast active">
            <div class="toast-content">
                <i class="fas fa-solid fa-check check"></i>
                <div class="message">
                    <span id="text_title" class="text text-1">${title}</span>
                    <span id="text_body" class="text text-2">${body}</span>
                </div>
            </div>
            <i class="fa-solid fa-xmark close"></i>
            <div class="progress active"></div>
        </div>`

  wrapper.insertAdjacentHTML('beforeend', popup_data);

  const toast = document.querySelector(".toast");
  (closeIcon = document.querySelector(".close")),
  (progress = document.querySelector(".progress"));
  toast.classList.add("active");
  progress.classList.add("active");

  timer1 = setTimeout(() => {
    toast.classList.remove("active");
  }, 5000);

  timer2 = setTimeout(() => {
    progress.classList.remove("active");
  }, 5300);

  closeIcon.addEventListener("click", () => {
    toast.classList.remove("active");

    setTimeout(() => {
      progress.classList.remove("active");
    }, 300);

    clearTimeout(timer1);
    clearTimeout(timer2);
  });
}
* {
  margin: 0;
  padding: 0;
  overflow: hidden;
}

#wrapper {
  height: 100vh;
  width: 100vw;
}


/*popup part */

.toast:not(.showing):not(.show) {
  /*bootsratp overide */
  opacity: 1;
}

.toast {
  position: absolute;
  z-index: 10;
  top: 25px;
  right: 30px;
  border-radius: 12px;
  background: #fff;
  padding: 20px 35px 20px 25px;
  box-shadow: 0 6px 20px -5px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  transform: translateX(calc(100% + 30px));
  transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.35);
}

.toast.active {
  transform: translateX(0%);
}

.toast .toast-content {
  display: flex;
  align-items: center;
}

.toast-content .check {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 35px;
  min-width: 35px;
  background-color: #4070f4;
  color: #fff;
  font-size: 20px;
  border-radius: 50%;
}

.toast-content .message {
  display: flex;
  flex-direction: column;
  margin: 0 20px;
}

.message .text {
  font-size: 16px;
  font-weight: 400;
  color: #666666;
}

.message .text.text-1 {
  font-weight: 600;
  color: #333;
}

.toast .close {
  position: absolute;
  top: 10px;
  right: 15px;
  padding: 5px;
  cursor: pointer;
  opacity: 0.7;
}

.toast .close:hover {
  opacity: 1;
}

.toast .progress {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 3px;
  width: 100%;
}

.toast .progress:before {
  content: "";
  position: absolute;
  bottom: 0;
  right: 0;
  height: 100%;
  width: 100%;
  background-color: #4070f4;
}

.progress.active:before {
  animation: progress 5s linear forwards;
}

@keyframes progress {
  100% {
    right: 100%;
  }
}

button {
  padding: 12px 20px;
  font-size: 20px;
  outline: none;
  border: none;
  background-color: #4070f4;
  color: #fff;
  border-radius: 6px;
  cursor: pointer;
  transition: 0.3s;
}

button:hover {
  background-color: #0e4bf1;
}

.toast.active~button {
  pointer-events: none;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div id="wrapper">
  <button type="button" onclick="showPopUp('test','body')">test</button>
</div>

最佳答案

每个 .toast 元素都位于完全相同的绝对位置,因此您将它们全部堆叠在一起。更好的方法是为所有 toast 元素提供一个包装/容器元素。你设置它的绝对位置,然后只需在其中添加 toast 元素,它们不需要有任何定位,它们只需具有标准的 block 级元素堆叠即可。

let timer1, timer2;
const wrapper = document.getElementById('toast-container')

function showPopUp(title, body) {
  const popup_data =
    `<div class="toast active">
            <div class="toast-content">
                <i class="fas fa-solid fa-check check"></i>
                <div class="message">
                    <span id="text_title" class="text text-1">${title}</span>
                    <span id="text_body" class="text text-2">${body}</span>
                </div>
            </div>
            <i class="fa-solid fa-xmark close"></i>
            <div class="progress active"></div>
        </div>`

  wrapper.insertAdjacentHTML('beforeend', popup_data);

  const toast = document.querySelector(".toast");
  (closeIcon = document.querySelector(".close")),
  (progress = document.querySelector(".progress"));
  toast.classList.add("active");
  progress.classList.add("active");

  timer1 = setTimeout(() => {
    toast.classList.remove("active");
  }, 5000);

  timer2 = setTimeout(() => {
    progress.classList.remove("active");
  }, 5300);

  closeIcon.addEventListener("click", () => {
    toast.classList.remove("active");

    setTimeout(() => {
      progress.classList.remove("active");
    }, 300);

    clearTimeout(timer1);
    clearTimeout(timer2);
  });
}
* {
  margin: 0;
  padding: 0;
  overflow: hidden;
}

#wrapper {
  height: 100vh;
  width: 100vw;
}


/*popup part */

#toast-container {
  position: absolute;
  z-index: 10;
  top: 25px;
  right: 30px;
}

.toast:not(.showing):not(.show) {
  /*bootsratp overide */
  opacity: 1;
}

.toast {
  border-radius: 12px;
  background: #fff;
  padding: 20px 35px 20px 25px;
  box-shadow: 0 6px 20px -5px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  transform: translateX(calc(100% + 30px));
  transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.35);
}

.toast.active {
  transform: translateX(0%);
}

.toast .toast-content {
  display: flex;
  align-items: center;
}

.toast-content .check {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 35px;
  min-width: 35px;
  background-color: #4070f4;
  color: #fff;
  font-size: 20px;
  border-radius: 50%;
}

.toast-content .message {
  display: flex;
  flex-direction: column;
  margin: 0 20px;
}

.message .text {
  font-size: 16px;
  font-weight: 400;
  color: #666666;
}

.message .text.text-1 {
  font-weight: 600;
  color: #333;
}

.toast .close {
  position: absolute;
  top: 10px;
  right: 15px;
  padding: 5px;
  cursor: pointer;
  opacity: 0.7;
}

.toast .close:hover {
  opacity: 1;
}

.toast .progress {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 3px;
  width: 100%;
}

.toast .progress:before {
  content: "";
  position: absolute;
  bottom: 0;
  right: 0;
  height: 100%;
  width: 100%;
  background-color: #4070f4;
}

.progress.active:before {
  animation: progress 5s linear forwards;
}

@keyframes progress {
  100% {
    right: 100%;
  }
}

button {
  padding: 12px 20px;
  font-size: 20px;
  outline: none;
  border: none;
  background-color: #4070f4;
  color: #fff;
  border-radius: 6px;
  cursor: pointer;
  transition: 0.3s;
}

button:hover {
  background-color: #0e4bf1;
}

.toast.active~button {
  pointer-events: none;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" integrity="sha512-iecdLmaskl7CVkqkXNQ/ZH/XLlvWZOJyj7Yy7tcenmpD1ypASozpmT/E0iPtmFIB46ZmdtAc9eNBvH0H/ZpiBw==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<div id="wrapper">
  <div id="toast-container"></div>
  <button type="button" onclick="showPopUp('test','body')">test</button>
</div>

关于javascript - 使弹出 div 可堆叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76086633/

相关文章:

javascript - 如何放大到div的中心

javascript - 如何使用 JavaScript 动态创建 HTML 标签(带有内容)?

javascript - 当 Yeoman 上的前一个提示为真时,如何执行其他提示?

html - 占位符在输入字段内自动换行

javascript - 使用 Shadow DOM 有什么缺点?

html - 如何使用媒体查询以 block 显示方式获取表

css - 纯 CSS 悬停框移动页面文本

html - Bootstrap 输入,textarea float 标签 css

javascript - Angular 4 dblclick 事件在移动 View 中不起作用

php - IF 语句不改变变量的结果