CSS 相对/绝对(relative/absolute)定位系列(三)

标签: css相关 absolute float IE6 IE7 | 发表时间:2011-03-20 22:32 | 作者:张 鑫旭 恋上女人香
出处:http://www.zhangxinxu.com/wordpress

by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=1528

//zxx:直接接上回

一、absolute正业之元素隐藏

元素隐藏与显示是我们在页面制作与交互效果实现中非常常见的,如果您只是使用display:nonedisplay:block/inline来实现DOM元素的显隐控制,那你就out了。就元素的显示与隐藏实现,使用display在有些时候算是比较糟糕的方法了。

控制元素显隐的方法很多,但是本文不是讲元素显隐控制的,所以,只讲与absolute相关的一些方法。
absolute属性相关的隐藏方法,我知道的有三种,分别如下:

.hidden{
    position:absolute;
    top:-9999em;
}
.hidden{
    position:absolute;
    visibility:hidden;
}
.hidden{
    position:absolute;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
}

使用absolute属性控制DOM元素的显隐有三个关键点:页面可用性回流与渲染配合JavaScript的控制

① 可用性隐藏
所谓可用性隐藏,就是兼顾屏幕阅读器这类互联网阅读辅助设备的隐藏方式。Yahoo! 可用性实验室成员Ted Drake就不同隐藏方法下屏幕阅读器的可用性问题作为测试,结果发现下面两种隐藏方式屏幕阅读器是读不了的。

.completelyhidden {
    display:none;
}
.visibilityhidden {
    visibility:hidden;
}

You don’t want to show those hidden panels to any user. Use display:none for the hidden panels.

Screen readers will also ignore sections with visibility:hidden.

所以,从可用性角度而言,像“选项卡内容”,“更多收起展开”这类元素隐藏与显示就不推荐使用display:none, 或者是position:absolute + visibility:hidden

例如优酷网电影或视频的简介中“显示详情”的实现就是使用的display:none,如下截图:
优酷网的展开详情display:none实现 张鑫旭-鑫空间-鑫生活

而大众点评网的隐藏层多采用position:absolute + visibility:hidden的方法,如下截图:
大众点评网隐藏层的实现 张鑫旭-鑫空间-鑫生活

上述隐藏内容其实都是有用的信息,对于像盲人这类需要借助屏幕阅读器的用户无法知道这些信息了。拿优酷的那个例子,盲人用户就无法知道影片完整的简介。

如果希望隐藏内容能够被辅助阅读设备识别,就不能使用display:none以及visibility:hidden隐藏元素。可以使用模拟隐藏的隐藏方法,又称可用性隐藏。就是下面两种隐藏方法。

.hidden{
    position:absolute;
    top:-9999em;
}
.hidden{
    position:absolute;
    clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
    clip: rect(1px, 1px, 1px, 1px);
}

但是,如果你是希望完全隐藏的,那就可以使用display:nonevisibility:hidden

额外说明:如果隐藏元素含有链接元素或是可获得焦点的控件元素,但是又是使用的可用性隐藏。这些隐藏的链接与控件也是可以响应键盘焦点Tab切换的,但是这会让键盘使用用户产生不解与疑惑的。所以,从某种意义说,某些情况下,要兼顾屏幕阅读器用户和键盘用户有时候是不可兼得的。

②回流与渲染
早先时候我曾翻译过两篇关于回流与重绘的文章,“最小化浏览器中的回流(reflow)”以及“回流与重绘:CSS性能让JavaScript变慢?”。

我自己是没测过。不过根据上面这两篇文章的说法,以及一位口碑前端前辈的说法,使用absolute隐藏于显示元素是会产生重绘而不会产生强烈的回流。而使用display:none不仅会重绘,还会产生回流,DOM影响范围越广,回流越强烈。所以,就JavaScript交互的呈现性能上来讲,使用absolute隐藏是要优于display相关隐藏的。

③配合JavaScript的控制
说到元素的显示与隐藏,免不了与JavaScript的交互。例如display相关的隐藏于显示,就是display:block/inline/inline-block/...display:none
要让元素隐藏,很简单,直接:

dom.style.display = "none";

但是,如果要显示隐藏的元素,咋办呢?因为不同的标签所处的display水平是不一样的,于是,我们很难有一个简单的统一的显示方法。例如,下面的代码可能使用于div, p标签,但是对于span等inline水平的元素,可能就会嗝屁了(原本单行显示结果换行)。

dom.style.display = "block";

况且,随着浏览器的不断进步,以后类似于display:table-celldisplay:list-item会越来越多的使用。再想通过display实现通用的显隐方法难度又会增大些。

这就是使用display属性控制元素显隐的局限性。顺带一提的是jQuery的显隐方法show()/hide()/toggle()就是基于display的,其会存储元素先前的display属性值,于是元素再显示的时候就可以准确地显示出之前的display值了。

