了不起的IE7浏览器-CSS新特性-实现与思维变革

这篇文章发布于 2015年07月30日,星期四,23:42,归类于 CSS相关。 阅读 30127 次, 今日 3 次 11 条评论

 

一、不仅仅是IE7浏览器

本文所展示的一系列特性,以及一些思维方式的转变不仅适用于IE7浏览器,如果你的项目只需要兼容IE9+,或者你直接捣鼓移动端,其实都是适用的。

静心阅读,说不定会发现一些以前没注意的点。

虽然说,整个大中国,IE7份额远不如IE6浏览器,但是,我所从事的几个项目,IE6的占有率相当小,IE7却有6%多。

因此,IE7浏览器还是需要考量的。

以前在我还需要兼容IE6浏览器的时候,我总觉得IE6和IE7浏览器是一个路子的一个货色,很多bug和行为表现是一致的。认为,要兼容IE7和兼容IE7基本上没多大差别。后来深入实践发现,之前的想法有些天真了。实际上,IE7浏览器下,我们也能实现很多好玩且有价值的东西。

二、IE7新支持选择器以及作用

1. 多类选择器
所谓多类选择器指的是类似.classA.classB这种多个类名写在一起的选择器,实际上,IE6浏览器也是支持的,但是呢?有bug. .a.c.b.c貌似会冲突(年代久远,75%的确信),好像是要写成.c.a.c.b.

IE7浏览器大家可以放心大胆地使用,没有任何bug存在。但是呢,根据数年前我在Chrome浏览器下的测试和分析,多类选择器是CSS选择器中性能相当低下的选择器,好像没有之一。但是呢,CSS选择器本身就很快,对吧,1~2毫秒的差异其实大家也不必在意。毕竟,没人会整个CSS文件全部都是多类选择器,那就太傻了!

IE7支持多类选择器,使得我们在CSS构建的时候,可以放心大胆使用状态类名对整个项目进行控制。

所谓状态类名,有些对应于HTML控件中的一些属性,例如:.disabled, .checked, .active, .selected. 对的,这些特性整站通用,有些人可能会疑问,到处使用,不怕冲突吗?

不怕,这些状态类名,除了通用特性,其余处于一种辅助UI的角色,需要与特定场景相关联,并不会独立使用。

例如,我们项目中有两种按钮,一种是红色,一种是绿色。类名分别是:.button_red, .button_green. 在IE6年代,要实现这两种按钮的禁用态,一般是两个新的独立的类名:.button_red_disabled, .button_green_disabled. 对于按钮本身而言,貌似没什么问题,但是从整个项目来看,有失体系。

现在,IE7支持多类选择器,我们就可以使用整站通用的.disabled状态类名,红色和绿色按钮的禁用态书写,直接就是:.button_red.disabled {}.button_green.disabled {}. 然后其他什么禁用,我们就是.xxx.disabled等。

2. 相邻父子选择器
所谓相邻父子选择器指的是类似 .classA > .classB这种写法的选择器,只会控制下一层级的元素。IE6浏览器支持的选择器是“后代选择器”,也就是类似.classA .classB,两个选择器之间直接是空格,然而,这种选择器在面对复杂场景的时候,容易样式冲突,不好控制。

例如,连续的ul,li嵌套,单纯使用ul li选择器非常容易出问题,因为ul下面所有的li标签都受影响了,而实际上,我们只想控制本ul下面的li元素。在IE7+浏览器下面,就没有这样的担忧,使用ul > li选择器则完全没有这样的问题。

除了有效降低冲突,提高选择的精确度,我们还可以使用相邻父子选择器实现一些巧妙的功能。举个例子:我也页面上实现藏了几个弹框要加载的DOM元素,默认是要隐藏的,然后,加载到弹框的之前,需要是显示的。怎么搞?

我以前的做法是弹框要加载的时候,使用JS让DOM元素显示。后来鄙人发现,不需要动用JS. 由于默认的DOM元素直接放在<body>下,而弹框装载后到了弹框里面,于是,我使用了一个小小的父子选择器就搞定了整个儿显示问题。

body > .dom { display: none; }

元素一旦载入弹框,就会自动显示,因为,它已经不是<body>下相邻的子元素了。

3. 相邻兄弟选择器
相邻兄弟选择器指的是类似 .classA + .classB这种写法的选择器,表示紧跟在我后面的兄弟选择器,注意必须是紧跟着的兄弟,其他远一点的,或者前面的兄弟都不行。

别小看这个选择器,我们可以让IE7浏览器也绽放夺目的光彩。

先举个简单实用的小例子。我们使用弹框的时候,右下角或左下角或者中间都有两个按钮,按钮之间有一定的距离,假设20像素:

