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

移动端Leaflet地图上层Bootstrap模态框滚动显示bug求助

问题:Vue2+Leaflet+Bootstrap模态框滚动导致地图空白
  • 在移动端Chrome或三星浏览器中,滚动Bootstrap模态框时,浏览器导航栏自动隐藏,页面显示高度增加,Leaflet地图下方出现空白区域
  • 尝试调用map.invalidateSize()无效;修改模态框CSS后,Safari中模态框完全无法滚动
解决方案

核心思路是锁定页面视口高度,避免导航栏隐藏触发的高度变化,同时保证模态框在各浏览器的滚动兼容性:

  • 模态框显示时,给html和body添加固定高度样式,阻止视口尺寸突变
  • 仅让modal-body负责滚动,而非整个modal-dialog,解决Safari滚动失效问题
  • 模态框关闭后移除固定样式,并延迟调用地图尺寸校验,确保DOM更新完成

修改后的完整代码

Template部分

<template>
  <div id="app">
    <l-map ref="map" :center="[51, 0]" :zoom="10" @ready="onReady()">
      <l-tile-layer url="https://tile.openstreetmap.org/{z}/{x}/{y}.png"/>
      <l-circle-marker :lat-lng="[51, 0]" @click="showModal()"/>
    </l-map>
    <div ref="testModal" class="modal fade" id="testModal" tabindex="-1" aria-labelledby="poi" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title">Test</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
          </div>
          <div class="modal-body custom-modal-body">
            <p v-for="n in 30" :key="n">line {{n}}</p>
           </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

Script部分

import { Modal } from 'bootstrap';
import { LMap, LTileLayer, LCircleMarker } from 'vue2-leaflet';

export default {
  name: 'App',
  components: {
    LMap,
    LTileLayer,
    LCircleMarker,
  },
  data() {
    return {
      testModal: null,
      mapInstance: null
    }
  },
  methods: {
    onReady() {
      this.mapInstance = this.$refs.map.mapObject;
      const modalEl = document.getElementById('testModal');
      
      // 模态框显示时锁定视口
      modalEl.addEventListener('show.bs.modal', () => {
        document.documentElement.classList.add('modal-open-fixed');
        document.body.classList.add('modal-open-fixed');
      });
      
      // 模态框关闭后恢复视口并校验地图尺寸
      modalEl.addEventListener('hidden.bs.modal', () => {
        document.documentElement.classList.remove('modal-open-fixed');
        document.body.classList.remove('modal-open-fixed');
        // 延迟调用确保DOM已更新
        setTimeout(() => {
          this.mapInstance.invalidateSize();
        }, 100);
      });
    },
    showModal() {
      this.testModal.show();
    }
  },
  mounted() {
    this.testModal = new Modal(document.getElementById('testModal'));
  }
}

Style部分

html, body, #app {
  height: 100%;
  margin: 0;
  padding: 0;
}

/* 锁定视口高度,防止导航栏隐藏触发高度变化 */
.modal-open-fixed {
  height: 100vh;
  overflow: hidden;
  position: fixed;
  width: 100%;
}

/* 仅让modal-body滚动,保证Safari兼容性 */
.custom-modal-body {
  max-height: calc(100vh - 140px); /* 减去header和footer高度 */
  overflow-y: auto;
}

/* 引入Bootstrap样式 */
@import '~bootstrap/scss/bootstrap.scss';

关键说明

  • modal-open-fixed类通过固定视口高度,彻底避免浏览器导航栏隐藏导致的页面高度突变
  • 滚动区域限定在modal-body,符合Bootstrap原生滚动逻辑,解决Safari滚动失效问题
  • 延迟调用invalidateSize()确保模态框关闭后DOM已完全恢复,地图能正确计算容器尺寸

内容的提问来源于stack exchange,提问作者gregoire

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:32:39