经典的“粘连”footer布局就是。我们有一块内容 <main>
。当 <main>
的高度足够长的时候,紧跟在 <main>
后面的元素 <footer>
会跟在 <main>
元素的后面。当 <main>
元素比较短的时候(比如小于屏幕的高度),我们期望这个 <footer>
元素能够“粘连”在屏幕的底部。如下图所示:
main
足够长时
main
比较短时
上面布局的实现方法在参考文章中已经有提到。下面主要探讨我们项目中遇到的情况:
我们需要实现的布局就是 按钮“提交”所在的区域能够自由伸缩。当屏幕较低时,最就是“提交”按钮和表单所在的区域接触或者有一定的间隙。 示例图就是下面的:
上面的布局在移动端需要考虑以下因素对布局的影响:
安卓上键盘弹起会对 absolute
和 fixed
产生影响;
我们的绝对定位的元素是使用的 bottom
相对于屏幕的底部定位;
为了解决以上的两个问题的解决方案:
使用正常文档流的元素包裹绝对定位的元素;
绝对定位元素的父级元素应该有一个 min-height
防止,父级元素太低时,绝对定位元素“溢出”父级元素;(min-height >= 绝对定位元素 + bottom);
根据“粘连”footer布局的思想,结合弹性盒布局。我们需要的这种布局可以有两种方式,分别介绍如下:
vh
单位 先来了解下 vh
和 vw
这两个单位。
vh vw
上面两个单位通俗的意义就是在css中获取当前屏幕的高度和宽度(不通过js计算)。
示例代码如下:
<body> <div class="item1"></div> <div class="item2"></div> <div class="item3"> <div class="btn-item">你好</div> </div> </body>
css代码如下:
* { margin: 0; padding: 0; } body { /*主要就是这里获取视窗口的高度*/ min-height: 100vh; display: flex; } .item1 { height: 100px; background-color: #ddd } .item2 { height: 300px; background-color: #fea0a0 } .item3 { /*防止绝对定位的元素溢出父级元素*/ min-height: 30px !important; border: 1px solid #481eff; position: relative; height: 0; -webkit-box-flex: 1; -webkit-flex: 1; -moz-box-flex: 1; -ms-flex: 1; flex: 1; -webkit-flex-basis: 0; -ms-flex-preferred-size: 0; flex-basis: 0; max-height: 100%; } .btn-item { position: absolute; bottom: 10px; border: 1px solid #000; }
vh
单位的兼容性问题。兼容列表如下:
因为兼容性问题,纯css的方法在我们的项目中使用还是不现实。但是我们想下问题的本质:在使用弹性盒的基础上,我们唯一需要做的就是知道弹性盒元素的高度(就是我们项目中屏幕的高度)。
就是在dom树渲染完成以后给 body
设置高度未屏幕的高度。为了避免不必要的“重绘”或者是“重排”在head标签中添加如下js。
var callback = function(){ document.body.style.height=window.screen.height+'px'; }; //是否是页面加载触发绑定了事件 if ( document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll) ) { callback(); } else { //DOMContentLoaded 仅支持ie9+ 和移动端 <=ie8 使用 onreadystatechange 可以监听dom是否加载完毕 document.addEventListener("DOMContentLoaded", callback); }
使用 jQuery 或者是 Zepto 的方法,仍然在head标签中添加如下js。
$(function(){ $('body').height($(window).height()); })
所以在我们的项目中结合弹性盒布局和添加简单的动态js计算屏幕的高度。就可以完美实现我们项目中需要的布局。
body { /*使用js动态计算就可以不使用vh单位*/ /*min-height: 100vh;*/ display: flex; }
因为是一个