弹框按钮截图

有没有什么方法实现单纯的20像素间距,而没有其他多余的margin呢?

传统思路可能是这样:

.button { margin-left: 20px; }
.button:first-child { margin-left: 0; }

中文释义就是,左边20像素间距,其中,第一个按钮左间距为0. 鼓掌。其实不失为一个好方法。如果我们转换下思路,实现起来可能就更加简单了:

.button + .button { margin-left: 20px; }

天然第一个按钮不会有margin-left间距值。

再举个大点的也更实用的例子,大家可能听过CSS3单复选框技术. 在IE9+浏览器下,我们可以使用单选框和复选框的一些特性,实现展开收起,选项卡,开关效果等。

实际上,我们IE7浏览器也能近似实现这样的效果。IE7、IE8虽然不支持原生的CSS3选择器:checked, 但是,属性选择器还是基本支持的,加上同样支持各类兄弟选择器,于是,IE7浏览器也能渐进使用这类CSS3新技术。

:checked + .xxx { /* IE9+选中效果 */ }
[checked] + .xxx { /* IE8选中效果 */ }
[defaultChecked] + .xxx { /* IE7选中效果 */ }

4. 兄弟选择器
兄弟选择器指的是类似 .classA ~ .classB这种写法的选择器,使用的是弯弯符号,表示A元素后面的所有兄弟元素。对,只能是后面的元素。严格来说,这是个CSS3选择器,但是IE7浏览器支持之,且我使用下来还没遇到过什么诡异问题。

IE7+浏览器下,由于相邻兄弟选择器和兄弟选择器的存在,我们在JS构建一些DOM元素来实现一些UI组件效果的时候,我们的处理方法可能就会发生一些变化。举个例子,placeholder占位符效果。从实现上讲,input元素前插入构建的含placeholder值的元素是最简单也更容易定位的;但是,实际实现的时候,确实要遵循后置原则, 也就是创建的元素要在目标元素的后面。

为什么呢?

原因很简单,在CSS中,我们没有前兄弟选择器,只有后兄弟选择器。于是,我们只能根据前面兄弟控制后面。

还是上面placeholder例子,由于我们是后置实现,于是,我们就能轻松通过CSS实现focus时候,placeholder文字透明度降低到40%的效果:

input:focus + .xxx { filter: alpha(opacity=40); }

但是,要是你前置,或者包裹,都是不行滴!

5. 属性选择器
包括CSS 2.1水平的属性选择器[attr], [attr="val"], [attr~="val"], [attr|="bar"]以及CSS3水平的属性选择器[foo^="bar"], [foo$="bar"], [foo*="bar"].

没错,所有这些属性选择器IE7浏览器都是支持的,虽然某些细节上有些小bug, 但是,基本的属性全部都是支持的。

于是,我们就可以使用属性选择器,隐藏项目中所有的单复选框以及submit按钮,而使用UI更好的自定义<label>控件元素替换显示。

input[type='radio'],
input[type='checkbox'],
input[type='submit'] {
    position: absolute;
    clip: rect(0 0 0 0);
}

好了,老一代的前端由于IE6不支持属性选择器,可能不太认识;新一代的移动端的前端可能只知道CSS3属性选择器,这里有必要简单科普下,尤其[attr~="val"], [attr|="bar"]这两厮。

[attr~=”val”]
这个表示,属性值中间,有匹配val的单词,注意这里的名词——“单词”。CSS3中有一个[foo*="bar"],表示,属性值中间,有匹配的字符内容,这里这里的名词——“字符”。大家都知道,CSS选择器这东西是老外弄出来的,老外的的母语是English, English的句子都是一个单词+空格+一个单词实现的。这这里的[attr~="val"]就是用来匹配这些单词的。因此:

<div attr="val"></div>      
<div attr="text val"></div> 
<div attr="value"></div>    
<div attr="val-ue"></div>   

表情出卖了一切。笑脸是支持,能识别,抓狂是不能识别。而[attr*="val"]上面4个都是支持的,因为,每个attr属性值都有val字符。

[attr|=”bar”]
这个表示,属性值开头必须是bar的单词,或者开头是bar-。CSS3中有一个[foo^="bar"],表示属性值以bar字符开头即可。类似上面的单词和字符的区别,因此有:

<div attr="bar"></div>      
<div attr="bar-val"></div> 
<div attr="barval"></div>    
<div attr="bar val"></div>   

同样的,如果是使用[foo^="bar"] CSS3选择器,则上面4个都是支持的,因为,每个attr属性值开头都是bar字符。

其他属性选择器,通俗易懂,我就不详细说明了。

