div仿框架方法详解

4月 23rd, 2009

[参与测试的浏览器:IE6 / IE7 / IE8 / FF3 / OP9.6 / SF3 / Chrome2 ]
[操作系统:Windows]

问这样的问题的人很多,我对此有比较深入的研究,但自己从来没有给出过完整的解答与分析,觉得有些对不住样式界的列祖列宗。

先请看demo:

提示:你可以先修改部分代码再运行。

通过css的结构大家应该不难看出,这里采用了ie6最基本的hack来区分ie6与其他浏览器来实现这个效果。

那么本教程也将分而述之。

撇开ie6,我们看这个demo:

提示:你可以先修改部分代码再运行。

大家看到,此时div的实际高宽,完全由left / right / top / bottom这四个属性所掌控着,于是我们便可以借助这个特性,轻松地完成div仿框架的效果了:

提示:你可以先修改部分代码再运行。

让我们将应该有滚动条的地方的滚动条效果折腾出来:

提示:你可以先修改部分代码再运行。

以上方法其实早已由wiseinfo在Html+CSS 构建 B/S结构软件界面 — 布局篇 — position方式中进行过介绍,在该文中,ie6亦是分而治之的,它的方法是在html代码顶部加入“<?xml version=”1.0″ encoding=”UTF-8″?>”,使得ie6进入quirks mode(怪异模式)来完成ie6下的div仿框架,但这样做将出现一些影响比较显著的弊端:

1. quirks mode下的ie6连盒模型都变了,就是说你在页面中写任何内容就要慎用padding和border,况且quirks mode下的变化还不止这一点。
2. 如果底部使用绝对定位,则会发生“绝对定位基对象(在此为body)高度为偶数时,出现1px空隙”的bug。

提示:你可以先修改部分代码再运行。

于是我们需要另辟蹊径。

在很多次失败之后,我终于发现有一个标签可以救ie6于水深火热,那就是最伟大的“<html>”标签,它继承了ie6 quirks mode(怪异模式)下的盒模型状态。

提示:你可以先修改部分代码再运行。

利用这一点,我们可以在不太轻松的调整之后完成以下效果:

提示:你可以先修改部分代码再运行。

再用下我们的二列布局知识来完成最终形态,在此我们将艳遇著名的3px bug:

提示:你可以先修改部分代码再运行。

现在我们拥有了ie6的仿框架和非ie6的div仿框架的最终形态,只需要利用hack做个简单的加法则行了:
(当然,同一属性写两遍,后面的属性所对应的值将覆盖前者,这个基础的优先级基础大家还需要温故一下。)
(再“当然”一下——当然,有人对hack深恶痛绝,那么请在使用之前,阅读此文看看是否能消消心头之恨。)

提示:你可以先修改部分代码再运行。

它很强大而实用,真的:

提示:你可以先修改部分代码再运行。


以下是09-05-09的补充

但在实际应用中主体部分常常是个iframe,加个iframe,IE7则无法适应。T_T

提示:你可以先修改部分代码再运行。

而且……其实IE7下还不止这一点bug(虽然可以直接overflow-y:scroll,但我于心不忍)。

提示:你可以先修改部分代码再运行。

所幸IE7和IE6的html标签有着相同的盒模型,所以可以直接将IE6 only的部分修改为IE6+IE7 only。

提示:你可以先修改部分代码再运行。

iframe无法适应高度的bug也一起被修复了,人生真美好。

提示:你可以先修改部分代码再运行。

续集完,谢谢观赏。


以下是09-05-24的补充,在KentXD的细心测试下,该方案在ie6下又出现了惊喜:

当bottom部分存在文字的时候,从bottom部分跨越至main部分一直选定,当选定状态仍保持的时候,最大化 / 还原窗口,页面整体向上移动了n个像素,貌似*padding:70px 0;失去了作用。

提示:你可以先修改部分代码再运行。

^-^ 好在改变position的属性为absolute之后,该bug顺利修复:

提示:你可以先修改部分代码再运行。

又一篇续集结束,谢谢Kent

Chomo xhtml+css , ,