您可以狠狠地点击这里:jQuery与display的显隐测试
jQuery存储display数组值 张鑫旭-鑫空间-鑫生活

而使用绝对定位实现的一些元素隐藏方法的控制就相对简单很多的。例如:position:absolute + visibility:hidden方法,当我们要让元素(原本非绝对定位元素)显示的时候,我们需要设置:

dom.style.position = "static";
dom.style.visibility = "visible";

而类似的position:absolute + top:-999em方法,当我们要让元素(原本非绝对定位元素)显示的时候,我们只需要设置:

dom.style.position = "static";

而无需担心原本标签的是inline水平还是block水平。所以,就显隐的JavaScript控制上来讲,absolute相关方法要比display略胜一筹。

结合上面三点讨论,我们可以看出,当前占据主流的display:block/none控制元素显示与隐藏的方法其实是诸多方面有弊端的方法,有拿着鸡毛当令箭的意味。实际上,这种活(元素显隐)交给absolute属性更合适,控制元素显示与隐藏才是absolute属性的正业所在//zxx: display属性控制元素显隐之所以会控制大半壁江山是因为其语义就是“显示(display)”,于是先入为主,再加上人的从众性。

如果您看到下面的文字,可能是由于在其他网站或是RSS中阅读本文,本文原地址:http://www.zhangxinxu.com/wordpress/?p=1528,本文作者:张鑫旭,来自张鑫旭-鑫空间-鑫生活,访问原出处更多优秀技术文章。

二、absolute与等高布局

拿简单的两栏布局举例,左栏与右栏有不同的背景色,且中间隔边框线分隔,如何实现?因为随着内容的不同,有可能左侧栏高度较高,也有可能是右侧栏高度较高。所以,要实现无缝的填色,定高不行不通的,置高度不理显然也不行,此时解决方法就是让左右两栏等高。

我较早的时候写过一篇名为“纯CSS实现侧边栏/分栏高度自动相等”的小tip,其实现原理如下:

margin-bottom:-3000px; padding-bottom:3000px;

后来在“我所知道的几种display:table-cell的应用”一文中也提过使用display:table-cell实现等高布局。

这里再介绍些如何使用absolute实现等高布局。

正如系列前篇所述,应用了position:absolute的元素无宽度,无高度。正好,我们可以利用该特性来实现等高布局所需要的效果——如等高的背景色、边框效果等。

您可以狠狠地点击这里:绝对定位与等高布局demo

点击demo页面中的两个按钮就可以看到无论左侧栏高还是右侧栏高,两边背景颜色纯纯的,中间的垂直分隔线直直的,如下截图:
绝对定位等高布局左侧栏高度较高 张鑫旭-鑫空间-鑫生活
绝对定位等高布局右侧栏高度高 张鑫旭-鑫空间-鑫生活

其中,实现等高效果的核心CSS代码如下:

.equal_height{width:100%; height:999em; position:absolute; left:0; top:0;}

同时,满足以下一些条件:

  1. 高度999em的绝对定位层位于侧栏容器内,侧栏positionrelative
  2. 该栏实际元素内容用一个与absolute绝对定位层为兄弟关系的标签层包裹,positionrelativez-index1或其他
  3. 左右栏的父标签需设置overflow:hidden,同时为了兼容IE6/7,需设置positionrelative

以上条件对应下图标注:
绝对定位等高布局实现条件标注 张鑫旭-鑫空间-鑫生活

原理很简单:由于绝对定位元素无高度的特性无宽度的特性,我们可以伪造一个高度足够高的绝对定位层(设置背景色,边框等属性),同时设置父标签溢出隐藏,那么其多出来的高度酒不会显示了,也就实现了看上去的等高布局效果了。具体细节可参见demo页面中的代码展示,相信很好理解的。

如果您看到下面的文字,可能是由于在其他网站或是RSS中阅读本文,本文原地址:http://www.zhangxinxu.com/wordpress/?p=1528,本文作者:张鑫旭,来自张鑫旭-鑫空间-鑫生活,访问原出处更多优秀技术文章。

三、absolute属性与IE6/IE7之间的误会

absolute属性确实存在不少兼容性的问题,首先absolute属性定位相关(left/top)的些bug(例如IE6的奇偶bug)这里不予以讨论。//zxx:很多人都知道,再说就没意思了。

所以,下面所展示的些“误会”都是没有定位属性的(即无left/top/right/bottom)。

1. margin定位元素绝对定位元素重叠的误会
以前经常碰到的,今天怎么都模拟不出来了,这个先空着,回头补上…… (*^__^*) 嘻嘻……

补充于2011-04-18
很简单,双栏自适应布局中,左侧元素absolute绝对定位,右侧的margin撑开距离定位。可参见“页面重构鑫三无准则 之无宽度准则”一文中新浪微博的实例页面中的使用(那里是padding撑开距离)。

