这篇文章发布于 2012年05月11日,星期五,22:32,归类于 JS实例。 阅读 96912 次, 今日 5 次 21 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=2387
一、容我唠叨
我们都知道,CSS3 media queries
是响应布局实现之利器。国外很多著名的前端站点,如css-tricks, smashingmagazinegazine等都采用了响应布局。
虽然国内此技术应用就像是打不着的打火机,没法跟如火如荼的欧美相比。但是,毕竟趋势是向前发展的,总会迎来遍地开花的时候,只是时间的长短而已。
本文所涉及的三个关键技术点,伪类(IE8+), js(getComputedStyle, IE9+)以及media queries(IE9+)都需要现代浏览器的支持。因此,如果您不是做HTML5开发,或是从事的是面向大众的普通web页面,本文内容没有任何实用价值。有帮助的,估计就是拓宽思路,增长眼界了。因此,本文内容很快就会归于沉寂,或许5年之后,某君阴差阳错进入此处,发现此文,会不由得惊叹——原来很多年前就有人介绍这个技术啦!但是,历史的发展与推动少不了那些湮没在历史中的开拓者。
media queries
可以让设备在不同尺寸下应用不同的CSS样式、布局等。以适应手持设备、普屏显示器、宽屏显示器,以及未来冰箱上的联网显示器,汽车上的数码设备等。然后,仅仅通过CSS做布局可能无法应对所有的交互请求。
举个简单例子,我们打开浏览器可能处于非最大化状态,此时,如果作为普屏处理,加载的图片可能就是128*128的小尺寸图片。但是,当我们最大化以获得更好阅读体验的时候,需要使用更大尺寸的图片256*256, 使用media queries
? 拜托,CSS只能改变外在的尺寸,你难道要2倍尺寸拉伸?显然,更合理的做法是加载256*256尺寸的中等尺寸图片。以目前的技术而言,估计除了使用JS修改图片src
外,很难有其他更可用的方法了。
OK, 现在问题来了,如何让JS的修改与CSS布局改变同步呢?
二、CSS交互与JS交互同步问题
如何让CSS样式、布局改变的时候,同时准确触发JS的交互呢?
方法一、直接宽度/高度值匹配
何意?CSS3 media queries
跨界触发一般都有一个宽度或高度值,或是color(很少使用)。例如,普屏图片宽度128*128,可能就是如下CSS:
@media screen and (max-width: 1024px) { img { width: 128px; height: 128px; } }
意思就是screen(屏幕)宽度不超过1024像素(max-width:1024px
)的时候,图片宽度是128像素,高度也是128像素。
因此,我们可能通过浏览器窗口尺寸改变的resize事件中捕获浏览器窗口尺寸,与1024对比,如果小于则触发对应的普屏事件处理,大于,则宽屏处理。
window.addEventListener("resize", function() { // window.innerWidth IE9+浏览器支持 if (window.innerWidth <= 1024) { // 普屏处理 } else { //宽屏处理 } });
确实是简单高效的方法。但是,也是有不足的。
① 可维护性
一个载体所对应的数值是会经常变的。例如,小胖今天体重148斤,明天喝碧生源厕所来回几个小时,可能就只有145斤了。同样的,对于1024这个值,变动的几率是很大的。变动其实没什么,麻烦的是下面的JS中的判断的数值与CSS中的限制是要一致的。也就是CSS宽度阈值改变,JS也要跟着变。显然,这种高耦合增加了后期的维护成本。
② 宽度的计算与不确定性
window.innerWidth
返回的是窗口内部宽度(不包括浏览器的框框),单位是像素。但是,width
属性的单位并不固定。有些站点,可能使用em
, %
或最新的vw
, rem
, in
等(完整单位参见之前“CSS长度值及时间、频率、角度单位”一文)。
而这些单位的宽度转换成px
就需要计算,而这些单位很多是相对的,例如em
是与字体大小相关的,如果网页的字体大小被用户手动改变(视力不佳用户,或是“Ctrl + 加号”的误操作),可能你之前按照12像素比例的宽度计算就会不准确。这就是宽度计算的不确定性。
可见,我们有必要寻求更佳的同步方法。什么呢,就通过CSS本身!
通过CSS本身?
比方说吧(虽然这个例子实用性不佳),我们通过media queries
让图片宽度变成128像素,就可以通过检测图片应用的宽度判断当前设备状态。
当然,这里只是举例,其实这比上面1024px方法更搓,因为,牵扯到实际样式的CSS是会经常变动的,JS显然不能与之高耦合。
那该如何应用呢?很简单,应用在不会使用的元素,不会产生额外影响的CSS属性。例如在<head>
标签上使用z-index
属性(from Stephanie)。
@media screen and (min-width: 45em) { head { z-index: 2; } }
不过,根据Jeremy Keith的测试,Webkit浏览器貌似不支持,其返回的z-index
值是auto
, 不是数值2
. 我那热乎乎的小心脏,瞬间冰冻,啊~~
应用在<body>
标签上到是可以的,不过,由于body标签暴露在外,参与CSS布局,如何其设置了定位属性(relative, absolute等),z-index
立马勃起,如果里面在层级复杂点,哦呵呵,兄弟你把妹的时间估计要陪代码咯!
不过,对于一般的页面(不是类似游戏页面,幻灯片页面的页面),只有某些艺高人才敢在body上增加定位属性(违背最小化影响原则 – part 7),因此,在body
上设置z-index
属性一般问题不大,但是,从可理解性上讲,z-index
弱了点。因为,z-index
值一般是数值。你说:
800~1024 z-index:1; 1024~1280 z-index:2; 1280~1440 z-index:3; 1440~1680 z-index:4;
两个月后,你在看JS中,zIndex
的1
, 2
, 3
, 4
,你还记得对应的数值范围吗?别人经手你的代码,知道各个数值对应的含义吗?(别跟我扯注释~~)
因此,我们需要寻求更佳的方案。
方法二、body标签+伪类+content内容生成
因为每个页面都有body
标签,在该标签上打标记便于整站通用。
这里的伪类指:after
, :before
亦可,因为,使用该CSS属性与实际用途冲突概率要比z-index
属性小多了,更加安全。
content内容生成我专门写过一篇文章:“CSS content内容生成技术以及应用”,后来又结果伪类属性写了篇:“:after伪类+content内容生成经典应用”。您有兴趣可以看看。而这里,则是一个新的应用典型了。
使用content内容生成的最大好处在于,我们可以随意定义里面的内容(z-index只能数值),例如:
{ content: "普屏"; }
显然,这个描述性的文字是很泛的,概括性强,不会因为1024px
变成980px
而跟着变动,而且,含义明显,一目了然。
因此,上面的一番分析总结,body:after + content
是相当好的一个方法。
我们唯一剩下的技术难点就是如何使用JS获取content
的内容。当当当当,前几天的写的“获取元素CSS值之getComputedStyle方法熟悉”一文内容就派上用场了。
使用方法就是标题中的getComputedStyle
:
var content = window.getComputedStyle(document.body, ":after").getPropertyValue("content");
然后,我们就可以根据content
的具体内容,准确捕获media queries越界的瞬间,并作出相关的JS交互了!
if (content === "窄屏") { // …… } else if (content === "普屏") { // …… } else if (content === "宽屏") { // …… }
三、百闻不如一见
您可以狠狠地点击这里:伪类+js与media queries跨界demo
下图为宽屏(1680px
)下等比缩放的效果图:
我们修在宽度改成1024px
,则图片不仅尺寸变小了,src地址也应用了小图的地址:
相关CSS代码如下:
.demo img { width: 512px; } @media screen and (max-width: 1024px) { body:after { display: none; content: 'normalscreen'; } .demo img { width: 256px; } }
JS代码比较长,这里就不完整展示了,不过有个东西很重要,需要提醒下:
getComputedStyle
返回的content
值在某些浏览器下是带有引号的,因此,你不能使用===
直接匹配,可以使用简单正则test
方法(demo页面的方法),或是索引查找indexOf
方法,或是字符分隔split
方法等。
if (content === "normalscreen") {}if (/normalscreen/.test(content)) {}
四、我肚子很饿
上午驾驶员考试,考桩考和小路,请假了,下午才回来。于是,晚上忙着赶活,完成本文,晚饭也懒得吃,因此,现在还饿着。本来想补一个media queries
与transition
动画配合,使用JS做响应延迟的例子(跨界的时候,应用了transition
的元素动画,此时,即时响应的JS交互可能就会出问题,如定位等)。
不过,肚子饿饿,就懒得搞了。好,我要赶快撤了,去吃西北口味的“茄子牛肉盖浇饭”,我口水下来咯~~
本文为原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=2387
(本篇完)
- 应运而生的web页面响应布局 (0.333)
- 翻译:web响应设计,乏味! (0.333)
- 热门:响应图片(Responsive Images)技术简介 (0.333)
- 获取元素CSS值之getComputedStyle方法熟悉 (0.306)
- :after伪类+content内容生成经典应用举例 (0.264)
- 内容loading加载后高度变化CSS3 transition体验优化 (0.239)
- 响应式图片srcset全新释义sizes属性w描述符 (0.229)
- CSS/CSS3长度、时间、频率、角度单位大全 (0.212)
- 我是如何在实际项目中使用before/after伪元素的 (0.197)
- Canvas中颜色过渡动画效果的实现 (0.191)
- CSS ::marker伪元素简介 (RANDOM - 0.149)
正好还有几天就5年了,我不小心点了进来。。
刚好查到这里,谢谢。
?
为什么我jq获取css的-webkit-transform 返回的是 matrix(1, 0, 0, 1, 0, -300)
我要拿到那个-300怎么拿
这个方法真不错的样子。。。正好能用到。。可以试验一下。。试验完回来报告结果
你好,想请教您一个问题,关于media queries不兼容IE678等低版本浏览器,网上查资料说需要加载一个脚本 css3-mediaqueries.js ,可是试过没起作用,想知道除了在头部添加此js之外,还需要有哪些变化吗?
@susan 换一个试试。 网上响应布局脚本多如牛毛,搜英文不要百度。
你解决这个问题了么 ?解决了 请分享 我的问题跟你的一样
解决了的也给我分享下,正为这个问题发愁呢
最近刚碰到这个问题,发现了一个实用的小插件
https://github.com/JoshBarr/js-media-queries
原理跟LZ的第二点是一样的,不过把content的内容写进了html font-family,貌似是避免案桌的兼容问题
话说,定义window.onresize事件函数不行吗
说的对
web developer没有firebug好用啊
你好呀,请问你这篇文章里的图 :窗口大小 里的插件是哪个浏览器的:)
@小牛牛 FireFox 前端必备插件 web developer
强人····
可以 @media 然后不要用 img 元素了。。。用 background-image 代替。。。
Where is the demo?
注意身体,按时进饭,预祝顺利拿到驾照,哈
想了一会没想到能取代content的属性,,
只是这个demo本身不够复杂,让img作为background,然后media queries判断就不需要用到JS了
楼主思维很严谨啊