您现在的位置是:网站首页> 编程资料编程资料
转载:On having layout_CSS/HTML_
2023-05-25
244人已围观
简介 转载:On having layout_CSS/HTML_
文中所有的 layout 这个单词都未作翻译,一来本身这个单词意思就比较多,翻成啥都觉得别扭,二来它也是专有的属性,所以就意会一下吧。水平有限,很多地方都是模模糊糊地意译,发现错误欢迎留言指出。
引用一段来自Dean Edwards的评价:
I recommend that every CSS designer and DOM scripter read this. Understanding “layout” gives a huge insight into lots of other IE bugs and idiosyncrasies.
介绍
Internet Explorer 中有很多奇怪的渲染问题可以通过赋予其“layout”得到解决。John Gallant 和 Holly Bergevin 把这些问题归类为“尺寸bug(dimensional bugs)”,意思是这些 bug 可以通过赋予相应元素某个宽度或高度解决。这便引出关于“layout”的一个问题:为什么它会改变元素的渲染特性,为什么它会影响到元素之间的关系?这个问题问得很好,但却很难回答。在这篇文章中,我们专注于这个复杂问题会有那些方面的表现,某一方面的具体讨论和范例请参考文中给出的相关链接。
hasLayout — 定义
“Layout”是一个 IE/Win 的私有概念,它决定了一个元素如何显示以及约束其包含的内容、如何与其他元素交互和建立联系、如何响应和传递应用程序事件/用户事件等,这有点类似于一个窗体的概念。
微软的开发者们认为盒状元素(box-type elements)应该具有一个“属性(property)”(这是面向对象编程中的一个概念),于是他们便使用了 layout , 也就是 hasLayout。
hasLayout 其实既不是一个属性更不是一个行为,而是 IE 这个渲染引擎代代继承一贯拥有的一个渲染概念,在这个概念下渲染的元素将具有一种特性。
实际上这种渲染特性在有些 HTML 元素中与身俱来,而在另外一些元素中也可以通过一些 CSS 属性将其触发为 true ,且一旦触发将不可逆转。
术语
当我们说一个元素“拥有layout”或“得到layout”,或者说一个元素“has layout” 的时候,我们的意思是指它的微软专有属性 hasLayout 被设为了 true 。一个“layout元素”可以是一个默认就拥有 layout 的元素或者是一个通过设置某些 CSS 属性得到 layout 的元素。
而“无layout元素”,是指 hasLayout 未被触发的元素,比如一个未设定宽高尺寸的干净 div 元素就可以做为一个 “无layout祖先”。
给一个默认没有 layout 的元素赋予 layout 的方法包括设置可触发 hasLayout = true 的 CSS 属性。参考默认 layout 元素以及这些属性列表。没有办法设置 hasLayout = false , 除非把一开始那些触发 hasLayout = true 的 CSS 属性去除。
问题种种
hasLayout 的问题不管新手还是老手,不管设计师或者程序员可能都遇到过。具有 layout 的元素通常有着不同寻常而且难以预料的的显示效果,而且有时甚至会牵连到他们的孩子元素。
一个元素是否具有“layout”可能会引发如下的一些问题:
- IE 很多常见的浮动 bug 。
- 元素本身对一些基本属性的异常处理问题。
- 容器和其子孙之间的边距重叠(margin collapsing)问题。
- 使用列表时遇到的诸多问题。
- 背景图像的定位偏差问题。
- 使用脚本时遇到的浏览器之间处理不一致的问题。
上面的列表只是列出一个大概,也不完善。下面的文章将尽可能详细彻底的描述有无“layout”所带来的各种问题。
Layout 从何而来
不同于标准属性,也不像某些浏览器的私有 CSS 属性,layout 无法通过某一个 CSS 声明直接设定 。也就是说没有“layout属性”这么一个东西,元素要么本身自动拥有 layout,要么借助一些 CSS 声明悄悄地获得 layout。
默认layout元素
下列元素应该是默认具有 layout 的:
,,
, , ,属性
下列 CSS 属性和取值将会让一个元素获得 layout:
position: absolute- 绝对定位元素的包含区块(containing block)就会经常在这一方面出问题。
float: left|right- 由于 layout 元素的特性,浮动模型会有很多怪异的表现。
display: inline-block- 当一个内联级别的元素需要 layout 的时候往往就要用到它,这也可能也是这个 CSS 属性的唯一效果——让某个元素拥有 layout。“inline-block行为”在IE中是可以实现的,但是非常与众不同: IE/Win: inline-block and hasLayout 。
width: 任意值- 很多人遇到 layout 相关问题发生时,一般都会先尝试用这个来修复。
height: 任意值- height: 1% 就在 Holly Hack 中用到。
zoom: 任意值(MSDN)- MS专有属性,无法通过校验。 不过
zoom: 1可以临时用做调试。 writing-mode: tb-rl(MSDN)- MS专有属性,无法通过校验。
在 IE7 中,overflow 也变成了一个 layout 触发器:
overflow: hidden|scroll|auto- 这个属性在之前版本 IE 中没有触发 layout 的功能。
overflow-x|-y: hidden|scroll|auto- overflow-x 和 overflow-y 是 CSS3 盒模型中的属性,尚未得到浏览器的广泛支持。他们在之前版本IE中没有触发 layout 的功能。
另外 IE7 的荧幕上又新添了几个 haslayout 的演员,如果只从 hasLayout 这个方面考虑,min/max 和 width/height 的表现类似,position 的 fixed 和 absolute 也是一模一样。
position: fixed- ./.
min-width: 任意值- 就算设为0也可以让该元素获得 layout。
max-width: 除 none 之外的任意值- ./.
min-height: 任意值- 即使设为0也可以让该元素的 haslayout=true
max-height: 除 none 之外的任意值- ./.
以上结论借助 IE Developer Toobar 以及预先测试得出。
有关内联级别元素
对于内联元素(可以是默认即为内联的比如
span元素,也可以是display: inline的元素)width和height只在 IE5.x 下和 IE6 的 quirks 模式下触发hasLayout。因为在 IE6 中,如果浏览器运行于标准兼容模式下,内联元素会忽略 width 或 height 属性,所以设置 width 或 height 不能在此种情况下令该元素具有 layout。zoom总是可以触发hasLayout,但是在 IE5.0 中不支持。
具有“layout” 的元素如果同时也
display: inline,那么它的行为就和标准中所说的 inline-block 很类似了:在段落中和普通文字一样在水平方向和连续排列,受 vertical-align 影响,并且大小可以根据内容自适应调整。这也可以解释为什么单单在 IE/Win 中内联元素可以包含块级元素而少出问题,因为在别的浏览器中display: inline就是内联,不像 IE/Win 一旦内联元素拥有 layout 还会变成 inline-block。脚本属性 hasLayout
我们这里称 hasLayout 为“脚本属性”是为了和我们熟知的 CSS 属性相区别。
注意一旦一个元素拥有了 layout,就没有办法再将其设成
hasLayout = False了。hasLayout-property 可以用来检测一个元素是否拥有 layout:举个例子,如果它的
id是“eid”,那么只要在 IE5.5+ 的地址栏里输入javascript: alert(eid.currentStyle.hasLayout)即可检测它的状态。IE的 Developer Toolbar 可以实时检查一个元素的当前样式;如果
hasLayout是 true ,那么它的值显示为 “-1”。 我们可以通过实时修改一个元素的属性将“zoom(css)”设置为“1”来触发hasLayout以便调试。另外一个需要注意的是“layout”会影响脚本编程。如果一个元素没有“layout”,那么
clientWidth/clientHeight总是返回0。这会让一些脚本新手感到困惑,而且这和 Mozilla 浏览器的处理方式也不一样。不过我们可以利用这一点在 IE5.0 中检测“layout”:如果clientWidth是零那么这个元素就没有 layout。CSS hacks
下面用于触发
haslayout的 hack 已经经过 IE6 及以下版本测试。今后版本的IE有可能会对此做不同处理。如果新版本浏览器发布我们会重新整理这部分内容。John Gallant 和 Holly Bergevin 在2003年发布的 Holly hack :
/* \*/ * html .gainlayout { height: 1%; } /* */- 可以让 IE5+ 的任意元素获得 layout,除了标准兼容模式 IE6 中的内联元素。
- 一般都很有效,除了在某些极少情况下,需要用 height:0 或者 1px 更好一些。
- 和
overflow: hidden不相容,除非在 IE6 的标注兼容模式下(因为这时如果父元素没有定高,那么height: 1%会被变回height: auto)。
或者我们可以用 underscore hack:
.gainlayout { _height: 0; }另外,更具有向后兼容性的方法是使用 条件注释(conditional comments):
在条件注释中链接一个专门对 IE/Win 做修正的外部样式表文件,也不失为一个安全有效的好方法:
我们更倾向于使用
height: 0和1px—— 并主张始终使用height除非它和别的什么东西冲突 (overflow: hidden)。对于取值,我们则倾向于避免1%,因为它可能会(虽然很少)引起一些问题。一个需要注意的情况是如果我们希望一个元素保持内联,那么就不能使用
height了,这时可以用display: inline-block。我们只在早期调试阶段用zoom: 1来避免一些渲染错误。我们曾看过一些把 Holly hack 真的当作 holy(神圣的) hack 盲目使用的情况,比如对浮动元素使用或者对已经具有特定宽度的元素也使用这个 hack。要记住这个 hack 的目的不是要给某个元素加一个高度,而只是要触发
hasLayout = True而已。不要给所有元素设置 layout:
* {_height: 1px;}。所谓过犹不及,获得 layout 不等于获得灵丹妙药,它只是用来改变渲染模式。Hack整理
但是浏览器总是会变的,我们需要面对很多问题,比如一些依赖 IE6 的 bug 所做的 hack 会在 IE7 或更高版本的新浏览器中因 bug 修复而失效(甚至有害)的问题;比如新版本浏览器中类似的布局 bug 依然存在但用于 hack 的过滤器比如
* html却不能正常工作的问题。这种情况下,MS专有属性zoom就可以考虑使用了。zoom: 1;可以让 IE5.5+ 的任何元素(包括内联元素)获得 layout,但是在 IE5.0 中无效。- 没有其他附带效果(内联元素会变成 inline-block,这个当然)。
- 如果需要通过验证,应该用条件注释将
zoom隐藏起来。
其实当我们考虑到“向后兼容”时是很自相矛盾的,我们强烈建议页面设计者回过头看一下自己页面中用的到的明显的或是不明显的“hacks”,并用条件注释针对不同浏览器重新处理以保万无一失。
关于IE Mac 的小问题
IE Mac 和 windows 下的 IE 是完全不同的两个东西,它们各自拥有自己的渲染引擎,IE Mac 就全然不知“hasLayout”(或contenteditable)所谓何物。相比之下 IE Mac 的渲染引擎要更标准兼容一点,比如
height就是被当作height处理,没有别的效果。因此针对“hasLayout”的 hacks 和别的解决方法(特别是通过使用height或width属性的)往往对 IE Mac 来说是有害的,所以需要对其隐藏。更多的关于 IE Mac 相关的问题可以在 IE Mac, bugs and oddities pages 找到。MSDN 文档
MSDN 中涉及到 hasLayout 这个 MS 属性的地方寥寥无几,而具体解释 layout 和 IE 渲染模型之间关系的则少之又少。
在IE4的时候,除了未经绝对定位也未指定宽高的内
相关内容
点击排行
本栏推荐
