在外企银行工作,开发的app是混合应用。说实话国外银行功能确实没有国内银行多,而且技术比较守旧,就在去年上半年,没错,2018年上半年,我们的app还必须兼容安卓4.4,并且测试还会旧设备去测,这让我们不得不放弃css3。好在页面少,工作量不算太大。而且幸运的是,去年下半年公司app的webview外壳升级,终于可以用上css3。
虽然以前写的css虽然看起来很愚笨,但是确实在任何设备都没有兼容性问题。所以还是在这里总结下吧,即使以后可能再也不使用。
本次举例的布局就是最常见的header,content,footer,就比如下面的样子。
navbar (header)和底部导航 (footer)一定是固定高度的,不同尺寸的屏幕下,中间的主体内容 (content)是自由伸缩的,而且内容太多会出现滚动条,以保证页面不会挤坏。
这个使用flex实在是太容易实现了,指定flex-direction: column。中间的content设置flex:1(关键属性是flex-grow:1),header和footer设定死高度,别的不要设置。
这样content就会占满剩余空间,正好把header和footer挤在了边缘,视觉上就是他俩固定死上下位置了,content也实现了自适应。非常急速就实现了。
下面我们看看以前我的兼容方式怎么实现。
首先我们想下什么情况下,元素高度或者位置能自由变化,但是总能保持一定规律。
元素自由移动我们一定想到了position:absolute,没错这个属性使得元素脱离文档流,自占一层空间,并在自己空间里自由移动。
position:absolute还有个有意思的地方,如果我们不指定宽高,但是同时设置了left, right, top, bottom会怎样?
我们试验一下
.
html结构:
<
效果如下:
我们发现,子元素按照left, right, top, bottom四边展开,元素宽高就是这个展开空间的宽高,而且元素距离容器四边的距离也是固定的,即left, right, top, bottom的值。
我们继续修改container的宽高
.
我们发现:此时元素宽高随着父容器变大而变大,但是四边距离容器的距离仍然是固定的,这难道不是一种自适应?。
知道了这个,我们就再来看下开头的布局,如何应用。
首先header和footer始终固定在顶部和底部,content始终固定在中间,但是有个规律:在不同设备上,无论content高度怎么变化,唯一不变的就是距离容器的上面和下面距离,正好就是header和footer的值。
这下我们就可以使用absolute来实现了。
注意:
- position: absolute使元素脱离文档流,也就是父元素无法包裹子元素,子元素无法把父元素撑开,因此,有时候父元素不得不手动指定宽高。本例中父元素若需要占满屏幕,只能强制设置html和body的高度为100%(css3用100vh)。
- 一个块级元素,我们知道默认会自占一行,宽度为填满父元素的宽度。但是应用position:absolute后,该元素的宽度将不在占满父元素(谁叫你自己脱离了文档流了,还想占满父元素?),反而宽高为包裹子元素的宽高(类似于安卓android:layout_width="wrap_content"),所以,有必要手动设置宽高。
- position:absolute,位置参考最近的,属性为position:relative的父元素或者祖先元素,谁是第一个就参考谁。
- position:absolute元素自占一层空间,不与任何元素争夺空间,即无论怎么移动,都不占用,不挤压任何元素的空间,但是空间是有层级的,就比如楼层,因此会出现z方向的遮挡,谁层级高,谁就在谁上面,谁就会盖住谁,但永远不存在挤压和占用空间。
下面我们就先把容器写出来
html
接下来就是header和footer啦,header始终待在父容器顶部,footer始终待在父容器底部
.
最终就是content的啦,顶部和底部的距离分别是header和footer的高度,这样就能把他们露出来,不会把他们遮盖。
.
最后html结构如下
<
最后我们看下效果:
哎?奇了怪了?我的header的border-bottom呢?我明明设置了?
如果你inspect,你会发现border就在,只不过默认情况下,border会增加元素的大小,比如border宽1px,那么元素宽高会额外增加1px,但是我们的content的top仍然是44px。所以那个border被content遮住了,我们可以设置top:45px,但是更优化的方式是使用box-sizing:
.
这样修改完我们就实现了和flex一模一样的效果。
我们切换不同设备,页面完全自适应。
到此你觉得已经完美了?错,为啥说flex好用呢?
假设我的header和footer变了呢?典型的例子就是iphone-x系列,顶部刘海和底部控制条需要留出额外的44px和34px,还有某些页面需要根据业务调整header和footer高度。
如果是flex,header和footer变化,content仍然会自适应,因为content是基于剩余空间的,剩余空间是动态的,content也是动态的。
但是我们的ansolute解决方法是:
top:44px;
bottom:60px;
注意到是固定死的值,又不让用css3媒体查询,怎么办呢?要么我再定义个新的class,但是还是固定死值?怎么才能动态调整呢?
只能靠js来实现了!!
我们公司使用的是Ember框架,Ember的页面都是一个view实例,在渲染完view的dom元素后执行某些生命周期方法,或者叫钩子方法,比如didInsertElement,这样我们就可以在这里操作一些UI了,下面用伪代码示范一下
var
这样我们页面就完全自适应了,再也不怕任何设备啦。
以上就是不使用css3实现的兼容页面,当然我们变形一下也可以实现如下效果等等:
原理是一样的。