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

如何为JavaScript Modal添加关闭时的动画效果(含遮罩)?

为底部Modal添加关闭动画

问题说明

从W3Schools获取的底部Modal组件,点击触发按钮时,Modal内容会从底部滑入、遮罩层淡入;但点击关闭按钮或Modal外部区域时,Modal直接消失,无动画效果。需要为关闭过程添加匹配的动画,让显示和隐藏都有流畅的过渡。

实现思路

  • 避免直接隐藏:不能在关闭时立刻设置display: none,否则动画无法执行。需要先触发关闭动画,等动画完成后再隐藏Modal。
  • 添加关闭动画关键帧:为遮罩层添加fadeOut淡出动画,为Modal内容添加slideOut滑出动画,与打开时的fadeIn、slideIn方向完全反向,保证视觉一致性。
  • 统一关闭逻辑:封装closeModal函数,通过添加CSS类触发动画,监听animationend事件,动画结束后隐藏Modal并移除动画类,避免影响下次打开。
  • 准确判断外部点击:直接判断点击目标是否为Modal遮罩层,避免误触发关闭逻辑。

完整代码

HTML

<h2>底部Modal</h2>

<!-- 触发按钮 -->
<button id="myBtn">打开Modal</button>

<!-- Modal容器 -->
<div id="myModal" class="modal">
  <!-- Modal内容 -->
  <div class="modal-content">
    <div class="modal-header">
      <span class="close">&times;</span>
      <h2>Modal标题</h2>
    </div>
    <div class="modal-body">
      <p>Modal内容区域文本</p>
      <p>更多示例文本...</p>
    </div>
    <div class="modal-footer">
      <h3>Modal底部</h3>
    </div>
  </div>
</div>

CSS

/* Modal遮罩层 */
.modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgb(0, 0, 0);
  background-color: rgba(0, 0, 0, 0.4);
  animation-name: fadeIn;
  animation-duration: 0.4s;
}

/* Modal内容容器 */
.modal-content {
  position: fixed;
  bottom: 0;
  background-color: #fefefe;
  width: 100%;
  animation-name: slideIn;
  animation-duration: 0.4s;
}

/* 关闭按钮样式 */
.close {
  color: white;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}

/* Modal头部、内容、底部样式 */
.modal-header {
  padding: 2px 16px;
  background-color: #5cb85c;
  color: white;
}

.modal-body {
  padding: 2px 16px;
}

.modal-footer {
  padding: 2px 16px;
  background-color: #5cb85c;
  color: white;
}

/* 打开动画关键帧 */
@keyframes slideIn {
  from {
    bottom: -300px;
    opacity: 0;
  }
  to {
    bottom: 0;
    opacity: 1;
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* 关闭动画触发类 */
.modal.animate-out {
  animation-name: fadeOut;
}

.modal.animate-out .modal-content {
  animation-name: slideOut;
}

/* 关闭动画关键帧 */
@keyframes fadeOut {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

@keyframes slideOut {
  from {
    bottom: 0;
    opacity: 1;
  }
  to {
    bottom: -300px;
    opacity: 0;
  }
}

JavaScript

// 获取元素
const modal = document.getElementById("myModal");
const btn = document.getElementById("myBtn");
const span = document.querySelector(".close");

// 打开Modal
btn.onclick = function() {
  modal.style.display = "block";
};

// 关闭Modal逻辑封装
function closeModal() {
  // 添加关闭动画类
  modal.classList.add('animate-out');
  
  // 监听动画结束事件,仅执行一次
  modal.addEventListener('animationend', function() {
    modal.style.display = "none";
    // 移除动画类,避免影响下次打开
    modal.classList.remove('animate-out');
  }, { once: true });
}

// 绑定关闭按钮事件
span.onclick = closeModal;

// 点击Modal外部关闭
window.onclick = function(event) {
  if (event.target === modal) {
    closeModal();
  }
};

关键细节说明

  • 使用{ once: true }配置事件监听,确保动画结束事件只执行一次,避免内存泄漏。
  • 关闭动画的关键帧与打开动画完全反向,保证过渡效果的对称性。
  • 动画结束后必须移除animate-out类,否则下次打开Modal时会优先触发关闭动画。

内容的提问来源于stack exchange,提问作者Asma Binta Younus

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 06:45:34