作者:Tolonger
除了百分比流式布局之外,rem布局占据了目前移动端布局的热潮。那么究竟这几种布局差别在哪里,对应的有什么效果,希望本文能给你一些有益的启示。除此之外还有响应式布局,固定宽度布局等。
百分比流式布局
这里面最知名的当属bootstrap框架的思路,他所有的组件以及模板ui均是百分比流式布局,单位为px.并且我们看到的大部分对移动端适配的页面也均是采用这种核心思想去做的,方法简单,多端共用,可以针对不同临界值做额外处理。比如百度,天猫,知乎,京东,微信一些文章等。所以无论怎么看,百分比流式布局都是一种常规+主流的布局方案。 核心原则:文字为流式布局,宽度100%按照屏幕宽度缩放,高度固定px,水平采用百分比,或者固宽+变宽,图片固定大小或者百分比缩放,辅助flex布局 。有使用的最大媒体查询临界值(一般为640)。 通过下图去理解下:
缺点:在大屏幕的手机下显示效果会变成有些页面元素宽度被拉的很长,但是高度还是和原来一样,实际显示非常的不协调,这就是流式布局的最致命的缺点
网易的rem布局
随着分辨率的增大,页面的效果会发生明显变化,主要体现在各个元素的宽高与间距。375680的比320680的导航栏明显要高。能够达到这种效果的根本原因就是因为网易页面里除了font-size之外的其它css尺寸都使用了rem作为单位,比如你看导航栏的高度设置代码:
header,footer{
height:.90rem;
}
网易页面上html的font-size不是预先通过媒介查询在css里定义好的,而是通过js计算出来的,所以当分辨率发生变化时,html的font-size就会变,不过这得在你调整分辨率后,刷新页面才能看得到效果。你看代码就知道为啥font-size是直接写到html的style上面的了(js设置的原因). 这样的话,每个页面中的宽高以及具体值只要除以100即可,而根节点的字号则是font-size=deviceWidth / 6.4,页面宽度如果是640px,则转换之后是6.4rem。需要注意的是,字号需要额外的媒体查询,而不是rem定的。
//字号单独用px即可 ,这里建议大家用变量定义小中大正常集中字号常量就可以,不用每次去针对具体样式做字号调整。
@media screen and (max-width:321px){
.m-navlist{font-size:15px}
}
@media screen and (min-width:321px) and (max-width:400px){
.m-navlist{font-size:16px}
}
@media screen and (min-width:400px){
.m-navlist{font-size:18px}
}
//设置基本的字号,基本元素取材除100即可得到rem的大小,当然也可以用16px换算改变根字号为6.25rem即可。因为还有很大比例的手机设计为320的,所以这里考虑为640的。当屏幕大于640的时候,不再放大,让页面处于水平居中640px显示。
function fontAuto(){
var deviceWidth = document.documentElement.clientWidth;
if(deviceWidth > 640) deviceWidth = 640;
document.documentElement.style.fontSize = deviceWidth / 6.4 + 'px';
}
fontAuto();
window.onresize=function(){
fontAuto();
}
阿里rem布局
淘宝的效果跟网易的效果其实是类似的,随着分辨率的变化,页面元素的尺寸和间距都相应变化,这是因为淘宝的尺寸也是使用了rem的原因。在介绍它的做法之前,先来了解一点关于viewport的知识,通常我们采用如下代码设置viewport。
<meta name="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
这样整个网页在设备内显示时的页面宽度就会等于设备逻辑像素大小,也就是device-width。这个device-width的计算公式为:设备的物理分辨率/(devicePixelRatio * scale),在scale为1的情况下,device-width = 设备的物理分辨率/devicePixelRatio 。devicePixelRatio称为设备像素比,每款设备的devicePixelRatio都是已知,并且不变的,目前高清屏,普遍都是2,不过还有更高的,比如2.5, 3 等,魅族note的手机还有6p的devicePixelRatio就是3。淘宝触屏版布局的前提就是viewport的scale根据devicePixelRatio动态设置。js中可以通过devicePixelRatio拿到具体的设备数值。
1. 动态设置viewport的scale
var scale = 1 / devicePixelRatio;
document.querySelector('meta[name="viewport"]').setAttribute('content','initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
2.动态设置font-size
document.documentElement.style.fontSize =document.documentElement.clientWidth / 10 + 'px';
(3)布局的时候,各元素的css尺寸=设计稿标注尺寸/设计稿横向分辨率/10 (4)font-size可能需要额外的媒介查询,并且font-size不使用rem,这一点跟网易是一样的。
备注:你也可以通过阿里的现成的解决方案去实现,然后在预处理器中去处理px单位的字号
<script src="http://g.tbcdn.cn/mtb/lib-flexible/%7B%7Bversion%7D%7D/??flexible_css.js,flexible.js"/>
@function s($px) {
<a href="http://www.jobbole.com/members/wx1409399284">@return</a> ($px / 75) * 1rem;
}
p{
font-size:s(40);padding-left: s(52);
}
美团rem布局
综合使用scale以及font-size的方案,更加简单。其中个元素的css尺寸为px/100,字号也使用rem作为单位。
//根据屏幕大小及dpi调整缩放和大小
(function() {
var scale = 1.0;
var ratio = 1;
if (window.devicePixelRatio >= 2) {
scale *= 0.5;
ratio *= 2;
}
var text = '<meta name="viewport" content="initial-scale=' + scale + ', maximum-scale=' + scale +', minimum-scale=' + scale + ', width=device-width, user-scalable=no" />';
document.write(text);
document.documentElement.style.fontSize = 50*ratio + "px";
})();
响应式布局
响应式这种方式在国内很少有大型企业的复杂性的网站在移动端用这种方法去做,主要原因是工作大,维护性难,所以一般都是中小型的门户或者博客类站点会采用响应式的方法从web page到web app直接一步到位,因为这样反而可以节约成本,不用再专门为自己的网站做一个web app的版本。
@media (max-width:768px){
//css
}
备注 :响应式布局还可以根据设备宽度选择按需加载不同情况下的样式,可以加在样式link标签中。 <linkrel="stylesheet"href="css/1.css"media="(max-width:500px)"/>
固定宽度布局
- 主体页面固定宽度,两边留白。
.main{
width:980px;
margin:0 atuo;
}
设置viewport进行缩放
仅仅靠这个实现适配是远远不够的,页面载入的时候会有缩放的情况,所以尽量使用rem等常规布局方式去做布局比较好。 如果你想使用这个方案,可以使用以下代码实现,针对部分安卓不适配进行了一定的修正。(这种方式还是px为单位)
function changeViewport(){
// UI-width :WebApp布局宽度
// device-width :屏幕分辨率宽度
// target-densitydpi = UI-width / device-width * window.devicePixelRatio * 160;
var uiWidth = 750,
deviceWidth = (window.orientation == 90 || window.orientation == -90) ? window.screen.height : window.screen.width;
devicePixelRatio = window.devicePixelRatio || 1;
var myScale = deviceWidth / uiWidth;
var targetDensitydpi = uiWidth / deviceWidth * devicePixelRatio * 160;
//alert(uiWidth+","+deviceWidth+","+devicePixelRatio+","+myScale+","+targetDensitydpi);
var viewportContent = "initial-scale=" + myScale + ", maximum-scale=" + myScale + ", minimum-scale=" + myScale + ',target-densitydpi=' + targetDensitydpi + ', width=device-width, user-scalable=no';
//var viewportContent = "initial-scale=" + myScale + ", maximum-scale=" + myScale + ", minimum-scale=" + myScale + ', width=device-width, user-scalable=no';
document.querySelector('meta[name=viewport]').attributes['content'].value = viewportContent;
}
window.addEventListener("orientationchange", function() {
// Announce the new orientation number
changeViewport();
}, false);
changeViewport();
媒体类型
@meida还可以根据媒体类型进行断点。
- all,所有设备
- print,打印
- screen,彩色的电脑屏幕
- speech,暂不了解
web-is-not-tomorrow-but-today