iOS Safari中Bootstrap modal唤起键盘后底部空白如何解决
问题原因
这个是iOS Safari的长期已知渲染bug,和Bootstrap本身没有强绑定:软键盘唤起时,Safari不会实时更新视口高度的计算值,仍将软键盘占据的区域计入可视视口范围,而Bootstrap Modal默认基于视口高度做居中定位、高度约束,就会在模态框底部渲染出和软键盘高度相近的多余空白。
可直接复用的修复方案
1. CSS优先修复(推荐,覆盖90%以上场景)
针对iOS Webkit内核做专属适配,使用更准确的动态视口单位替代传统vh单位,同时修正modal打开时的页面定位逻辑:
/* iOS Safari 模态框软键盘空白修复 */ @supports (-webkit-touch-callout: none) { .modal-dialog { height: fit-content; min-height: -webkit-fill-available; /* dvh是动态视口单位,会自动扣除软键盘、地址栏占据的高度 */ max-height: 85dvh; margin: 1rem auto; } .modal-content { max-height: calc(85dvh - 2rem); overflow-y: auto; } body.modal-open { position: fixed; width: 100%; overscroll-behavior: none; } }
如果使用Bootstrap 5+版本,给modal标签加上modal-dialog-scrollable类,配合上述CSS即可完全消除空白。
2. JS兜底修复(兼容iOS15以下不支持dvh单位的旧版本)
通过监听输入框聚焦/失焦事件,在软键盘唤起时用visualViewport的实时高度手动约束模态框高度:
// 仅在iOS设备下注入逻辑 const isIOSDevice = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; if (isIOSDevice) { document.addEventListener('focusin', (e) => { // 仅处理模态框内的输入框、文本域 if (e.target.matches('.modal input, .modal textarea, .modal select')) { const activeModal = document.querySelector('.modal.show .modal-dialog'); if (activeModal) { // visualViewport.height会实时返回扣除软键盘后的真实可视高度 activeModal.style.maxHeight = `${window.visualViewport.height - 20}px`; } } }); document.addEventListener('focusout', (e) => { if (e.target.matches('.modal input, .modal textarea, .modal select')) { const activeModal = document.querySelector('.modal.show .modal-dialog'); if (activeModal) { activeModal.style.removeProperty('max-height'); window.scrollTo(0, 0); } } }); }
避坑提示
- 不要手动给模态框、模态框内容区设置
height: 100vh类的固定高度,否则软键盘弹出时高度无法自适应必然出现空白 - 不要在模态框打开时给body添加
padding-bottom的适配逻辑,iOS下该值会在软键盘弹出时出现计算偏移 - 如果模态框内有固定定位的底部按钮,建议把按钮放在
.modal-footer容器内,不要单独做fixed定位,避免键盘唤起时位置错位
内容的提问来源于stack exchange,提问作者jpok
相关产品推荐
相关产品推荐

