ie兼容响应式布局的实现总结

虽然说响应式设计的理想状态是,需对pc/移动各种终端进行响应;但是现实是高分辨率的pc端与手机终端屏幕相差太大,像电商这样有大量图片和文字 信息的同时排版要求精准的页面,设计一个同时适应高分辨率pc又适合小尺寸的手机终端是挑战;同时高分辨率下pc页面信息量巨大,对于手机端用户是否需 要,也许会造成带宽浪费;再者手机终端和pc终端的用户操作习惯也相差甚大,这种多图多信息量要求精准的页面,设计出来恐怕会是2个完全不同的版本,也许 各自维护更方便。由于业务形态原因,随着用户分辨率的提高,1024×768已不再是主流,宽屏用户比例越来越大,因此我们的响应式考虑如何充分利用PC 用户设备上更多空间而设计。下图为淘宝用户的屏幕分辨率和浏览器比例,鉴于ie8-浏览器目前占比约70%,media query的ie8-兼容迫于现实还是要做,泪……

media query简介

miedia query有2种引入方式:

1.link标签方式

<link type="text/css" media="screen" href="sans-serif.css">
<link type="text/css" media="print" href="serif.css">

2.css方式

@media screen {  * { font-family: sans-serif } }

媒体类型有很多种:‘aural’, ‘braille’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’, ‘tv’、‘embossed’、 ‘speech’、’3d-glasses’,但最常用的是screen和print,对于前端们来讲最常用的应该只有screen了。应用于所有媒体类 型可以用all,省略不写默认就是all。media query支持很多表达式,常用的如下,完整的查看这里:

@media all and (min-width: 400px) and (max-width: 700px) { } 
@media all and (orientation: portrait) {  } 
@media and (min-device-width: 800px) { }

利用media query可以轻松实现不同屏幕宽度时切换不同的页面布局,但是很不幸ie8及以下都还不支持media query,于是开始了下面的media query兼容之旅……

目前实现media query ie兼容的库比较成熟的有respond.js和css3-mediaqueries-js;它们各有优劣,respond.js 压缩后1k,只实现了media query中最常用的min-width max-width的兼容;css3-mediaqueries-js基本实现了所有css3规范中的media query特性的兼容,所以导致压缩有16k,测试反馈其性能远低于respond.js;不过确实一淘首页2次响应式设计均只需用到max-width 和min-width,Modernizr 和 H5BP 也均推荐使用respond.js,下面具体看看它们的实现吧

respond.js源码分析

使用方式

官方demo地址:http://scottjehl.github.com/Respond/test/test.html

  1. 在css中正常用 min/max-width media queries

    @media screen and (min-width: 480px) {     ...styles for 480px and up go here   
    }
    
  2. 引入respond.min.js,但要在css的后面(越早引入越好,在ie下面看到页面闪屏的概率就越低,因为最初css会先渲染出来,如果 respond.js加载得很后面,这时重新根据media query解析出来的css会再改变一次页面的布局等,所以看起来有闪屏的现象)

