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

React项目中Safari打开键盘时出现黑块及页面底部空白问题求助

React输入框唤起软键盘后底部空白+Safari黑块问题解决方案

方法1:监听键盘弹出动态调整页面高度

通过监听窗口resize事件,对比初始视口高度判断软键盘状态,动态调整页面根容器或body高度,避免底部留白。

import { useEffect, useState } from 'react';

function App() {
  const [initialHeight, setInitialHeight] = useState(window.innerHeight);

  useEffect(() => {
    const handleResize = () => {
      const currentHeight = window.innerHeight;
      // 高度差超过200px判定为键盘弹出,可根据实际场景调整阈值
      if (initialHeight - currentHeight > 200) {
        document.documentElement.style.height = `${currentHeight}px`;
        document.body.style.height = `${currentHeight}px`;
      } else {
        document.documentElement.style.height = 'auto';
        document.body.style.height = 'auto';
      }
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, [initialHeight]);

  return (
    <div className="app-container">
      <input type="text" placeholder="测试输入框" />
    </div>
  );
}

export default App;

方法2:修复Safari视口适配问题

Safari对软键盘弹出后的视口处理存在兼容性bug,需调整viewport配置并配合动态样式修复黑块:

  1. 在public/index.html的meta标签中添加viewport-fit=cover:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
  1. 在React组件中添加Safari专属适配逻辑:
import { useEffect } from 'react';

function InputSafariFix() {
  useEffect(() => {
    const handleFocus = () => {
      if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
        document.body.style.position = 'fixed';
        document.body.style.width = '100%';
      }
    };

    const handleBlur = () => {
      if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
        document.body.style.position = '';
        document.body.style.width = '';
        window.scrollTo(0, document.documentElement.scrollTop);
      }
    };

    const inputs = document.querySelectorAll('input, textarea');
    inputs.forEach(input => {
      input.addEventListener('focus', handleFocus);
      input.addEventListener('blur', handleBlur);
    });

    return () => {
      inputs.forEach(input => {
        input.removeEventListener('focus', handleFocus);
        input.removeEventListener('blur', handleBlur);
      });
    };
  }, []);

  return null;
}

// 在App组件中引入该修复组件
function App() {
  return (
    <div>
      <InputSafariFix />
      {/* 页面内容 */}
    </div>
  );
}

方法3:固定页面并禁用滚动

输入框聚焦时固定页面定位,防止软键盘弹出导致的页面滚动留白,失焦后恢复原状态:

import { useEffect } from 'react';

function InputScrollFix() {
  useEffect(() => {
    let scrollTop = 0;

    const handleFocus = () => {
      scrollTop = window.pageYOffset || document.documentElement.scrollTop;
      document.body.style.position = 'fixed';
      document.body.style.top = `-${scrollTop}px`;
      document.body.style.width = '100%';
    };

    const handleBlur = () => {
      document.body.style.position = '';
      document.body.style.top = '';
      window.scrollTo(0, scrollTop);
    };

    const inputs = document.querySelectorAll('input, textarea');
    inputs.forEach(input => {
      input.addEventListener('focus', handleFocus);
      input.addEventListener('blur', handleBlur);
    });

    return () => {
      inputs.forEach(input => {
        input.removeEventListener('focus', handleFocus);
        input.removeEventListener('blur', handleBlur);
      });
    };
  }, []);

  return null;
}

方法4:使用第三方库简化处理

如果自定义逻辑繁琐,可借助react-scroll-lock库锁定页面滚动,间接解决留白问题:

  1. 安装依赖:
npm install react-scroll-lock --save
  1. 在组件中使用:
import { useState } from 'react';
import ScrollLock from 'react-scroll-lock';

function App() {
  const [isInputFocused, setIsInputFocused] = useState(false);

  return (
    <div>
      <ScrollLock isActive={isInputFocused} />
      <input
        type="text"
        onFocus={() => setIsInputFocused(true)}
        onBlur={() => setIsInputFocused(false)}
        placeholder="测试输入框"
      />
    </div>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:33:14