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

如何阻止手机键盘上推React作品集网站的UI?

React移动端scroll-snap布局遇键盘弹出上推UI的问题及解决方法

问题描述

我用React制作了一个作品集网站,包含4个高度为100vh的section,通过纵向滚动捕捉(scroll-snap)实现上下滚动,底部section为「联系我」表单。在手机端测试时发现,点击输入框弹出键盘后,键盘并非覆盖网站内容,而是将整个UI向上推挤,导致布局破坏。

截图对比

  • 正常UI:正常UI
  • 异常UI:异常UI

当前使用的CSS代码

单个section样式

.snap-section {
  height: 100vh;
  width: 100vw;
  min-height: 100vh;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  justify-content: center;
}

root元素样式

#root {
  background: radial-gradient(
    circle,
    rgba(1, 11, 56, 1) 0%,
    rgba(1, 20, 110, 1) 100%
  );
  overflow-x: hidden;
  width: 100vw;
  height: 100vh;
  scroll-snap-type: y mandatory;
  overflow-y: scroll;
}

我尝试过使用position: fixed和position: absolute,但这只会显示当前可见的顶部section,无法解决问题。需要找到让键盘仅覆盖网站内容、而非上推所有内容的方法。


解决方案

1. 用100dvh替代100vh(首选方案)

移动端浏览器中,100vh会将虚拟键盘的高度纳入计算,导致键盘弹出时视口高度被压缩,触发布局上推。而100dvh(动态视口高度)会忽略虚拟键盘,始终代表屏幕的实际可用高度(不含键盘),完美解决这个问题。

修改后的CSS代码:

.snap-section {
  height: 100dvh;
  width: 100vw;
  min-height: 100dvh;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  justify-content: center;
}

#root {
  background: radial-gradient(
    circle,
    rgba(1, 11, 56, 1) 0%,
    rgba(1, 20, 110, 1) 100%
  );
  overflow-x: hidden;
  width: 100vw;
  height: 100dvh;
  scroll-snap-type: y mandatory;
  overflow-y: scroll;
}

2. 针对旧浏览器的降级处理

如果需要兼容不支持dvh的浏览器(比如部分老版本iOS Safari),可以添加降级逻辑:

/* 基础样式 */
.snap-section {
  height: 100vh;
  height: 100dvh;
  width: 100vw;
  min-height: 100vh;
  min-height: 100dvh;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  justify-content: center;
}

#root {
  background: radial-gradient(
    circle,
    rgba(1, 11, 56, 1) 0%,
    rgba(1, 20, 110, 1) 100%
  );
  overflow-x: hidden;
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  scroll-snap-type: y mandatory;
  overflow-y: scroll;
}

/* 针对iOS Safari的降级适配 */
@supports (-webkit-touch-callout: none) {
  .snap-section {
    height: -webkit-fill-available;
    min-height: -webkit-fill-available;
  }
  #root {
    height: -webkit-fill-available;
  }
}

3. JS监听键盘状态动态调整(备选方案)

如果CSS方案不生效,可以通过JS监听视口变化,判断键盘是否弹出,然后强制固定布局高度:

React组件示例:

import { useEffect } from 'react';

function App() {
  useEffect(() => {
    const handleResize = () => {
      const windowHeight = window.innerHeight;
      const screenHeight = window.screen.height;
      // 当视口高度小于屏幕高度的70%时,判定为键盘弹出
      const isKeyboardOpen = windowHeight < screenHeight * 0.7;
      const rootEl = document.getElementById('root');
      
      if (isKeyboardOpen) {
        rootEl.classList.add('keyboard-open');
      } else {
        rootEl.classList.remove('keyboard-open');
      }
    };

    window.addEventListener('resize', handleResize);
    // 初始化时触发一次
    handleResize();
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return (
    {/* 你的网站内容 */}
  );
}

对应的CSS:

#root.keyboard-open {
  height: 100dvh !important;
  overflow-y: hidden;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:55:55