实现思路

  • 1.把head中所有的css路径取出来放入数组

  • 2.然后遍历数组一个个发ajax请求

  • 3.ajax回调后仅分析response中的media query的min-width和max-width语法,分析出viewport变化区间对应相应的css块

  • 4.页面初始化时和window.resize时,根据当前viewport使用相应的css块。

    window.matchMedia = window.matchMedia || (function(doc, undefined){var bool,docElem = doc.documentElement,refNode = docElem.firstElementChild || docElem.firstChild,// fakeBody required forfakeBody = doc.createElement_x('body'),div     = doc.createElement_x('div');div.id = 'mq-test-1';div.style.cssText = "position:absolute;top:-100em";fakeBody.style.background = "none";fakeBody.appendChild(div);return function(q){div.innerHTML = '­';docElem.insertBefore(fakeBody, refNode);bool = div.offsetWidth == 42;docElem.removeChild(fakeBody);return { matches: bool, media: q };};
    })(document);
    //检测是否支持media query,检测css是否有效的方法都差不多,创建一个元素应用该css后检测元素宽度,然后清除该元素。
    .......
    if( !!href && isCSS && !parsedSheets[ href ] ){// selectivizr exposes css through the rawCssText expandoif (sheet.styleSheet && sheet.styleSheet.rawCssText) {//sheet.styleSheet.rawCssText看不懂,原来是方便selectivizr和respond.js联用,http://selectivizr.com/tests/respond///selectivizr的作用是 CSS3 selectors for IE;约定将原csstext放在styleSheet的link上的扩展属性rawCssText上;这里如果联用selectivizr可以少次ajax请求translate( sheet.styleSheet.rawCssText, href, media );parsedSheets[ href ] = true;} else {if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base)|| href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){requestQueue.push( {href: href,media: media} );}}
    }
    .......
    其余的代码就是ajax实现和translate media query的max-width min-width的逻辑了;可以看出这里必须依赖ajax请求css路径才能得到css文件中的mediaquery的内容,那ajax的跨域问题就要 解决了;由于我们的静态资源都是要放cdn的,respond.js也给出了跨域方法,即引入代理页面。//把cross-domain/respond-proxy.html 放到cdn上
    //把cross-domain/respond.proxy.gif 放到当前域服务器上
    "http://externalcdn.com/respond-proxy.html" id="respond-proxy" rel="respond-proxy" />"/path/to/respond.proxy.gif" id="respond-redirect" rel="respond-redirect" />"/path/to/respond.proxy.js">
    这里ajax跨域实现是通过代理页面将获取到的css,再通过window.name通信实现;如在respond.proxy.js中function checkFrameName() {var cssText;try {cssText = iframe.contentWindow.name;var now = new Date().getTime(),useTime = now - initTime;alert('获取css耗时:'+ useTime + 'ms');}catch (e) { }if (cssText) {……//销毁之前用于通信的iframe,后续回调callbackcallback(cssText);}else{win.setTimeout(checkFrameName, 100);}
    }
    win.setTimeout(checkFrameName, 500);//500ms后确认内部iframe的name值是否传递过来,后续再更新当前viewport该用的css。
    

因为实现跨域代理的问题,初始化页面时应用上全部css耗时较长,以下光测试从开始执行该js文件到css取回调用之前的耗时为500ms-515ms之间(每次刷新结果不一样),ie8下测试结果如下

测试结果发现,刷新页面后会有明显的闪屏(以该测试demo为例,一开始页面背景是黑色的,这是默认css中的,跨域js执行完成后分析出 media query中的该viewport尺寸下应该应用red的背景,所以又变成红色),间隔时间为500ms以上。所以体验不是很好,而且该场景中ajax跨 域目前已经没有更好的实现方式,500ms间隔的闪屏避免不了。

同时因为是ajax请求css,所以会因为响应式而额外产生一个请求,好在之前css请求过一遍,这次ajax请求是读取浏览器缓存中的,如下图中fiddler的检测结果中的第三个请求和第六个请求:

respond.js总结

  • 优点:压缩后仅1k,不跨域时性能ok,只需引入respond.js通用易用
  • 缺点:仅支持media query的min-width和max-width(用于响应式够用);支持跨域,虽然配置有点麻烦,实现跨域代价高而且有闪屏体验欠佳。

css3-mediaqueries-js源码分析

css3-mediaqueries-js官方文档和demo都没有,相对于respond.js css3-mediaqueries-js支持几乎所有的media query的语法,访问测试demo

实现逻辑

其实现逻辑和respond.js差不多,只是更加支持的media query更加全面,同时支持内联style,支持各种宽度单位(em|ex|px|in|cm|mm|pt|pc),但是这里的初始化是在 domready后执行,为了让用户感觉不出页面有闪屏(之前应用初始化样式然后js提取media query中的样式再覆盖一遍)现象,这里的实现是先将html移出可视区域外,等解析完media query后再重置回来,但实际目测感觉稍有闪屏(当然这里的测试是测试body背景色,移出可视区域外不管用,当然绝大部分响应式场景是适用的),实现 如下:

// prevent jumping of layout by hiding everything before painting 先将html移出可视区域外
var docEl = document.documentElement;docEl.style.marginLeft = '-32767px';// make sure it comes back after a while 异常处理,万一获取mediaquery css失败,重置回来
setTimeout(function () {docEl.style.marginTop = '';
}, 20000);……// return visibility after media queries are tested 生效后重新可见
cssHelper.addListener('cssMediaQueriesTested', function () {// force repaint in IE by changing widthif (ua.ie) {docEl.style.width = '1px';}setTimeout(function () {docEl.style.width = ''; // undo widthdocEl.style.marginLeft = ''; // undo hidevar now = new Date().getTime();var useTime = now - initTime;alert('media query生效时间:'+useTime+'ms');}, 0);// remove this listener to prevent following executioncssHelper.removeListener('cssMediaQueriesTested', arguments.callee);
});

其余实现和respond.js基本一致,也需要使用ajax,所以css3-media-queries.js本身不支持跨域,当然非要支持跨域 也可以,也可以像respond.js一样使用代理页面跨域即可,但也会出现闪屏的现象。还是先看看不跨域情况下,大多数人为什么选择 respond.js,主要原因还是完美支持的media query特性导致压缩后16K,下载和执行时间都逊于respond.js,下面是同域下在ie8的测试结果(耗时140ms而respond.js仅 15ms)

css3-mediaqueries-js总结

  • 优点:1、基本支持所有css3中的media query语法
  • 缺点:1、不支持跨域(如cdn),就算支持了跨域也存在闪屏现象;2、和respond.js对比性能较差

全局切换class

因为css/js需要放到cdn上面,需要跨域,css3-mediaqueries-js不支持跨域,respond.js支持跨域但是实现跨域 后性能较差,有闪屏体验也差,而且配置麻烦,不方便各个业务通用。对比respond.js和css3-mediaqueries-js可知,实现响应式 应用min-width和max-width足矣;同时模拟media query的效果只需要在2个关键时间点根据viewport切换css(初始化页面时和window.resize)即可。所以可以选择切换css link,可以动态切换css块,也可以切换class

  • 切换css link(优点:逻辑清晰;缺点:增加请求数,维护麻烦,如修改一个模块涉及到3个尺寸的响应,至少需要改3个文件)

    "stylesheet" type="text/css" media="screen and (max-width: 990px)" href="respond750.css&uuot;>
    "stylesheet" type="text/css" media="screen and (max-width: 1200px)" href="respond990.css">
    
  • 切换内联css块(respond.js和css3-mediaqueries-js就是通过js分析出media query然后自动根据当前viewport切换css块,这个理想环境下是最好的,自动分析只管写media query,但是依赖ajax获取css内容,跨域实现成本高体验也不好)

  • 全局切换class(特别是初始化页面时最好在页面内容未开始渲染之前切换class,不然会出现像韩国naver购物频道在宽屏时刷新效果,刷新时内容由中间向外偏),特定viewport用特殊全局class标记,响应式样式继承在该class下,实现大致如下:

实现方式

@media screen and (min-width: 990px) {.content {width: 990px;color: red;}
}
@media screen and (min-width: 1200px) {.content {width: 1200px;color: green;}
}
.w990 .content {width: 990px;color: red;
}
.w1200 .content {width: 1200px;color: green;
}
"w990">
"content">content

全局切换class这种方式维护也是个问题,首先是js分散2处,body最上方切换全局class,domready时 window.resize时切换class,同时响应式尺寸增加时,需要改变js判断条件;再看css的维护,media query一份,加全局class一份相同的,维护需要同时修改2次,初期media query几十行也能接受,但是后来改版media query几百行,这样维护成本就大大增加了,全局class和media query copy相同的代码引入less解决,使用方法如下:

#channels {.w1200() {.etao-channels {padding: 170px 0 0 30px;li {margin-right: 25px;}}}.w990() {.etao-channels {padding: 25px 0 0 15px;li {margin-right: 8px;}}.w750() {.etao-channels {padding: 5px 0 0 5px;li {margin-right: 5px;}a {color: #333;}}}
}
// 这样只需维护上面一处代码即可
#channels > .w1200;
@media (max-width: 1119px) {#channels > .w990;
}
@media (max-width: 989px) {#channels > .w750;
}
.w990 {#channels > .w990;
}
.w750 {#channels > .w750;
}