hack该不该用?!

4月 21st, 2009

这是一个极具争议的话题,此帖仅代表个人观点,希望能借此抛砖引玉,大家能谈谈各自的想法,予老鸟以谈资,予新手以借鉴。

hack是什么呢,它是用来针对浏览器在css解释上出现异常现象时,为了兼容各浏览器所使用的一种非常手段。

个人认为

一、应尽量避免hack的使用

  很多人都存在一种投机取巧的观点——不兼容,用hack。因为这样省时省力。但这样下去,你永远都无法知道为什么这个浏览器比那个浏览器多出10个像素了,越来越多的不知道将导致你对css的迷惑。你将越来越依赖hack。

  其实浏览器都已经很接近标准了,比如很多时候IE中的一些问题,都是由于hasLayout属性产生的,触发hasLayout便能顺利解决问题。又比如双倍距bug,加上display:inline就能解决问题了,并不需要用到hack来取掉那一倍的宽度。

  投机取巧、为了省时省力而使用hack,将使csser对css、对浏览器特性(或者说是漏洞)的理解停滞不前!故,请应尽量避免hack的使用。

二、不要畏惧hack的使用

  经常见到有人高声呼吁:千万不要使用hack,要做无hack安全绿色界面。

  我认为,这种过分极端的观点是错误的,这是一个误区。hack以及私有属性之所以被人挖掘并为高手所研究,正是因为它有其不可替代的价值。

  在一些特殊的情况下,不使用hack根本没有办法解决问题,比如要一个按钮上的文字在各主流浏览器中完美地垂直居中,如果没有hack,你能做到吗?比如css仿框架,不使用hack,你能做到吗?当然,你会说你不需要做到那么极致,但亲爱的,老板要。但亲爱的,你能做到更好,为什么不呢?

  你说不要用它,那就是因为它有弊端了,忌用hack的人有何顾虑呢?目前我所听到的声音都属于以下三种:

  1. 向后兼容问题(就是说你的页面ie8兼容了,在ie9下搞不好因为你使用的hack而错乱)

  不可否认,类似的悲剧确实存在。ie6向ie7过度的时代,important声明大概害惨了一批人,ie7继承了ie6的很多bug,但却完全支持了用于ie6 hack的important声明,于是用important根本无法区分ie7和ff2。

  但——但——但——在你使用hack的时候去预测一下是否再出现这样的情况,便可知hack用不用得了。简单例举一下:ie6有3px bug,我用“_margin-right:-3px”来解决,这个下划线+属性的写法仅ie6支持,ie7不支持,其他任何浏览器都不支持。按照标准的发展趋势来看,今后会有浏览器支持吗?今后会还浏览器出现这么极品这么囧的3px bug吗?这样的hack,不过是以ie6本身来制ie6本身,并不会对其他浏览器及其之后的浏览器造成影响。

  2. 如我之前所陈,使用hack可能致使csser依赖hack。

  这样的问题其实完全事在人为,不依赖hack很简单,我不去依赖就行了——尽、量、避、免、使、用、hack!

  3. 无法通过标准验证。

  乖乖,标准验证是为了什么呢?是为了让你所写的样式更加符合标准,你知道如何去标准就行了,浏览器并不标准的时候,我们还要钻破脑袋了去按照标准的方法做事。别傻了孩子,你会把制定标准的人活活气死的。

Chomo xhtml+css ,

图标组中鼠标经过图标显示详细信息

4月 17th, 2009

[参与测试的浏览器:IE6 / IE7 / IE8 / FF3 / OP9.6 / SF3 / Chrome2 ]
[操作系统:Windows]

一个电影图标(我觉得叫“海报缩图”不动听),鼠标滑过时显示它的名称和简介,这样的效果做起来很容易,稍稍利用:hover伪类便可实现。

提示:你可以先修改部分代码再运行。

然而这样的图标通常是成组出现的,于是就出现了一个问题:当鼠标滑过时,显示出来的详细信息将遮住其他的图标,从而使得“:hover”无法顺利触发。

提示:你可以先修改部分代码再运行。

