移动端唤起键盘时,如何让聊天窗口内容自适应收缩而非上移?
移动端聊天窗口键盘适配问题
问题描述
移动设备上聚焦输入框时,页面整体上移,头部和消息区被移出视野。
需求目标
聚焦输入框时,#messages区域能自动收缩以适配弹出的键盘,效果和桌面端缩小窗口高度时一致。
已尝试方案
- 用
height: 100%替换100dvh - 将高度声明从
<html>转移到<body>
补充说明
移动端Firefox表现正常,但Chrome和Safari计算dvh时未考虑屏幕键盘的占用空间。
原代码
CSS
html, body { padding: 0; margin: 0; } html { height: 100dvh; width: 100dvw; } body { height: 100%; width: 100%; background-color: white; } #content { height: 100%; display: flex; flex-direction: column; } #header { padding: 20px; background-color: #ccc; } #messages { margin: -10px 0; flex-grow: 1; flex-shrink: 1; overflow: auto; } .message { padding: 20px; } #footer { display: block; background-color: #aaa; padding: 20px; } input { padding: 5px; width: 100%; display: block; } button { border: 0; margin: 4px 0; padding: 4px; background-color: orange; font-weight: bold; }
HTML
<div id="content"> <div id="header">Header</div> <div id="messages"> <div class="message"><b>John:</b> Lorem ipsum dolor sit amet.</div> </div> <form id="footer"> <input> <button type="button">Send Message</button> </form> </div>
解决方案
针对Chrome和Safari的适配问题,推荐以下两种方案:
方案1:固定布局实现自动收缩
通过固定定位让容器始终贴合当前视口,结合flex布局特性,键盘弹出时视口高度变化,消息区会自动收缩。修改后的CSS如下:
html, body { padding: 0; margin: 0; height: 100%; width: 100%; } #content { position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: flex; flex-direction: column; } #header { padding: 20px; background-color: #ccc; flex-shrink: 0; /* 确保头部高度固定,不被压缩 */ } #messages { margin: -10px 0; flex-grow: 1; overflow: auto; } .message { padding: 20px; } #footer { display: block; background-color: #aaa; padding: 20px; flex-shrink: 0; /* 确保输入区高度固定,不被压缩 */ } input { padding: 5px; width: 100%; display: block; } button { border: 0; margin: 4px 0; padding: 4px; background-color: orange; font-weight: bold; }
方案2:JavaScript监听键盘状态动态调整高度
如果固定布局不符合需求,可通过JS监听窗口变化和输入框状态,动态设置消息区高度:
const messages = document.getElementById('messages'); const input = document.querySelector('input'); let viewportHeight = window.innerHeight; // 监听窗口尺寸变化 window.addEventListener('resize', () => { const currentHeight = window.innerHeight; const headerHeight = document.getElementById('header').offsetHeight; const footerHeight = document.getElementById('footer').offsetHeight; // 判断键盘是否弹出(高度骤降) if (currentHeight < viewportHeight * 0.8) { messages.style.maxHeight = `${currentHeight - headerHeight - footerHeight}px`; } else { messages.style.maxHeight = ''; viewportHeight = currentHeight; } }); // 输入框聚焦时触发一次尺寸检查 input.addEventListener('focus', () => { setTimeout(() => window.dispatchEvent(new Event('resize')), 300); }); // 输入框失焦后恢复原状态 input.addEventListener('blur', () => { messages.style.maxHeight = ''; viewportHeight = window.innerHeight; });
内容的提问来源于stack exchange,提问作者Santi
相关产品推荐
相关产品推荐

