一种底部固定上方滚动的H5方案(IOS)

https://images.unsplash.com/photo-1541701494587-cb58502866ab?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb

上下分割思路

上下分割思路总结是指将页面分成上下两部分,一部分是主体滚动页面,一部分是底部固定物件。实现方式上可以分成:可视区域动态获取+CSS变量+UMIJS 全局样式变量三个关键点。

首先是要获取当前我们的可视区。我们不能简单的使用100VH来获取当前视口。因为在移动端100VH的高度这个属性会把上方和下方的导航工具也包含进去这篇文章提到这个问题.。一个计算当前有效视口的函数如下所示。其中,3rem是我指定的一个navbar 的大小这不是巧合,对应tw的h-12原子属性,并定义了 –content-height 这个 CSS 变量,这可以让其他样式根据当前的高度做一个变化。

const setWellVH = () => {
  document.body.style.setProperty(
    '--content-height',
    `calc(${window.innerHeight}px - 3rem)`,
  );
  // var html = document.getElementsByTagName('html')[0];
  // html.style.height = `calc(${window.innerHeight}px - 3rem)`;
};

当窗口初始化或者变化的时候调用上面的函数变化视口高度

window.onload = function () {
  setWellVH();
};

window.onresize = function () {
  setWellVH();
};

umijs 可以定义一个全局的样式,在src/global.less下我定义了这样一个全局样式

.effect-content {
    height:calc(var(--content-height));
}
<div className="bg-gray-100 effect-content pb-4 overflow-y-scroll">
	主体内容··
</div>
<div className="h-12 w-full px-7 bg-white z-10 flex justify-between items-center">
	底部navbar
</div>

还没有结束

就算完整按照上面的方法,你会发现这个底部的物件是可以被向上拖动的,会导致上方的滚动也成了问题(好像和上面的区域又连在了一起)。

初级想法是底部物件(我这里是导航栏)使用 fixed 进行绝对定位,然后上方区域设置滚动。但是这样的问题是,在移动端上,随着上方主体区域进行的滚动,底部会出现操作栏从而遮挡了底部。为了解决这个方法需要设定底部导航栏的层级,代码出自 stackoverflow

footer {
  position: fixed;
  bottom: 0;
  z-index: 10; /** this value affects the overlapping **/
}

改造后的底部导航栏是

<div className="...fixed bottom-0">

</div>

阻止页面拖动

做完上面全部,你会发现页面在某些情况下是可以被拖动的。这时候需要使用下面的代码,阻止页面拖动。

html {
    height  : 100%;
    overflow: hidden;
    position: relative;
}
body {
    height  : 100%;
    overflow: auto;
    position: relative;
}
https://stackoverflow.com/questions/29894997/prevent-ios-bounce-without-disabling-scroll-ability