常常听人诟病,响应式布局都不精,做什么前端,那么到底什么是响应式布局,其实现的原理在哪,我个人的看法如下:
1.目的:在项目中你会遇到不同的终端,由于终端分辨率不同,所以你要想让用户体验更好,就必要让你的页面能够适配多个终端。
2.先说一下PC端,首先rem在IE9及以下版本的浏览器是不被支持的,单位基本都是用px来写,所以PC端的响应式设计,在我看来,主要是最外围的包裹元素宽度百分百,然后第二层的包裹元素水平居中并且宽度固定,至于多宽,就要看你的UI设计图怎么给了,这里提到的最外围的包裹元素常常带有一定的背景颜色,或者水平居中的背景图案,这样当浏览器在水平方向向两端无限拉长时,正文的两旁是没有内容的,要么是空白,要么是带有一定底色或者图案,banner图的话,一般是放在中间正文的部分,不会受浏览器拉升的影响,如果不是拉升而是向里缩小,当缩小到视窗宽度比中间正文要小时,就会出现横向滚动条,很少会让中间的正文部分跟着视窗一起缩小,所以总而言之,PC端的响应式设计较为简单,毕竟光兼容问题就够我们受的了~。但是,有时需要我们先去判断设备类型,然后再去加载相应的样式和脚本(例如计算rem),可以根据媒体查询(带IE兼容的hack)去判断,也可以根据JS脚本,贴一段代码如下:
function browserType() {
if (navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)){
alert('移动端')
}else{
alert('PC端')
}
}
3.由于响应式布局多是针对移动端,所以首先要在<head>标签中添加下面这行代码:
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0" />
这将设置屏幕按1:1的尺寸显示,在 iPhone 和其他智能手机的浏览器提供网站全视图浏览,并禁止用户缩放页面。
4.媒体查询,即针对不同的屏幕尺寸设置不同的样式,它告诉浏览器页面如何呈现,假如一个终端的分辨率小于980px,那么可以这样写:
@media only screen and (max-980px){ #head { … } #content { … } #footer { … } }
或者
<link rel="stylesheet" href="style.css" media="only screen and (max-980px)"/>
如果兼容的终端类型多了,就要多写几个@media或者引入多个<link/>标签。
5.rem,通过根元素进行适配的(只参照<html>中的font-size,和<body>没有任何关系),这主要是针对响应式字体大小,可以写成:
@media only screen and (min-321px) and (max-375px){html{font-size:11px}} @media only screen and (min-376px) and (max-414px){html{font-size:12px}} @media only screen and (min-415px) and (max-639px){html{font-size:15px}} @media only screen and (min-640px) and (max-719px){html{font-size:20px}} @media only screen and (min-720px) and (max-749px){html{font-size:22.5px}} @media only screen and (min-750px) and (max-799px){html{font-size:23.5px}} @media only screen and (min-800px){html{font-size:25px}}
注意:上面是先统计自己网站有哪些主流的屏幕设备,然后去针对那些设备去做media query设置。
6.完全适配,如果要所有设备分辨率都能兼容适配,可以通过JS去动态计算根元素的font-size,最好把这个脚本放在<head>标签里,代码如下:
(function (doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function () { var clientWidth = docEl.clientWidth; if (!clientWidth) return; docEl.style.fontSize = 100 * (clientWidth / 750) + 'px'; console.log($("html").css("font-size")); }; if (!doc.addEventListener) return; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false); })(document, window);
注意:我所在公司的UI给的是750宽度的设计图,所以在该屏幕尺寸下的根元素的font-size是100px,然后直接将设计图中具体部位的尺寸大小除以100就可以得到对应的rem值,即完成了从px到rem的换算;
如果现在的屏幕尺寸是375(iphone 6),是750的一半,也就是说,设计图里指定宽度为200px(对应的width值为2rem)的地方,现在放在iphone 6上就显示为100px,但对应的width值还是2rem,所以只需要给该元素添加2rem,就实现了宽度的全适配。
7.背景图片,主要是运用background-size这个新属性,使用background简写属性的时候会将它覆盖,所以需要把它在background简写属性的后面,合在一起写也行,但在低版本的IE浏览器中会有兼容问题。
8.背景图片铺满整个屏幕的适配问题,现有一张设计图750*1200,规定铺满用户设备的整个屏幕,在用js监听设备尺寸的宽度进行适配的时候,如果出现高度放大的比例比宽度小,或者高度缩小的比例比宽度大, 那么图片就会变矮,如果仍然采取原来同比例缩放情况下的rem,元素出现的位置就比原来的位置更靠下,为了解决这个问题,有两种方案:
(1)记住垂直方向上元素的相对位置(相对于整个设备的高度)是不变的,只需要将垂直方向上涉及到rem的单位值全部上乘以压缩比例(即当前设备尺寸的屏幕高度/同比例缩放情况下的屏幕高度),即
// 计算相同缩放比例下背景图片的高度 var sameRatioHeight=1200 * ($(window).width() / 750); // 计算垂直方向每一单位的压缩比例 var changeRatio=$(window).height() / sameRatioHeight;
注意:最后在重置垂直方向DOM元素的rem单位值的时候,因为要先获取重置之前的值,所以需要在DOM页面渲染完成之后操作,即放进window.onload=function(){}中执行,如果直接在DOM节点树生成之后立即执行的话,即放进$(function(){})里面,获取到的重置之前的单位值就不是js监听适配得来的单位值,而是以根节点中原始的font-size(引入bootstrap的话就是12px)去作rem操作的得到的单位值,一个正确的例子如下:
$(function(){ // 计算相同缩放比例下背景图片的高度 var sameRatioHeight=1209 * ($(window).width() / 750); // 计算垂直方向每一单位的压缩比例 var changeRatio=$(window).height()/sameRatioHeight; // 将垂直方向涉及到rem的单位值全部乘以上面得出的压缩比例; $(window).on("load",function(){ $(".container").css("padding-top",parseInt($(".container").css("padding-top"))*changeRatio); $(".box").css("height",parseInt($(".box").css("height"))*changeRatio); $(".box1").css("margin-top",parseInt($(".box1").css("margin-top"))*changeRatio); $(".box2").css("top",parseInt($(".box2").css("top"))*changeRatio); $("p").css("font-size",parseInt($("p").css("font-size"))*changeRatio); }) })
(2)如果铺满的不是可视区,而是整个文档内容,这样背景图片就是同比例缩放,元素的相对位置和实际位置都不会变,但是会出现竖向滚动条。