前端页面开发或是现在日渐增多的Hybird APP应用开发中,经常遇到模拟原生APP界面效果不佳情况,固定header、footer便是其中一种。

涉及header、footer固定,主体部分可滑动,最初想法一般是

position: fixed

然而,iOS各种下input获取焦点后fixed失效等一系列问题,致使我们不得不选择另辟他径。于是,我们这样玩

* {
    box-sizing: border-box;
    margin: 0;
}
html, body, #app {
    height: 100%;
}
body {
    -webkit-overflow-scrolling: touch;
}
.header,
.footer {
    position: absolute;
    left: 0;
    right: 0;
    height: 50px;
    z-index: 100;
}
.header {
    top: 0;
    background: #ff910f;
}
.footer {
    bottom: 0;
    background: #f3f3f3;
}
.content {
    padding: 50px 0;
    overflow: auto;
    height: 100%;
}

似乎是很不错的选择,很多移动端网站以及Hybird APP也都在这样用。然而,还有很多网站或是Hybird APP还是选择了IScroll之类的三方库来模拟,不得不承认的是,类似IScroll使用CSS3来模拟iOS的Bounce效果,很不错,但有时候我们可能不希望使用IScroll这样的库,譬如,只是一个简单的活动页等。这个情况下,我们使用如上结构,似乎可以满足,然而,实际使用中发现,如果网页低于一屏高,header、footer还是会被“带走”,这个情况下,有人建议使用js来阻止body的touch事件,这样由于主要滑动的是.content下面的内容,也不至于整页滑动导致header、footer随滚动而动,但这么暴力的处理往往是不理想的(可能影响其他功能,且页面功能多时,可能出现js加载延迟,页面初始化完第一次还是可以滚动)。

效果大概是这样的:

iOS-scroll-header-footer-1

期望是只有主体部分能够滚动,然而

iOS-scroll-header-footer-2

向上滑动

iOS-scroll-header-footer-3

向下滑动

最近遇到这样的问题,尝试后做了如下小改动,可以零js解决此问题,示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <title>Title</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
        }

        html, body, #app {
            height: 100%;
        }

        body {
            -webkit-overflow-scrolling: touch;
        }

        .header,
        .footer {
            position: absolute;
            left: 0;
            right: 0;
            height: 50px;
            z-index: 100;
        }

        .header {
            top: 0;
            background: #ff910f;
        }

        .footer {
            bottom: 0;
            background: #f3f3f3;
        }

        .content {
            position: relative;
            padding: 50px 0;
            overflow: auto;
            height: 100%;
        }

        .content > .scroll-wrap {
            box-sizing: content-box;
            min-height: 100%;
            padding-bottom: 1px;
        }
    </style>
</head>
<body>
<div id="app">
    <div class="header">测试Header</div>
    <div class="content">
        <div class="scroll-wrap">
            主体
        </div>
    </div>
    <div class="footer">测试Footer</div>
</div>
</body>
</html>

很简单,既然js实现可能滞后生效(首次不生效)又可能冲突,那么我们就在css中动点手脚,在.content下加一层min-height为100%+1px的块,如下:

.content > .scroll-wrap {
    box-sizing: content-box;
    min-height: 100%;
    padding-bottom: 1px;
}

浏览器解析的时候始终会认为需要滚动条,而不会触发整个页面的Bounce效果,尝试多个iOS系统,基本没有什么问题,只是1px的差异,遇到处女座可能有点纠结了。

PS:这个方法最终没有用到自己的项目上,因为自己项目是一个动态构建webapp的平台,组件都是第三方开发的,可能会有高度100%的需求,且不希望使用CSS3的vh等来实现全屏高,所以希望主体部分下元素可以继承主体高度,设置min-height后似乎并不合适。但纯粹自己开发网站、Hybird APP的情况,完全可以尝试