目前一淘新首页采用以上方法维护,支持1200px、990px、750px三个尺寸的响应,不得不承认维护成本还是偏高,欢迎各种改进建议,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Luogu P1471 方差

题目传送门 开了十倍空间才过是什么鬼&#xff1f;该不会我线段树炸了吧……细思极恐 平均数都会求&#xff0c;维护区间和&#xff0c;到时候除一下就好了。 方差的求法如下(用的Luogu的图片) 因为要维护一个平方&#xff0c;我们可以考虑使用van♂完全平方公式将它拆开&#…

python学习day17 递归函数

递归函数 http://www.cnblogs.com/Eva-J/articles/7205734.html def age(n):if n 4:return 40elif n >0 and n < 4:return age(n1) 2print(age(1)) # 46 只要写递归函数&#xff0c;必须要有结束条件。 二分法查找 l [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,5…

2018年最好用的20个Bootstrap网站模板

Bootstrap是目前最受欢迎也是最简洁的建站方式之一&#xff0c;尤其是伴随移动端的发展&#xff0c;响应式设计已经毫无疑问成为了网页设计的趋势&#xff0c;网站建设要求兼容手机端已经是一种刚需&#xff0c;也成为提升用户体验的一种必要方式。但这无疑会加大设计师和前端人…

bit、byte、位、字节、汉字、字符之间的区别

