Web移動(dòng)端Fixed布局的解決方案 __veblen
移動(dòng)端業(yè)務(wù)開發(fā)愿棋,iOS 下經(jīng)常會(huì)有 fixed 元素和輸入框(input 元素)同時(shí)存在的情況。 但是 fixed 元素在有軟鍵盤喚起的情況下该押,會(huì)出現(xiàn)許多莫名其妙的問題。 這篇文章里就提供一個(gè)簡(jiǎn)單的有輸入框情況下的 fixed 布局方案椒振。
iOS下的 Fixed + Input BUG現(xiàn)象
讓我們先舉個(gè)栗子效诅,最直觀的說明一下這個(gè) BUG 的現(xiàn)象。 常規(guī)的 fixed 布局霎匈,可能使用如下布局(以下僅示意代碼):
<body class="layout-fixed">
<!-- fixed定位的頭部 -->
<header>
</header>
<!-- 可以滾動(dòng)的區(qū)域 -->
<main>
<!-- 內(nèi)容在這里... -->
</main>
<!-- fixed定位的底部 -->
<footer>
<input type="text" placeholder="Footer..."/>
<button class="submit">提交</button>
</footer>
</body>
對(duì)應(yīng)的樣式如下:
header, footer, main {
display: block;
}
header {
position: fixed;
height: 50px;
left: 0;
right: 0;
top: 0;
}
footer {
position: fixed;
height: 34px;
left: 0;
right: 0;
bottom: 0;
}
main {
margin-top: 50px;
margin-bottom: 34px;
height: 2000px
}
然后看起來就是下面這個(gè)樣子戴差。拖動(dòng)頁(yè)面時(shí) header 和 footer 已經(jīng)定位在了對(duì)應(yīng)的位置,目測(cè)沒問題了铛嘱。
但接下來問題就來了暖释!如果底部輸入框軟鍵盤被喚起以后,再次滑動(dòng)頁(yè)面墨吓,就會(huì)看到如下圖所示:
我們看到 fixed 定位好的元素跟隨頁(yè)面滾動(dòng)了起來... fixed 屬性失效了球匕!
這是為什么呢?簡(jiǎn)單解釋下: 軟鍵盤喚起后帖烘,頁(yè)面的 fixed 元素將失效(即無法浮動(dòng)亮曹,也可以理解為變成了 absolute 定位),所以當(dāng)頁(yè)面超過一屏且滾動(dòng)時(shí)秘症,失效的 fixed 元素就會(huì)跟隨滾動(dòng)了照卦。
這便是 iOS 上 fixed 元素和輸入框的 bug 。其中不僅限于 type=text 的輸入框乡摹,凡是軟鍵盤(比如時(shí)間日期選擇役耕、select 選擇等等)被喚起,都會(huì)遇到同樣地問題聪廉。
解決思路:
既然在 iOS 下由于軟鍵盤喚出后瞬痘,頁(yè)面 fixed 元素會(huì)失效,導(dǎo)致跟隨頁(yè)面一起滾動(dòng)板熊,那么假如——頁(yè)面不會(huì)過長(zhǎng)出現(xiàn)滾動(dòng)框全,那么即便 fixed 元素失效,也無法跟隨頁(yè)面滾動(dòng)邻邮,也就不會(huì)出現(xiàn)上面的問題了竣况。
那么按照這個(gè)思路,如果使 fixed 元素的父級(jí)不出現(xiàn)滾動(dòng),而將原 body 滾動(dòng)的區(qū)域域移到 main 內(nèi)部丹泉,而 header 和 footer 的樣式不變情萤,代碼如下:
<body class="layout-scroll-fixed">
<!-- fixed定位的頭部 -->
<header>
</header>
<!-- 可以滾動(dòng)的區(qū)域 -->
<main>
<div class="content">
<!-- 內(nèi)容在這里... -->
</div>
</main>
<!-- fixed定位的底部 -->
<footer>
<input type="text" placeholder="Footer..."/>
<button class="submit">提交</button>
</footer>
</body>
header, footer, main {
display: block;
}
header {
position: fixed;
height: 50px;
left: 0;
right: 0;
top: 0;
}
footer {
position: fixed;
height: 34px;
left: 0;
right: 0;
bottom: 0;
}
main {
/* main絕對(duì)定位,進(jìn)行內(nèi)部滾動(dòng) */
position: absolute;
top: 50px;
bottom: 34px;
/* 使之可以滾動(dòng) */
overflow-y: scroll;
}
main .content {
height: 2000px;
}
這樣再來看一下:
在原始輸入法下摹恨,fixed
元素可以定位在頁(yè)面的正確位置筋岛。滾動(dòng)頁(yè)面時(shí),由于滾動(dòng)的是 main
內(nèi)部的div
晒哄,因此footer
沒有跟隨頁(yè)面滾動(dòng)睁宰。
上面貌似解決了問題,但是如果在手機(jī)上實(shí)際測(cè)試一下寝凌,會(huì)發(fā)現(xiàn)main
元素內(nèi)的滾動(dòng)非常不流暢柒傻,滑動(dòng)的手指松開后,滾動(dòng)立刻停止较木,失去了原本的流暢滾動(dòng)特性红符。百度一下彈性滾動(dòng)的問題,發(fā)現(xiàn)在 webkit
中伐债,下面的屬性可以恢復(fù)彈性滾動(dòng)预侯。
-webkit-overflow-scrolling: touch;
在 main 元素上加上該屬性,嗯峰锁,絲般順滑的感覺又回來了萎馅!
main {
/* main絕對(duì)定位,進(jìn)行內(nèi)部滾動(dòng) */
position: absolute;
top: 50px;
bottom: 34px;
/* 使之可以滾動(dòng) */
overflow-y: scroll;
/* 增加該屬性虹蒋,可以增加彈性 */
-webkit-overflow-scrolling: touch;
}
另外糜芳,這里的 header 和 footer 使用的是 fixed 定位,如果考慮到更老一些的 iOS 系統(tǒng)不支持 fixed 元素千诬,完全可以把 fixed 替換成 absolute 耍目。測(cè)試后效果是一樣的。
Android 下布局
在 Android2.3+ 中徐绑,因?yàn)椴恢С?overflow-scrolling ,因此部分瀏覽器內(nèi)滾動(dòng)會(huì)有不流暢的卡頓莫辨。但是目前發(fā)現(xiàn)在 body 上的滾動(dòng)還是很流暢的傲茄,因此使用第一種在 iOS 出現(xiàn)問題的 fixed 定位的布局就可以了。
如果需要考慮 Android2.3 以下系統(tǒng)沮榜,因?yàn)椴恢С?fixed 元素盘榨,所以依然要需要考慮使用 isScroll.js 來實(shí)現(xiàn)內(nèi)部滾動(dòng)。
加油蟆融!移動(dòng)端常見問題及解決方案