6. first-child伪类选择器
IE7浏览器还支持:first-child伪类,可以选择第一个子元素。

但是呢,与之对应的:last-child伪类却不支持,别说IE7浏览器了,IE8浏览器也不支持:last-child伪类,一直到IE9浏览器才支持。

这个伪类能做的事情可多了,各种列表啊,或者细节带图标的按钮啊,等等,对吧,绝对可以释放更多的页面构建的创造力。

三、新支持的CSS声明或特性

1. position:fixed固定定位
IE6浏览器只支持absolute定位,IE7——开始支持fixed定位,也就是浏览器观点,元素位置不变,纹丝不动,不被滚走。

position:fixed除了基本的定位功能,还能实现纯CSS控制的全屏遮罩效果,以前的JS动态计算就不用了等等,一些珍藏秘籍,以后有机会再分享。

2. min/max-width/height最大/小宽度高度
可以实现特定宽度区间内的自适应布局。例如:1024像素到1280像素,就可以使用min/max-width/height控制,不需要JS参与,兼容IE7+浏览器。

min/max-width/height本质上也属于响应式CSS属性。其作用还是很强的,使用频率也是相当之高,以前棘手的特定范围内的图片尺寸控制也有了新思路。

3. absolute拉伸
absolute元素,如果没有明显的尺寸限制说,当left/righttop/bottom对立方向的属性值同时存在的时候,元素的尺寸会被拉伸,同时,该拉伸的元素内部支持百分比高度,于是我们就能四线高度自适应效果实现。

并再次基础上衍生出内滚动布局等等。

4. png alpha透明
以前IE6浏览器只支持索引透明,IE7浏览器下面,不仅索引透明支持,Alpha通道透明也支持。于是乎,我们的布局更自由,图片资源利用率更好了,因为PNG图片适用于各种场景各种背景,从此告别传统年代图标的毛刺的效果图。

5. border-color:transparent透明
以前IE6浏览器,边框颜色设为transparent实际上显示的是黑色,但是IE7浏览器支持边框透明色,使用border模拟图形的时候,就少了很多阻碍。

四、JS部分

Ajax请求可以使用XMLHttpRequest了。

等。

五、结语部分

总之,最近做的些不用管IE6,需要兼容IE7的项目,让我发现了很多好玩地东西,页面重构的创造力也比IE6时代要高很多很多。

CSS/HTML技术有时候就是那么回事,看上去挺简单的,但是一旦深入下去,加上自己的创造力和新思维,会发现,尼玛原来做的事情可以有这么多!

好了,已经开始打瞌睡了。已经没有以前结尾可以洋洋洒洒吐槽一大波文字的精气神了。

姿势有限,如果大家发现有错误之处,欢迎纠正,不甚感谢!也欢迎诸位补充可能遗漏的一些IE7的闪光点。

感谢阅读!

(本篇完)

分享到:


发表评论(目前11 条评论)

  1. ie9下固定定位失效说道:

    大神,ie9下用position:fixed来写遮罩层和弹窗,遮罩无效(用的rgba,背景色不起作用),弹窗掉到了页面底部;改用position:absolute来写遮罩和弹窗,弹窗在页面中显示出来了,但是不随页面滚动而滚动,遮罩也无效(用的rgba,背景色不起作用)。求大神指点。

  2. ie9下固定定位失效说道:

    ie9下固定定位失效

  3. yao说道:

    好文章!

  4. hkongm说道:

    ~=和|=精髓!

  5. crwinl说道:

    感谢分享~~

  6. tcdona说道:

    赞,又学到了

  7. llj说道:

    我感觉大神去掉洋洋洒洒的吐槽会更让人感觉容易理解

  8. moto说道:

    “要兼容IE7和兼容IE7基本上没多大差别” 这句,有文字错误。哈哈

  9. jason、说道:

    旭哥你好,这段文字没看懂
    “我以前的做法是弹框要加载的时候,使用JS让DOM元素显示。后来鄙人发现,不需要动用JS. 由于默认的DOM元素直接放在下,而弹框装载后到了弹框里面,于是,我使用了一个小小的父子选择器就搞定了整个儿显示问题。”.
    不知道是不是你写的太简洁了还是我思维没转过来,可是没理解,为什么增加body > .dom{}就可以在加载的时候显示呢!

    • 张 鑫旭说道:

      @jason 因为在加载的时候,该DOM在弹框内部,已经不是body的相邻子元素,而是相距很远的子元素。此时body > .dom{}是没有效果的。

      • Joey说道:

        旭哥,我的理解是,该DOM元素原本属于body的相邻子元素,然后利用js将该DOM复制到某一个节点中,从而使>选择不起作用,显示该DOM元素?