package com.suypower.chengyu.test; public class ByteTest { /** * byte 8 bits -128 - 127 * 1 bit 1 二进制数据 * 1 byte 8 bit * 1 字母 1 byte 8 bit(位) * 1 汉字 2 byte 16 bit */ public static void main(String[] args) { // TODO Auto-generated method st…

Android SDK 2.3/3.0/4.0/4.2 下载与安装教程

Eclipse下搭建Android开发环境教程&#xff1a;http://dev.son1c.com/show/1253.html Google已经发布了Android SDK 4.2版本.下面给朋友们介绍一下安装 Android 模拟器 Emulator模拟器的方法: 1、首先确定安装了Java JDK&#xff0c;如果没有&#xff0c;可以去http://www.ora…

PMP:4.项目整合管理

内容中包含 base64string 图片造成字符过多&#xff0c;拒绝显示转载于:https://www.cnblogs.com/mapanguan/p/9916902.html

浏览器渲染原理与过程

一、浏览器如何渲染网页 要了解浏览器渲染页面的过程&#xff0c;首先得知道一个名词——关键路径渲染。关键渲染路径&#xff08;Critical Rendering Path&#xff09;是指与当前用户操作有关的内容。例如用户在浏览器中打开一个页面&#xff0c;其中页面所显示的东西就是当前…

css框架:五大css流行框架的总结-css教程-PHP中文网

本篇文章给大家带来的内容是关于css框架&#xff1a;五大css流行框架的总结&#xff0c;有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对你有所帮助。 如今&#xff0c;CSS框架越来越受欢迎&#xff0c;可以说已经应用到每一个网站上了。作为开发工具…

第十四天

###数组&#xff1a;面向对象的方式创建&#xff1a;var arr01 new Array(1,2,3,"abc");直接创建&#xff1a;var arr02 [1,2,3,"abc"]alert (arr02.length);alert(arr02[3]);var arr03 [[1,2,3],["a","b","c","d&q…

【English Email】CIP payouts now in Workday

simplification简化的[ˌsɪmplɪfɪˈkeɪʃn] quota配额[ˈkwoʊtə] regional区域的[ˈriːdʒənl] mechanics技工[məˈknɪks] annual年度的 [ˈnjuəl] mid-year年中 [mɪd jɪr] bridge桥接[brɪdʒ] Incentive激励 [ɪnˈsentɪv] Due to the simplification of …

爬取网页的通用代码框架

import requests def getHTMLText(url)try:r requests.get(url,timeout30)r.raise_for_status()r.encoding r.apparent_encodingreturn r.textexcept:return "产生异常"if__name__ "__main__"url "http://www.baidu.com"print(getHTMLText(ur…

深入理解CSS盒模型 - 程序猿的程 - 博客园

深入理解CSS盒模型 本文是学习中传思客在慕课网开的课程《前端跳槽面试必备技巧》的学习笔记。课程地址&#xff1a;https://coding.imooc.com/class/evaluation/129.html#Anchor。 如果你在面试的时候面试官让你谈谈对盒模型的理解&#xff0c;你是不是不知从何谈起。这种看似…

蓝桥杯——机器人行走

某少年宫引进了一批机器人小车。可以接受预先输入的指令&#xff0c;按指令行动。小车的基本动作很简单&#xff0c;只有3种&#xff1a;左转&#xff08;记为L&#xff09;&#xff0c;右转&#xff08;记为R&#xff09;&#xff0c;向前走若干厘米&#xff08;直接记数字&am…

JavaWeb:脚本标识

脚本标识 一、JSP表达式 1、介绍 用于向页面中输出信息 2、语法格式 <% 表达式%>3、注意 在"<%"和""之间不允许有空格&#xff0c;但是在""后面的表达式之间可以有空格不仅可以插入到网页中&#xff0c;还可以插入到HTML标记中&#xf…

线程死锁问题

1 package com.demo.bingfa;2 3 /**4 * java并发编程中&#xff0c;死锁的概念5 *6 * 我们启用了两个线程&#xff0c;分别抢占2个资源&#xff0c;但这两个资源又分别被不同的对象&#xff08;字符串&#xff09;锁住了。7 * 当第一个线程调用 resource1 方法&#xff0c;…

CSS的4个简写

CSS的4个简写 2010-12-13 18:50 聂微东 阅读(1547) 评论(3) 编辑 收藏 1.background 简写属性在一个声明中设置所有的背景属性: background-colorbackground-imagebackground-repeatbackground-attachmentbackground-position 例如: background: #444444 url(image.png…

spring boot 整合 (全)

参考: https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples转载于:https://www.cnblogs.com/lshan/p/9924005.html

使用PM2搭建在线vue.js开发环境(以守护进程方式热启动)

项目以vue.jslayUI的作为前端开发技术栈&#xff0c;需要有一个在线的环境供项目成员实时查看效果&#xff0c;总不能每次都webpack打包发布后才能看到效果吧&#xff01;刚开始就简单使用npm run dev命令热启动&#xff0c;但是shell命令窗口退出后&#xff0c;热启动也就失效…

微信小程序工具类

wechat-common-sdk ? 场景&#xff1a;目前工作中的项目需要包含并使用另一个项目。 也许是第三方库&#xff0c;或者你独立开发的&#xff0c;用于多个父项目的库。 现在问题来了&#xff1a;你想要把它们当做两个独立的项目&#xff0c;同时又想在一个项目中使用另一个。 我…

zabbix实现mysql数据库的监控

先来介绍zabbix中几个常用的术语&#xff1a; 主机&#xff08;host&#xff09;&#xff1a; 要监控的网络设备&#xff0c;可由ip或DNS名称指定。 主机组&#xff08;host group&#xff09;&#xff1a; 主机的逻辑容器&#xff0c;可以包含主机和模板&#xff…