Bootstrap 模态框组件 #

模态框(Modal)是一种覆盖在页面上的弹窗组件,用于显示重要信息、收集用户输入或确认操作。Bootstrap 的模态框组件功能强大,支持多种尺寸、动画效果和自定义内容。

基础模态框 #

基本结构 #

html
<!-- 触发按钮 -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  打开模态框
</button>

<!-- 模态框 -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">模态框标题</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>
      </div>
      <div class="modal-body">
        <p>这是模态框的内容区域。</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
        <button type="button" class="btn btn-primary">保存</button>
      </div>
    </div>
  </div>
</div>

结构解析 #

元素 类名 作用
模态框容器 .modal 模态框主容器
淡入淡出 .fade 动画效果
对话框 .modal-dialog 对话框容器
内容区 .modal-content 内容包装器
头部 .modal-header 标题和关闭按钮
标题 .modal-title 模态框标题
主体 .modal-body 主要内容区域
底部 .modal-footer 操作按钮区域

静态背景 #

默认情况下,点击模态框外部会关闭模态框。使用 data-bs-backdrop="static" 可以禁用此行为:

html
<div class="modal fade" data-bs-backdrop="static">
  ...
</div>

禁用键盘关闭 #

使用 data-bs-keyboard="false" 禁用 ESC 键关闭:

html
<div class="modal fade" data-bs-keyboard="false">
  ...
</div>

模态框尺寸 #

小尺寸 #

html
<div class="modal-dialog modal-sm">
  ...
</div>

默认尺寸 #

html
<div class="modal-dialog">
  ...
</div>

大尺寸 #

html
<div class="modal-dialog modal-lg">
  ...
</div>

超大尺寸 #

html
<div class="modal-dialog modal-xl">
  ...
</div>

全屏模态框 #

html
<!-- 始终全屏 -->
<div class="modal-dialog modal-fullscreen">
  ...
</div>

<!-- 响应式全屏 -->
<div class="modal-dialog modal-fullscreen-sm-down">小屏全屏</div>
<div class="modal-dialog modal-fullscreen-md-down">中屏全屏</div>
<div class="modal-dialog modal-fullscreen-lg-down">大屏全屏</div>
<div class="modal-dialog modal-fullscreen-xl-down">超大屏全屏</div>
<div class="modal-dialog modal-fullscreen-xxl-down">超大屏全屏</div>

垂直居中 #

使用 .modal-dialog-centered 使模态框垂直居中:

html
<div class="modal-dialog modal-dialog-centered">
  ...
</div>

滚动长内容 #

模态框内滚动 #

html
<div class="modal-dialog modal-dialog-scrollable">
  <div class="modal-content">
    <div class="modal-header">
      <h5 class="modal-title">长内容模态框</h5>
    </div>
    <div class="modal-body">
      <p>很长的内容...</p>
      <p>很长的内容...</p>
    </div>
  </div>
</div>

实战案例 #

确认对话框 #

html
<!-- 触发按钮 -->
<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#confirmModal">
  删除
</button>

<!-- 确认模态框 -->
<div class="modal fade" id="confirmModal" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">确认删除</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <p>确定要删除此项目吗?此操作无法撤销。</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
        <button type="button" class="btn btn-danger">确认删除</button>
      </div>
    </div>
  </div>
</div>

表单模态框 #

html
<!-- 触发按钮 -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#formModal">
  添加用户
</button>

<!-- 表单模态框 -->
<div class="modal fade" id="formModal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">添加用户</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <form>
          <div class="mb-3">
            <label class="form-label">姓名</label>
            <input type="text" class="form-control" placeholder="请输入姓名">
          </div>
          <div class="mb-3">
            <label class="form-label">邮箱</label>
            <input type="email" class="form-control" placeholder="请输入邮箱">
          </div>
          <div class="mb-3">
            <label class="form-label">角色</label>
            <select class="form-select">
              <option>管理员</option>
              <option>编辑</option>
              <option>用户</option>
            </select>
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
        <button type="button" class="btn btn-primary">保存</button>
      </div>
    </div>
  </div>
</div>

图片预览模态框 #

html
<!-- 触发图片 -->
<img src="thumbnail.jpg" class="img-thumbnail" style="cursor: pointer;" 
     data-bs-toggle="modal" data-bs-target="#imageModal">

<!-- 图片模态框 -->
<div class="modal fade" id="imageModal" tabindex="-1">
  <div class="modal-dialog modal-lg modal-dialog-centered">
    <div class="modal-content bg-transparent border-0">
      <div class="modal-body p-0 text-center">
        <img src="full-image.jpg" class="img-fluid rounded">
      </div>
    </div>
  </div>
</div>

登录模态框 #

html
<!-- 触发按钮 -->
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#loginModal">
  登录
</button>

<!-- 登录模态框 -->
<div class="modal fade" id="loginModal" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header border-0">
        <h5 class="modal-title">登录</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <form>
          <div class="mb-3">
            <label class="form-label">邮箱</label>
            <input type="email" class="form-control" placeholder="请输入邮箱">
          </div>
          <div class="mb-3">
            <label class="form-label">密码</label>
            <input type="password" class="form-control" placeholder="请输入密码">
          </div>
          <div class="d-flex justify-content-between mb-3">
            <div class="form-check">
              <input class="form-check-input" type="checkbox" id="remember">
              <label class="form-check-label" for="remember">记住我</label>
            </div>
            <a href="#" class="text-decoration-none">忘记密码?</a>
          </div>
          <div class="d-grid">
            <button class="btn btn-primary" type="submit">登录</button>
          </div>
        </form>
      </div>
      <div class="modal-footer border-0 justify-content-center">
        <span class="text-muted">还没有账号?</span>
        <a href="#" class="text-decoration-none">立即注册</a>
      </div>
    </div>
  </div>