要解决这个问题,关键在于如何使得现在被遮住的这个<a>也能触发:hover。
=> 被遮住的<a>能触发:hover吗?不能!
=> 那么现在问题转化为:如何使得现在被遮住的这个<a>不被遮住。
=> 事实上:<a>的一个子元素不被遮住即可。
=> 加一个透明的子元素便能实现了。

思路图(3D的也,透视的也,我真牛 ^-^):

提示:你可以先修改部分代码再运行。

(编者按:炫不炫?好炫!——鼓掌。)

这是一个比较复杂的效果,在兼容性上还是存在一些问题,所以需要作情处理,其细节请参见demo中样式表的注释。
该效果的产生离不开对“层的叠加”的理解,如对此有疑问,请参阅我的相关文章:理解五条叠加法则,自由使用层的叠加

Chomo xhtml+css , ,

理解五条叠加法则,自由使用层的叠加

4月 16th, 2009

[参与测试的浏览器:IE6 / IE7 / IE8 / FF3 / OP9.6 / SF3 / Chrome2 ]
[操作系统:Windows]

貌似很多同学对为什么这个div在上层,那个div在下层、无论如何设置z-index都无法居上的问题纠结抓狂、上吐下泻、恶心失眠、郁郁而终,致使不敢随意使用层的叠加。
但层的叠加效果,在交互设计中却频频出现,所以我们必须驾驭它,要驾驭它,就要掌握其规律。

首先明确几点在文中所需要用到的概念:

  1. 静态定位:position:static(为position属性的默认值)。
  2. 动态定位:position:relative或position:absolute或position:fixed。
  3. 祖元素:任意包含该元素的元素。
  4. 父元素:直接包含该元素的祖元素。
  5. 同辈元素:拥有共同的父元素的元素。

【注】这些概念为作者自定义,仅用于本文。

关于同辈元素是个非常关键的词,这里还需要详细解释一下。

  1. <div>
  2.       <div></div>
  3.       <div id="a"></div>
  4.       <div></div>
  5.       <div></div>
  6.       <div></div>
  7.       <div></div>
  8. </div>
  9. <div id="f">
  10.       <div></div>
  11.       <div id="b"></div>
  12.       <div id="c"></div>
  13.       <div></div>
  14.       <div></div>
  15.       <div></div>
  16. </div>

在这个例子中,div#a与div#b并不是“同辈元素”,只有像div#b和div#c这样拥有同样父体div#f的的元素才能叫“同辈元素”。

接下来看看这五条法则:

法则一:同辈元素定位方式相同,且无z-index设置时,html靠后者居上。

提示:你可以先修改部分代码再运行。

法则二:同辈元素同为动态定位时,且有z-index设置时,z-index值大者居上。

提示:你可以先修改部分代码再运行。

法则三:同辈元素定位方式不同时,动态定位居上。

提示:你可以先修改部分代码再运行。

法则四:非同辈元素,任意一者及其祖元素不具备动态布局时,html靠后者居上。

提示:你可以先修改部分代码再运行。

法则五:【重要】:非同辈元素,任意一者或其祖元素拥有动态定位时,各自向上寻找动态定位的祖元素至它们共有的祖元素的下一级为止,并分别从中拿出具备最高级别的祖元素(或其本身)进行比较。

情况1:子元素的z-index无论多大,父元素大者居上。

情况2:父元素居下,子元素也可以居上。

情况1、情况2结合扩展比较。

提示:你可以先修改部分代码再运行。

其实前四点都是基础,只有第五点比较难于理解,这里详细解释一下:

  1. <div id="ab" style="position:absolute;">
  2.       <div id="a" style="position:relative; z-index:100;">
  3.             <div id="a_inner1">
  4.                   <div id="a_inner2">
  5.                         <div id="a_inner3" style="position:relative; z-index:98;">
  6.                               <div id="a_inner4">
  7.                                     <div id="a_inner5">
  8.                                     </div>
  9.                               </div>
  10.                         </div>
  11.                   </div>
  12.             </div>
  13.       </div>
  14.       <div id="b">
  15.             <div id="b_inner1">
  16.                   <div id="b_inner2">
  17.                         <div id="b_inner3" style="position:relative; z-index:99;">
  18.                               <div id="b_inner4">
  19.                               </div>
  20.                         </div>
  21.                   </div>
  22.             </div>
  23.       </div>
  24. </div>

