解决方案:通过 absolute 代替 fixed 实现固定在键盘顶部
第一步:外层元素禁止滚动,内层元素滚动 + 获取可视区高度
第二步:用 absolute 替代 fixed 实现
以下示例代码使用的是 Vue3
index.vue
<template>
<div class="wrapper" :style="{ height: height + 'px' }">
<!-- 这里 -50 就是减去固定在底部的元素高度 -->
<div class="body" :style="{ height: height - 50 + 'px' }">
<input v-model="value" />
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
<p>内容</p>
</div>
<div class="fixed-bottom">固定在底部</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import useVisualViewport from "@/use/useVisualViewport";
const { height } = useVisualViewport();
const value = ref("");
// 此处解决 ios 向上滑动出现和键盘一样高度的白色衬底区域
onMounted(() => {
window.onscroll = () => {
document.documentElement.scrollTop = 0;
};
});
onUnmounted(() => {
window.onscroll = null;
});
</script>
<style lang="scss" scoped>
.wrapper {
position: relative;
overflow: hidden;
.body {
padding: 20px;
overflow: auto;
}
.fixed-bottom {
border-top: 1px solid #ccc;
text-align: center;
line-height: 50px;
width: 100%;
height: 50px;
position: absolute;
bottom: 0;
left: 0;
}
}
</style>
window.visualViewport 此 api 只兼容 ios 13 以上
useVisualViewport
import { ref, onMounted, onUnmounted } from "vue";
export default function useVisualViewport() {
let width = ref(window.innerWidth);
let height = ref(window.innerHeight);
const handler = () => {
// 只兼容 ios13 以上
if (window.visualViewport) {
width.value = window.visualViewport.width;
height.value = window.visualViewport.height;
} else {
width.value = window.innerWidth;
height.value = window.innerHeight;
}
};
onMounted(() => {
window.visualViewport.addEventListener("resize", handler);
window.visualViewport.addEventListener("scroll", handler);
});
onUnmounted(() => {
window.visualViewport.removeEventListener("resize", handler);
window.visualViewport.removeEventListener("scroll", handler);
});
return { width, height };
}
最终效果
注意
注意:此方案只兼容 ios 13 以上, ios 13以下的系统普及率较低了