</div>

详情模态框 #

html
<!-- 触发按钮 -->
<button type="button" class="btn btn-link" data-bs-toggle="modal" data-bs-target="#detailModal">
  查看详情
</button>

<!-- 详情模态框 -->
<div class="modal fade" id="detailModal" tabindex="-1">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">产品详情</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>
      <div class="modal-body">
        <div class="row">
          <div class="col-md-4">
            <img src="product.jpg" class="img-fluid rounded">
          </div>
          <div class="col-md-8">
            <h4>产品名称</h4>
            <p class="text-danger fw-bold">¥99.00</p>
            <p>产品详细描述信息...</p>
            <table class="table table-sm">
              <tbody>
                <tr><th>品牌</th><td>品牌名</td></tr>
                <tr><th>型号</th><td>型号</td></tr>
                <tr><th>规格</th><td>规格</td></tr>
              </tbody>
            </table>
          </div>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
        <button type="button" class="btn btn-primary">加入购物车</button>
      </div>
    </div>
  </div>
</div>

JavaScript API #

通过 JavaScript 打开 #

javascript
var myModal = new bootstrap.Modal(document.getElementById('myModal'));
myModal.show();

配置选项 #

javascript
var myModal = new bootstrap.Modal(document.getElementById('myModal'), {
  backdrop: true,    // 点击背景是否关闭
  keyboard: true,    // ESC 键是否关闭
  focus: true        // 打开时是否聚焦
});

方法 #

javascript
// 显示
myModal.show();

// 隐藏
myModal.hide();

// 切换
myModal.toggle();

// 更新
myModal.handleUpdate();

// 销毁
myModal.dispose();

事件 #

javascript
var myModal = document.getElementById('myModal');

// 显示前触发
myModal.addEventListener('show.bs.modal', function() {
  console.log('模态框即将显示');
});

// 显示后触发
myModal.addEventListener('shown.bs.modal', function() {
  console.log('模态框已显示');
});

// 隐藏前触发
myModal.addEventListener('hide.bs.modal', function() {
  console.log('模态框即将隐藏');
});

// 隐藏后触发
myModal.addEventListener('hidden.bs.modal', function() {
  console.log('模态框已隐藏');
});

// 隐藏被阻止时触发
myModal.addEventListener('hidePrevented.bs.modal', function() {
  console.log('隐藏被阻止');
});
事件类型 说明
show.bs.modal 调用 show 方法时触发
shown.bs.modal 模态框完全显示后触发
hide.bs.modal 调用 hide 方法时触发
hidden.bs.modal 模态框完全隐藏后触发
hidePrevented.bs.modal 点击背景或 ESC 键但被阻止时触发

动态内容 #

通过 data 属性传递数据 #

html
<button type="button" class="btn btn-primary" 
        data-bs-toggle="modal" 
        data-bs-target="#dynamicModal"
        data-id="123"
        data-name="产品名称">
  查看详情
</button>

<div class="modal fade" id="dynamicModal" tabindex="-1">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        <p id="modalContent"></p>
      </div>
    </div>
  </div>
</div>

<script>
document.getElementById('dynamicModal').addEventListener('show.bs.modal', function(event) {
  var button = event.relatedTarget;
  var id = button.getAttribute('data-id');
  var name = button.getAttribute('data-name');
  
  var modalBody = this.querySelector('#modalContent');
  modalBody.textContent = 'ID: ' + id + ', 名称: ' + name;
});
</script>

嵌套模态框 #

Bootstrap 不支持嵌套模态框,建议使用其他方式:

html
<!-- 不推荐:嵌套模态框 -->
<div class="modal">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        <button data-bs-toggle="modal" data-bs-target="#modal2">
          打开另一个模态框
        </button>
      </div>
    </div>
  </div>
</div>

推荐做法:先关闭当前模态框,再打开新模态框:

javascript
// 先隐藏当前模态框
$('#modal1').modal('hide');

// 监听隐藏完成事件
$('#modal1').on('hidden.bs.modal', function() {
  // 打开新模态框
  $('#modal2').modal('show');
});

最佳实践 #

1. 模态框位置 #

将模态框放在页面底部,避免嵌套在其他元素中:

html
<body>
  <!-- 页面内容 -->
  
  <!-- 模态框放在最后 -->
  <div class="modal fade" id="myModal">...</div>
</body>

2. 可访问性 #

html
<div class="modal fade" id="myModal" tabindex="-1" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="myModalLabel">标题</h5>
      </div>
    </div>
  </div>
</div>

3. 关闭按钮 #

html
<!-- 推荐:使用 btn-close -->
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="关闭"></button>

<!-- 或使用文字按钮 -->
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>

4. 防止滚动条跳动 #

css
/* 模态框打开时防止页面滚动条跳动 */
body.modal-open {
  overflow: hidden;
  padding-right: 0 !important;
}

常见问题 #

1. 模态框不显示? #

检查是否引入了 Bootstrap JavaScript:

html
<script src="bootstrap.bundle.min.js"></script>

2. 点击按钮无反应? #

检查 data-bs-toggledata-bs-target 属性:

html
<button data-bs-toggle="modal" data-bs-target="#myModal">打开</button>

3. 模态框背景变暗? #

确保模态框放在 .modal-backdrop 外面,通常放在 body 最后。

4. 模态框内容动态更新后滚动问题? #

调用 handleUpdate() 方法:

javascript
myModal.handleUpdate();

下一步 #

现在你已经掌握了模态框组件,接下来学习 工具类,了解 Bootstrap 提供的各种实用工具类!

最后更新:2026-03-28