为了再现IE6/IE7下的这个argin定位元素绝对定位元素重叠的误会,我特地做了个简单的demo页面,您可以狠狠地点击这里:IE6/7下margin与absolute元素重叠demo

可以看到在IE6/7下左侧应用了absolute属性的图片与右边的自适应的文字内容重叠了,如下图所示(截自IE7):
IE7下margin元素与absolute元素重叠 张鑫旭-鑫空间-鑫生活

此问题出现的原因与下面浮动与绝对定位元素重叠有着某些类似的原因,因为问题的出现都与绝对定位元素所在的标签水平有关:上述demo中,absolute属性所在的标签是div标签,属于block水平的元素。如下截图:
使用的div标签 张鑫旭-鑫空间-鑫生活

要是我们把这里的block水平的div元素修改成inline水平的span标签,则重叠的问题就没有了。如下截图:
span标签下的重叠问题的修复 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:IE6/7下margin与absolute元素重叠问题修复demo

如果您手上的浏览器是即使是IE6/IE7,点击上面的demo页面也不会有重叠的bug了,而此问题的修复是非常简单的将div标签换成span,如下截图所示:
换成span标签的示意截图 张鑫旭-鑫空间-鑫生活

2. 浮动与绝对定位元素重叠的误会
很简单,前面一个标签是浮动元素,后面的是block水平的绝对定位元素,结果IE8+,以及现代浏览器文字与图片重叠;但是IE6/IE7浏览器确是并排显示的。如下截图示意:
IE8下文字与图片重叠 张鑫旭-鑫空间-鑫生活
IE6下图文并排 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:浮动元素绝对定位元素重叠demo

CSS代码如下:

.box{padding:1em; background-color:#f0f3f9; overflow:hidden; _zoom:1;}
.l{float:left;}
.abs{position:absolute;}

HTML代码如下:

<div class="box">
    <img class="l" src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" />
    <div class="abs">呦喝,这不是张含韵小姐吗?</div>
</div>

为何现代浏览器以及IE8+浏览器下浮动的图片与绝对定位的文字会重叠,而IE6/7却是并列显示?这是由于IE6/IE7浏览器将inline水平标签元素和block水平的标签元素没有加以区分一视同仁渲染了。我在前面已经多次提到,应用了绝对定位属性的元素具有包裹性,等同于没有高度与宽度的inline-block元素

上面斜体加粗的这个结论实际上说得不够严谨,在IE6/IE7浏览器下,上面的话是没错的;在所有浏览器下,对于inline水平的元素,上面的话也是没错的;但是在现代浏览器下,对于block水平的元素,上面的结论就有商榷之处。实际上,按照正确的绝对定位渲染,像div, p这类block水平标签并未完全inline-block化。inline-block化的元素有三大特性:包裹性;高宽可定义;图文混排。然而,div, p这类标签应用了position:absolute后,在非IE6/7浏览器下,只有包裹性和高宽可定义这两个特性,但并不支持图片混排,也就是与图片文字在一起的时候会换行。

下面是举例字,验证上面的结论。首先是这么句话:“对于inline水平的元素,上面的话也是没错的”。这句话的意思其实是,如果是inline水平的元素,上面的那个示例就不会有兼容性问题了,于是我们把应用了abs类名的div标签改成span,如下HTML代码:

<div class="box">
    <img class="l" src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" />
    <span class="abs">呦喝,这不是张含韵小姐吗?</span>
</div>

结果如下图:
IE8下浮动元素与绝对定位元素并排显示 张鑫旭-鑫空间-鑫生活

不仅IE8浏览器,Firefox/Chrome等先前重叠的现在都并排显示了。

您可以狠狠地点击这里:浮动与inline水平绝对定位元素不重叠demo

下面再来验证这个结论:“现代浏览器下block水平元素absolute化后不支持图片混排”。也是很简单的,我们可以把最上面重叠的那个例子的图片的浮动属性干掉,也就是如下的HTML代码:

<div class="box">
    <img src="http://image.zhangxinxu.com/image/study/s/s128/mm1.jpg" />
    <div class="abs">呦喝,这不是张含韵小姐吗?</div>
</div>

结果如下图:
IE8下绝对定位元素与图片换行 张鑫旭-鑫空间-鑫生活

而在IE6/IE7浏览器下,依旧是并排显示滴,如下图:
IE6/IE7下依旧并排显示 张鑫旭-鑫空间-鑫生活

OK,现在应该很好理解最上面为何在现代浏览器下图片文字重叠而IE6/IE7下并排显示了。

在“CSS float浮动的深入研究、详解及拓展”系列中多次阐述了浮动元素的“无高度”特性,所以,当图片应用了float:left属性后,图片所占据的高度丢失,于是,原本换行显示在下面的文字就提上去了,于是就形成了重叠,如下图标示:
浮动与绝对定位重叠图示 张鑫旭-鑫空间-鑫生活

四、下节看点

下篇讲relative属性,内容包括:
relative的占位性;
relative最小化影响原则;
relative在一些bug中的修复功能;
等……

时间仓促,资质有限,文章难免有表述不准确或是理解有误的地方,欢迎指正,不甚感谢。

原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=1528

(本篇完)

有话要说,点击这里发表评论。

相关 [css 相对 绝对] 推荐:

CSS 相对/绝对(relative/absolute)定位系列(四)

- Jerry - 张鑫旭-鑫空间-鑫生活
本文地址:http://www.zhangxinxu.com/wordpress/?p=1834. 前三篇(1, 2, 3)都是介绍的absolute属性,终于,轮到本文讲讲relative相对定位. 一、relative属性的形象化思维. relative是个看上去低调,有些特殊才能,气场强大,有着不俗身世,但无形中会影响他人的凡人.

CSS 相对/绝对(relative/absolute)定位系列(三)

- 恋上女人香 - 张鑫旭-鑫空间-鑫生活
本文地址:http://www.zhangxinxu.com/wordpress/?p=1528. 一、absolute正业之元素隐藏. 元素隐藏与显示是我们在页面制作与交互效果实现中非常常见的,如果您只是使用display:none与display:block/inline来实现DOM元素的显隐控制,那你就out了.

CSS图形

- GLORY - 酷壳 - CoolShell.cn
下面的示例展示了使用纯CSS制作的各种图形,你可以自由地修改文中的CSS代码. 经测试,IE9, Chrome, FF, Safari都可以正常显示. 五角星形 via Kit MacAllister. 心形 via Nicolas Gallagher. 无穷大 via Nicolas Gallagher.

用 Compass 寫 CSS

- Jay - Blog.XDite.net
最近在開發一個新產品,整體來說應該是接近寫完了,不過越接近完工,抓 IE 系列的 bug 就越是挫折. 朋友 @evenwu 就來洗我要不要換成 Compass,說這東西超神奇,超好用,還可以把 IE bug 殺光光. 其實之前就久仰 Compass 大名了,只是文件實在看起來太他媽的眼花繚亂,因為專案進度一直在跑,不太敢貿然換掉寫 CSS 的方式.

CSS 入门

- - 博客 - 伯乐在线
级联样式表非常简单,也就是 (X)HTML 网页之上的分层设计. 使样式表 “级联”,这样您就可以跨站点应用它 — 也就是说,将样式应用到网站,它就会自行应用到每个网页的每个元素. ●XHTML:可扩展 HTML. 对于网站,将数据与设计分离是一个重要的概念:数据使用 (X)HTML 发送到 浏览器,而设计使用 CSS 应用到该数据.

css 圆角

- - CSDN博客推荐文章
作者:kangquan2008 发表于2012-2-20 22:32:24 原文链接. 阅读:6 评论:0 查看评论.

CSS架构

- - 博客 - 伯乐在线
英文原文: CSS Architecture,编译: CSDN-张红月. Philip Walton 在AppFolio担任前端工程师,他在Santa Barbara on Rails的聚会上提出了CSS架构和一些最佳实践,并且在工作中一直沿用. 擅长CSS的Web开发人员不仅可以从视觉上复制实物原型,还可以用代码进行完美的呈现.

CSS总结

- - CSDN博客Web前端推荐文章
         接触过一段CSS,为简单理解,将CSS说成两步,一步是你做个“记号”,另一步是根据记号设置样式.      网页的内容和样式是分开的. “记号”便是能标识网页中某部分内容的关键字词(选择器),而根据记号设置样式呢,就是按图索骥根据记号设置标识的那部分内容的样式.     这段时间练习的每个CSS小例子,或是用id做记号,或是用name,或是用class,只有有了这些所谓的记号,CSS设定的样式才有用,.

CSS基础

- - CSDN博客Web前端推荐文章
1、引入CSS的四种方式. 行内样式、内嵌样式、链接样式、导入样式. 基本选择器:标签选择器,ID选择器,类选择器,通用选择器. 通用选择器:*{css代码}. 通用选择器作用:对整个网页中所有HTML标签进行样式定义. 常见用法:定义*{margin:0;padding:0}通用样式,并置于CSS文件最顶端,用于对HTML内所有的标签进行重置以保证页面能兼容多种浏览器.

CSS命名规范

- - BlogJava-首页技术区
网上整理的比较好的css命名规则,为css代码的规范化做参考,增加代码的可读性. 容器: container 页头:header 内容:content/container. 页面主体:main 页尾:footer 导航:nav . 侧栏:sidebar 栏目:column 左右中:leftright center .