在这个例子中,我们来比较div#a_inner5和div#b_inner4的层叠关系。
到它们所共同拥有的祖元素div#ab的下一级为止,div#a_inner5的祖元素包括:div#a,div#a_inner1,div#a_inner2,div#a_inner3,div#a_inner4;div#b_inner4的祖元素包括:div#b,div#b_inner1,div#b_inner2,div#b_inner3。
然后分析它们的祖元素中具有动态定位的:div#a_inner5的祖元素中含有动态定位的元素有:div#a,div#a_inner3;div#b_inner4的祖元素中含有动态定位的元素有:div#b_inner3。
然后再拿出最高级进行比较:div#a > #div#b_inner3。

父元素居下,子元素也可以居上的情况,则是利用非同辈元素在祖元素具备动态布局时,其比较已经与position:static无关,而其祖元素却可以通过html的位置来进行比较。

当然,有时候还存在特例,比如flash、比如ie6中的select无法遮住,这些都属于异常情况,大家可以自己搜索一下相关文章(最好到我滴博客搜,顺便点击哈广告什么的)。

Chomo xhtml+css , ,

小字体小行高兼容性分析及差异解决办法

4月 8th, 2009

[参与测试的浏览器:IE6 / IE7 / IE8 / FF3 / OP9.6 / SF3 / Chrome2 ]
[操作系统:Windows]

浏览器们缺乏党的教育,对行高没有统一的认识,于是在小字体小行高的情况下,总出现肉眼可见差异,对美观产生了举足轻重的影响。

要解决这一细节性的问题,我们首先得进行一番测试来了解各浏览器对于行高的认识,由于仅小行高和小字体影响比较大,我们就不探究其细节规律(比如字体大小对变化速度的影响规律)了,能在一定程度上解决问题便达到了我们想要的效果。

以下是经过一番头晕眼花的测试后得出的实验数据:

大小 行高 浏览器 宋体 Arial纯中文 Arial带英文字符
上边距 下边距 上边距 下边距 上边距 下边距
12px 14px ie6 0px 3px 0px 3px 1px 2px
12px 14px ie7 1px 2px 0px 3px 1px 2px
12px 14px ie8 1px 2px 0px 3px 1px 2px
12px 14px ff3 1px 2px 2px 1px 2px 1px
12px 14px chrome2 1px 2px 2px 1px 2px 1px
12px 14px op9.6 1px 2px 1px 2px 1px 2px
12px 14px sf3 1px 2px 1px 2px 1px 2px
12px 15px ie6 1px 3px 1px 3px 1px 3px
12px 15px ie7 2px 2px 1px 3px 1px 3px
12px 15px ie8 1px 3px 0px 4px 1px 3px
12px 15px ff3 1px 3px 2px 2px 2px 2px
12px 15px chrome2 1px 3px 2px 2px 2px 2px
12px 15px op9.6 1px 3px 1px 3px 1px 3px
12px 15px sf3 1px 3px 1px 3px 1px 3px
12px 16px ie6 1px 4px 1px 4px 2px 3px
12px 16px ie7 2px 3px 1px 4px 2px 3px
12px 16px ie8 2px 3px 1px 4px 2px 3px
12px 16px ff3 2px 3px 3px 2px 3px 2px
12px 16px chrome2 2px 3px 2px 3px 2px 3px
12px 16px op9.6 2px 3px 2px 3px 2px 3px
12px 16px sf3 2px 3px 2px 3px 2px 3px
12px 17px ie6 2px 4px 2px 4px 3px 3px
12px 17px ie7 3px 3px 2px 4px 3px 3px
12px 17px ie8 2px 4px 1px 5px 2px 4px
12px 17px ff3 2px 4px 3px 3px 3px 3px
12px 17px chrome2 2px 4px 3px 3px 3px 3px
12px 17px op9.6 2px 4px 2px 4px 2px 4px
12px 17px sf3 2px 4px 2px 4px 2px 4px

