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

Telegram React迷你应用虚拟键盘关闭后视口高度无法恢复问题

解决Telegram迷你应用WebView中关闭虚拟键盘后底部出现黑色空白的问题

问题描述

我用React开发Telegram迷你应用,通过WebView在Telegram中展示,遇到以下问题:

  • 重现步骤:
    1. 创建多个输入框
    2. 点击最后一个输入框,虚拟键盘弹出,页面滚动至聚焦的输入框
    3. 关闭键盘后,视口无法恢复初始高度,屏幕底部出现黑色空白区域

默认视图:
默认视图
键盘弹出状态:
键盘弹出状态
键盘关闭状态:
键盘关闭状态

相关代码:

<div className="bg-white h-[100vh] overflow-hidden relative flex flex-col gap-10">
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
  <input type="text" placeholder="test" className="bg-red-300" />
</div>

核心原因

问题根源在于使用100vh设置容器高度。Telegram的WebView在虚拟键盘弹出时会调整可见视口高度,但vh单位是基于页面加载时的初始视口高度计算的,键盘关闭后不会自动更新这个值,导致容器高度和实际可见视口不匹配,从而出现底部黑色空白。

解决方法

方法1:用动态视口单位dvh替换vh

现代浏览器支持dvh(动态视口高度)单位,它会实时跟随当前可见视口高度变化,完美适配键盘弹出/关闭的场景,修改代码如下:

<div className="bg-white h-[100dvh] overflow-hidden relative flex flex-col gap-10">
  {/* 输入框内容保持不变 */}
</div>

方法2:监听窗口resize事件手动调整高度

如果需要兼容不支持dvh的环境,可以通过监听窗口大小变化事件(键盘弹出/关闭会触发resize)来手动更新容器高度:

import { useEffect, useRef } from 'react';

function App() {
  const containerRef = useRef(null);

  useEffect(() => {
    const updateHeight = () => {
      if (containerRef.current) {
        containerRef.current.style.height = `${window.innerHeight}px`;
      }
    };

    window.addEventListener('resize', updateHeight);
    // 初始化时设置一次高度
    updateHeight();

    return () => window.removeEventListener('resize', updateHeight);
  }, []);

  return (
    <div 
      ref={containerRef}
      className="bg-white overflow-hidden relative flex flex-col gap-10"
    >
      <input type="text" placeholder="test" className="bg-red-300" />
      <input type="text" placeholder="test" className="bg-red-300" />
      {/* 其他输入框 */}
    </div>
  );
}

方法3:利用Telegram WebApp API监听键盘状态

Telegram提供了WebApp专属API,可以直接监听键盘的显示/隐藏事件,针对性调整页面:

import { useEffect, useRef } from 'react';

function App() {
  const containerRef = useRef(null);

  useEffect(() => {
    const handleKeyboardToggle = (isVisible) => {
      if (containerRef.current) {
        containerRef.current.style.height = isVisible 
          ? `${window.innerHeight}px` 
          : `${window.screen.height}px`;
        // 关闭键盘后滚动到顶部,确保视口完全恢复
        window.scrollTo(0, 0);
      }
    };

    // 绑定键盘显示/隐藏事件
    Telegram.WebApp.onEvent('keyboardShow', () => handleKeyboardToggle(true));
    Telegram.WebApp.onEvent('keyboardHide', () => handleKeyboardToggle(false));

    // 组件卸载时移除事件监听
    return () => {
      Telegram.WebApp.offEvent('keyboardShow');
      Telegram.WebApp.offEvent('keyboardHide');
    };
  }, []);

  return (
    <div 
      ref={containerRef}
      className="bg-white h-[100vh] overflow-hidden relative flex flex-col gap-10"
    >
      {/* 输入框内容 */}
    </div>
  );
}

额外提示

  • 如果必须给容器设置overflow-hidden,可以在键盘关闭后触发一次页面重绘(比如临时添加再移除一个无用的CSS类),强制浏览器更新视口计算
  • 测试时尽量用真实的Telegram环境,模拟器可能存在视口计算偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:22:36