由表可见

1. 需要外观上非常完美的呈现单行文本垂直居中(没有1px的差异),需要设置字体为宋体。

解释:当字体为宋体的时候,各浏览器中上边距和下边距的差异都是较小的,出现问题的仅仅是IE6(行高为偶数时)与IE7(行高为奇数时),而IE6和IE7是可以很容易使用hack来通过padding的多少来精确控制其位置。

示例:

提示:你可以先修改部分代码再运行。

2. 如果确定标签内存在英文字符、数字、符号,可以设置英文字体,利用行高在15px下呈现的状态。

解释:此时仅ff3和chrome2浏览器存在些许差异,并且外观上不存在上多下少的边距。

示例:

提示:你可以先修改部分代码再运行。

3. 如果不能保证是否存在英文字符、数字、符号,又需要设置英文字体保证美观,也可利用行高在15px下呈现的状态。(推荐)

解释:此时ie8浏览器下的状态不容乐观,上下差异太大:上0px,下4px,但可以利用:before伪类,赐它一个符号。

示例:

提示:你可以先修改部分代码再运行。

Chomo xhtml+css , ,

按钮兼容性解决方案

4月 4th, 2009

[参与测试的浏览器:IE6 / IE7 / IE8 / FF3 / OP9.6 / SF3 / Chrome2 ]
[操作系统:Windows]

我想,如果css界也有猪坚强的话,那一定非各位表单元素莫属,不仅仅是IE浏览器,Firefox、Safari等都将给我们造成一系列的麻烦。

按钮的问题非常多,我们很难一一都进行解决,所以相对较好的办法,就是保证其在浏览器中高度、宽度上不会有太大差异,文字在按钮中显示基本正常就可以了:

提示:你可以先修改部分代码再运行。

当然,很多情况下,我们需要有更多的考虑,这时,我们便需要借助hack来完善:

提示:你可以先修改部分代码再运行。

PS.该方法在IE8中文字偏上的问题暂未解决,IE8对中文的支持实在让人失望。

【附注】目前已知的按钮存在的主要问题:

  1. IE6/IE7中:根据内容的多少将自动产生一定程度类似padding-left与padding-right的值。
  2. IE6/IE7中:会在紧贴边框的位置产生1px的与背景相同的内边框。
  3. IE6/IE7/IE8中:默认情况下会在其本身上下产生莫名其妙的外边距(类似margin)。
  4. IE6/IE7/IE8/FF3中:文字在按钮中的垂直位置混乱。
  5. IE8中:如果设置某些英文字体(如Arial),纯中文按钮与非纯中文按钮在垂直方向上便不再自动对齐。
  6. IE6中:按钮中的文字将受到vertical-align属性的影响。
  7. IE7中:字符集如果是gb系列(如gb2312),同时vertical-align:middle,则会产生莫名其妙的外边距(类似margin)。

[2009-04-14 已修复IE8中文字偏上的错误,方法请参见小字体小行高兼容性分析及差异解决办法]

提示:你可以先修改部分代码再运行。

Chomo xhtml+css , ,

firefox3.0的表格边框叠加Bug及其解决方案

4月 3rd, 2009

[参与测试的浏览器:IE6 / IE7 / IE8 / FF3 / OP9.6 / SF3 / Chrome2 ]
[操作系统:Windows]

先看看bug(请使用firefox3.0):

提示:你可以先修改部分代码再运行。

描述:为了更清晰地看出table边框情况,我们给body以margin:1px,而在firefox3.0中,table却并未显示1px的上边距和1px的左边距。

危害:这微不足道的1px,足以影响到该table盒模型的实际宽度,继而可能在某些部分导致页面错位。

解决方法:td和th的边框仅设置右侧方向和底部方向,用div来模拟缺失掉的边框。

提示:你可以先修改部分代码再运行。

Chomo xhtml+css , ,