omiga

简单就好

iframe高度自适应

1条评论»

如何让iframe自适应其内嵌的页面高度,即不出现纵向滚动条?当然是首先获取iframe内嵌文档自身的高度,再赋值给iframe。

获取iframe内嵌文档,有如下方法:

IE:

document.getElementById("myIframe").document;

FF:

document.getElementById("myIframe").contentWindow.document;

IE亦可写成FF的方法~···

PS:搞个页面,这两天就只弄这么个东西~···一个表格页面里面还嵌套了N层框架~····FF还报一大堆错,根本无法用Firebug调试,i sun~···搞死人~···一直想从顶层页面获取到其下层页面高度,但是始终获取不到正确值。最后在最底层页面获取其自身高度再传递到顶层页面~···over~···

Photoshop CS3快捷键

发表评论»

有时间看两个~大大有益~···

矩形、椭圆工具[M]
裁剪工具 [C]
移动工具 [V]
套索、多边形套索、磁性套索 [L]
魔棒工具 [W]
喷枪工具 [J]
画笔工具 [B]
像皮图章、图案图章 [S]
历史记录画笔工具 [Y]
像皮擦工具 [E]
铅笔、直线工具 [N]
模糊、锐化、涂抹工具 [R]
减淡、加深、海棉工具 [O]
钢笔、自由钢笔、磁性钢笔 [P]
添加锚点工具 [+]
删除锚点工具 [-]
直接选取工具 [A]
文字、文字蒙板、直排文字、直排文字蒙板 [T]
度量工具 [U]
直线渐变、径向渐变、对称渐变、角度渐变、菱形渐变 [G]
油漆桶工具 [K]
吸管、颜色取样器 [I]
抓手工具 [H]
缩放工具 [Z]
默认前景色和背景色 [D]
切换前景色和背景色 [X]
切换标准模式和快速蒙板模式 [Q]
标准屏幕模式、带有菜单栏的全屏模式、全屏模式 [F]
临时使用移动工具 [Ctrl]
临时使用吸色工具 [Alt]
临时使用抓手工具 [空格]
打开工具选项面板 [Enter]
快速输入工具选项(当前工具选项面板中至少有一个可调节数字) [0]至[9]
循环选择画笔 <]或[>
选择第一个画笔 [Shift]+<]
选择最后一个画笔 [Shift]+[>
建立新渐变(在”渐变编辑器”中) [Ctrl]+[N]

新建图形文件 [Ctrl]+[N]
用默认设置创建新文件 [Ctrl]+[Alt]+[N]
打开已有的图像 [Ctrl]+[O]
打开为… [Ctrl]+[Alt]+[O]
关闭当前图像 [Ctrl]+[W]
保存当前图像 [Ctrl]+[S]
另存为… [Ctrl]+[Shift]+[S]
存储副本 [Ctrl]+[Alt]+[S]
页面设置 [Ctrl]+[Shift]+[P]
打印 [Ctrl]+[P]
打开“预置”对话框 [Ctrl]+[K]
显示最后一次显示的“预置”对话框 [Alt]+[Ctrl]+[K]
设置“常规”选项(在预置对话框中) [Ctrl]+[1]
设置“存储文件”(在预置对话框中) [Ctrl]+[2]
设置“显示和光标”(在预置对话框中) [Ctrl]+[3]
设置“透明区域与色域”(在预置对话框中) [Ctrl]+[4]
设置“单位与标尺”(在预置对话框中) [Ctrl]+[5]
设置“参考线与网格”(在预置对话框中) [Ctrl]+[6]
设置“增效工具与暂存盘”(在预置对话框中) [Ctrl]+[7]
设置“内存与图像高速缓存”(在预置对话框中) [Ctrl]+[8]

还原/重做前一步*作 [Ctrl]+[Z]
还原两步以上*作 [Ctrl]+[Alt]+[Z]
重做两步以上*作 [Ctrl]+[Shift]+[Z]
剪切选取的图像或路径 [Ctrl]+[X]或[F2]
拷贝选取的图像或路径 [Ctrl]+[C]
合并拷贝 [Ctrl]+[Shift]+[C]
将剪贴板的内容粘到当前图形中 [Ctrl]+[V]或[F4]
将剪贴板的内容粘到裖蛑?[Ctrl]+[Shift]+[V]
自由变换 [Ctrl]+[T]
应用自由变换(在自由变换模式下) [Enter]
从中心或对称点开始变换 (在自由变换模式下) [Alt]
限制(在自由变换模式下) [Shift]
扭曲(在自由变换模式下) [Ctrl]
取消变形(在自由变换模式下) [Esc]
自由变换复制的象素数据 [Ctrl]+[Shift]+[T]
再次变换复制的象素数据并建立一个副本 [Ctrl]+[Shift]+[Alt]+[T]
删除裖蛑械耐及富蜓∪〉穆肪?[DEL]
用背景色填充所选区域或整个图层 [Ctrl]+[BackSpace]或[Ctrl]+[Del]
用前景色填充所选区域或整个图层 [Alt]+[BackSpace]或[Alt]+[Del]
弹出“填充”对话框 [Shift]+[BackSpace]
从历史记录中填充 [Alt]+[Ctrl]+[Backspace]

调整色阶 [Ctrl]+[L]
自动调整色阶 [Ctrl]+[Shift]+[L]
打开曲线调整对话框 [Ctrl]+[M]
在所选通道的曲线上添加新的点(‘曲线’对话框中) 在图象中[Ctrl]加点按
在复合曲线以外的所有曲线上添加新的点(‘曲线’对话框中) [Ctrl]+[Shift]
移动所选点(‘曲线’对话框中) [↑]/[↓]/[←]/[→]
以10点为增幅移动所选点以10点为增幅(‘曲线’对话框中) [Shift]+[箭头]
选择多个控制点(‘曲线’对话框中) [Shift]加点按
前移控制点(‘曲线’对话框中) [Ctrl]+[Tab]
后移控制点(‘曲线’对话框中) [Ctrl]+[Shift]+[Tab]
添加新的点(‘曲线’对话框中) 点按网格
删除点(‘曲线’对话框中) [Ctrl]加点按点
取消选择所选通道上的所有点(‘曲线’对话框中) [Ctrl]+[D]
使曲线网格更精细或更粗糙(‘曲线’对话框中) [Alt]加点按网格
选择彩色通道(‘曲线’对话框中) [Ctrl]+[~]
选择单色通道(‘曲线’对话框中) [Ctrl]+[数字]
打开“色彩平衡”对话框 [Ctrl]+[B]
打开“色相/饱和度”对话框 [Ctrl]+[U]
全图调整(在色相/饱和度”对话框中) [Ctrl]+[~]
只调整红色(在色相/饱和度”对话框中) [Ctrl]+[1]
只调整黄色(在色相/饱和度”对话框中) [Ctrl]+[2]
只调整绿色(在色相/饱和度”对话框中) [Ctrl]+[3]
只调整青色(在色相/饱和度”对话框中) [Ctrl]+[4]
只调整蓝色(在色相/饱和度”对话框中) [Ctrl]+[5]
只调整洋红(在色相/饱和度”对话框中) [Ctrl]+[6]
去色 [Ctrl]+[Shift]+[U]
反相 [Ctrl]+[I]
从对话框新建一个图层 [Ctrl]+[Shift]+[N]
以默认选项建立一个新的图层 [Ctrl]+[Alt]+[Shift]+[N]
通过拷贝建立一个图层 [Ctrl]+[J]
通过剪切建立一个图层 [Ctrl]+[Shift]+[J]
与前一图层编组 [Ctrl]+[G]
取消编组 [Ctrl]+[Shift]+[G]
向下合并或合并联接图层 [Ctrl]+[E]
合并可见图层 [Ctrl]+[Shift]+[E]
盖印或盖印联接图层 [Ctrl]+[Alt]+[E]
将当前层下移一层 [Ctrl]+<]
将当前层上移一层 [Ctrl]+[>
将当前层移到最下面 [Ctrl]+[Shift]+<]
将当前层移到最上面 [Ctrl]+[Shift]+[>

激活下一个图层 [Alt]+<]
激活上一个图层 [Alt]+[>
激活底部图层 [Shift]+[Alt]+<]
激活顶部图层 [Shift]+[Alt]+[>
调整当前图层的透明度(当前工具为无数字参数的,如移动工具) [0]至[9]
保留当前图层的透明区域(开关) [/]
投影效果(在”效果”对话框中) [Ctrl]+[1]
内阴影效果(在”效果”对话框中) [Ctrl]+[2]
外发光效果(在”效果”对话框中) [Ctrl]+[3]
内发光效果(在”效果”对话框中) [Ctrl]+[4]
斜面和浮雕效果(在”效果”对话框中) [Ctrl]+[5]
应用当前所选效果并使参数可调(在”效果”对话框中) [A]
图层混合模式
循环选择混合模式 [Alt]+[-]或[+]
正常 [Ctrl]+[Alt]+[N]
阈值(位图模式) [Ctrl]+[Alt]+[L]
溶解 [Ctrl]+[Alt]+[I]
背后 [Ctrl]+[Alt]+[Q]
清除 [Ctrl]+[Alt]+[R]
正片叠底 [Ctrl]+[Alt]+[M]
屏幕 [Ctrl]+[Alt]+[S]
叠加 [Ctrl]+[Alt]+[O]
柔光 [Ctrl]+[Alt]+[F]
强光 [Ctrl]+[Alt]+[H]
颜色减淡 [Ctrl]+[Alt]+[D]
颜色加深 [Ctrl]+[Alt]+[B]
变暗 [Ctrl]+[Alt]+[K]
变亮 [Ctrl]+[Alt]+[G]
差值 [Ctrl]+[Alt]+[E]
排除 [Ctrl]+[Alt]+[X]
色相 [Ctrl]+[Alt]+[U]
饱和度 [Ctrl]+[Alt]+[T]
颜色 [Ctrl]+[Alt]+[C]
光度 [Ctrl]+[Alt]+[Y]
去色 海棉工具+[Ctrl]+[Alt]+[J]
加色 海棉工具+[Ctrl]+[Alt]+[A]
暗调 减淡/加深工具+[Ctrl]+[Alt]+[W]
中间调 减淡/加深工具+[Ctrl]+[Alt]+[V]
高光 减淡/加深工具+[Ctrl]+[Alt]+[Z]
全部选取 [Ctrl]+[A]
取消选择 [Ctrl]+[D]
重新选择 [Ctrl]+[Shift]+[D]
羽化选择 [Ctrl]+[Alt]+[D]
反向选择 [Ctrl]+[Shift]+[I]

路径变选区 数字键盘的[Enter]
载入选区 [Ctrl]+点按图层、路径、通道面板中的缩约图
按上次的参数再做一次上次的滤镜 [Ctrl]+[F]
退去上次所做滤镜的效果 [Ctrl]+[Shift]+[F]
重复上次所做的滤镜(可调参数) [Ctrl]+[Alt]+[F]
选择工具(在“3D变化”滤镜中) [V]
立方体工具(在“3D变化”滤镜中) [M]
球体工具(在“3D变化”滤镜中) [N]
柱体工具(在“3D变化”滤镜中) [C]
轨迹球(在“3D变化”滤镜中) [R]
全景相机工具(在“3D变化”滤镜中) [E]
显示彩色通道 [Ctrl]+[~]
显示单色通道 [Ctrl]+[数字]
显示复合通道 [~]
以CMYK方式预览(开关) [Ctrl]+[Y]
打开/关闭色域警告 [Ctrl]+[Shift]+[Y]
放大视图 [Ctrl]+[+]
缩小视图 [Ctrl]+[-]
满画布显示 [Ctrl]+[0]
实际象素显示 [Ctrl]+[Alt]+[0]
向上卷动一屏 [PageUp]
向下卷动一屏 [PageDown]
向左卷动一屏 [Ctrl]+[PageUp]
向右卷动一屏 [Ctrl]+[PageDown]
向上卷动10 个单位 [Shift]+[PageUp]
向下卷动10 个单位 [Shift]+[PageDown]
向左卷动10 个单位 [Shift]+[Ctrl]+[PageUp]
向右卷动10 个单位 [Shift]+[Ctrl]+[PageDown]
将视图移到左上角 [Home]
将视图移到右下角 [End]
显示/隐藏选择区域 [Ctrl]+[H]
显示/隐藏路径 [Ctrl]+[Shift]+[H]
显示/隐藏标尺 [Ctrl]+[R]
显示/隐藏参考线 [Ctrl]+[;]
显示/隐藏网格 [Ctrl]+[”]
贴紧参考线 [Ctrl]+[Shift]+[;]
锁定参考线 [Ctrl]+[Alt]+[;]
贴紧网格 [Ctrl]+[Shift]+[”]

显示/隐藏“画笔”面板 [F5]
显示/隐藏“颜色”面板 [F6]
显示/隐藏“图层”面板 [F7]
显示/隐藏“信息”面板 [F8]
显示/隐藏“动作”面板 [F9]
显示/隐藏所有命令面板 [TAB]
显示或隐藏工具箱以外的所有调板 [Shift]+[TAB]

文字处理(在”文字工具”对话框中)
左对齐或顶对齐 [Ctrl]+[Shift]+[L]
中对齐 [Ctrl]+[Shift]+[C]
右对齐或底对齐 [Ctrl]+[Shift]+[R]
左/右选择 1 个字符 [Shift]+[←]/[→]
下/上选择 1 行 [Shift]+[↑]/[↓]
选择所有字符 [Ctrl]+[A]
选择从插入点到鼠标点按点的字符 [Shift]加点按
左/右移动 1 个字符 [←]/[→]
下/上移动 1 行 [↑]/[↓]
左/右移动1个字 [Ctrl]+[←]/[→]
将所选文本的文字大小减小2 点象素 [Ctrl]+[Shift]+[<]
将所选文本的文字大小增大2 点象素 [Ctrl]+[Shift]+[>]
将所选文本的文字大小减小10 点象素 [Ctrl]+[Alt]+[Shift]+[<]
将所选文本的文字大小增大10 点象素 [Ctrl]+[Alt]+[Shift]+[>]
将行距减小2点象素 [Alt]+[↓]
将行距增大2点象素 [Alt]+[↑]
将基线位移减小2点象素 [Shift]+[Alt]+[↓]
将基线位移增加2点象素 [Shift]+[Alt]+[↑]
将字距微调或字距调整减小20/1000ems [Alt]+[←]
将字距微调或字距调整增加20/1000ems [Alt]+[→]
将字距微调或字距调整减小100/1000ems [Ctrl]+[Alt]+[←]
将字距微调或字距调整增加100/1000ems [Ctrl]+[Alt]+[→] 键

On having layout

2条评论»

介绍

Internet Explorer 中有很多奇怪的渲染问题可以通过赋予其“layout”得到解决。John Gallant 和 Holly Bergevin 把这些问题归类为“尺寸bug(dimensional bugs)”,意思是这些 bug 可以通过赋予相应元素某个宽度或高度解决。这便引出关于“layout”的一个问题:为什么它会改变元素的渲染特性,为什么它会影响到元素之间的关系?这 个问题问得很好,但却很难回答。在这篇文章中,我们专注于这个复杂问题会有那些方面的表现,某一方面的具体讨论和范例请参考文中给出的相关链接。

hasLayout — 定义

“Layout”是一个 IE/Win 的私有概念,它决定了一个元素如何显示以及约束其包含的内容、如何与其他元素交互和建立联系、如何响应和传递应用程序事件/用户事件等。

这种渲染特性可以通过某些 CSS 属性被不可逆转地触发。而有些 HTML 元素则默认就具有“layout”。

微软的开发者们认为元素都应该可以拥有一个“属性(property)”(这是面向对象编程中的一个概念),于是他们便使用了 hasLayout,这种渲染特性生效时也就是将 hasLayout 设成了 true 之时。

术语

当我们说一个元素“得到 layout”,或者说一个元素“拥有 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 的:

  • <html>, <body>
  • <table>, <tr>, <th>, <td>
  • <img>
  • <hr>
  • <input>, <button>, <select>, <textarea>, <fieldset>, <legend>
  • <iframe>, <embed>, <object>, <applet>
  • <marquee>

属性

下列 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: 除 “auto” 外的任意值
很多人遇到 layout 相关问题发生时,一般都会先尝试用这个来修复。
height: 除 “auto” 外的任意值
height: 1% 就在 Holly Hack 中用到。
zoom: 除 “normal” 外的任意值 (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 的元素)

  • widthheight 只在 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,如果没有其他属性再添加 hasLayout 的话:

  • width, height (设为 “auto”)
  • max-width, max-height (设为 “none”)(在 IE 7 中)
  • position (设为 “static”)
  • float (设为 “none”)
  • overflow (设为 “visible”) (在 IE 7 中)
  • zoom (设为 “normal”)
  • writing-mode (从 “tb-rl” 设为 “lr-t)

大家在重置这些属性时要小心。 考虑一下某个菜单系统:在 a:hover 时改变了 hasLayout 的状态,不管是否是故意的,都可能导致渲染出现意外的状况(或者导致 IE 6 程序不稳定,比如在和 position: relative 同时使用时动态取消 hasLayout)。

display 属性的不同:当用“inline-block”设置了 haslayout = true 时,就算在一条独立的规则中覆盖这个属性为“block”“inline”,haslayout 这个标志位也不会被重置为 false

mid-width, mid-height 设为它们的默认值“0”仍然会赋予 hasLayout,但是 IE 7 却可以接受一个不合法的属性“auto”来重置 hasLayout

脚本属性 hasLayout

我们这里称 hasLayout 为“脚本属性”是为了和我们熟知的 CSS 属性相区别。

没有办法直接设置或重置一个元素的脚本属性 haslayout

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):

<!--[if lte IE 6]>
<style>
.gainlayout { height: 1px; }
</style>
<![endif]-->

在条件注释中链接一个专门对 IE/Win 做修正的外部样式表文件,也不失为一个安全有效的好方法:

<link rel="stylesheet" href="allbrowsers.css" type="text/css" />

<!--[if lte IE 6]>
<link rel="stylesheet" href="iefix.css" type="text/css" />
<![endif]-->

我们更倾向于使用 height: 01px —— 并主张始终使用 height 除非它和别的什么东西冲突 (overflow: hidden)。对于取值,我们则倾向于避免 1% ,因为它可能会(虽然很少)引起一些问题

height 不能应用于标准模式下的内联元素。在这种情况下我们可以用 display: inline-blockzoom: 1

我们曾看过一些把 Holly hack 真的当作 holy(神圣的) hack 盲目使用的情况,比如对浮动元素使用或者对已经具有特定宽度的元素也使用这个 hack。要记住这个 hack 的目的不是要给某个元素加一个高度,而只是要触发 hasLayout = True 而已。

不要给所有元素设置 layout:* {_height: 1px;}。所谓过犹不及,获得 layout 不等于获得灵丹妙药,它只是用来改变渲染模式。

Hack整理

但是浏览器总是会变的,我们需要面对很多问题,比如一些依赖 IE6 的 bug 所做的 hack 会在 IE7 或更高版本的新浏览器中因 bug 修复而失效(甚至有害)的问题;比如新版本浏览器中类似的布局 bug 依然存在但用于 hack 的过滤器比如 * html 却不能正常工作的问题。这种情况下,MS专有属性 zoom 就可以考虑使用了。

<!--[if lt IE 7]><style>
/* IE 6 + IE5.5 + IE5.0 所用样式*/
.gainlayout { height: 0; }
</style><![endif]-->

<!--[if IE 7]><style>
.gainlayout { zoom: 1;}
/* 或者其他任何以后可能需要的东西 */
</style><![endif]-->
  • 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 和别的解决方法(特别是通过使用 heightwidth 属性的)往往对 IE Mac 来说是有害的,所以需要对其隐藏。更多的关于 IE Mac 相关的问题可以在 IE Mac, bugs and oddities pages 找到。

MSDN 文档

MSDN 中涉及到 hasLayout 这个 MS 属性的地方寥寥无几,而具体解释 layout 和 IE 渲染模型之间关系的则少之又少。

在IE4的时候,除了未经绝对定位也未指定宽高的内联元素,几乎所有元素都有某种 layout(MSDN ——此文已被修改1)。在这种早期的layout概念中,像 border, margin, padding 这些属性被称作“layout属性”,它们是不能应用到一个简单的内联元素上的。换句话说,“拥有layout”就可以粗略理解成:“可以拥有这几个属性”。

MSDN 上仍然使用 layout 属性这种说法, 只是含义变了,它们和拥有 layout 的元素已经没有什么关系了。在 IE5.5 中方才引入了 MS 的这个专有属性 hasLayout,也只是某种内部的标志位而已。

在 IE5.5 中,MSHTML Editing Platform(即可以通过设置<body contenteditable=true>来允许用户实时编辑、拖动 layout 元素以及调整其尺寸等)的文档中描述了三个和 layout 相关的重要特性:

如果一个 layout 元素中有内容,内容的排版布局将由它的边界矩形框决定。

拥有 layout 的意思基本上就是表示某元素是一个矩形。

从内部来说,拥有 layout 意思就是一个元素将自己负责绘制其内部内容。

(Editing Platform —— 此文在 MSDN 上已被删除2)

和 layout 自身相关的内部工作机制直到2005年8月才有相应文档描述,当时由于 The Web Standards Project 和微软的特别工作小组的原因,Markus Mielke [MSFT] 打开了深入讨论的大门:

一 般来说,在 Internet Explorer 的 DHTML 引擎中,元素是不对自己的位置安排负责的。虽然一个 div 或者一个 p 元素都在源码中有一个位置,在文档流有一个位置,但是它们的内容却是由它们最近的一个 layout 祖先(经常是 body)控制安排的。这些元素依赖它们祖先的 layout 来为他们处理诸如决定大小尺寸和测量信息等诸多繁重的工作。

(HasLayout概述)

分析

我 们的分析试图解释在已知案例下发生了什么事情,这种分析也应该可以作为未知案例下的指导。但我们这种试图利用种种测试案例投石探路的黑箱测试方法,是注定 无法消除黑箱的神秘感的——我们无法回答“为什么”的问题。我们只能去尝试了解整个“hasLayout”模式的工作框架,以及它会怎样影响网页文档的渲 染。因此,最终我们只能提供一些指导方针(而且只能是指导方针,而不是绝对的解决方案)。

我们认为他们所指的是一个小窗体。一个 layout 元素的内部内容是完全独立的,而且也无法影响其边界外的任何内容。

而 MS 属性 layout 只是某种标志位:一旦它被设定,这个元素就会拥有 layout“特性”,这包括体现在其自身以及其非 layout 孩子元素身上的特殊性能——比如浮动和层叠等。

这种独立性也许正可以解释为什么 layout 元素通常比较稳定,而且它们可以让某些 bug 消失。这种情况的代价有二,一是偏离了标准,二是它没有考虑到今后可能因此出现的 bug 和问题。

MS 的“页面”模式,从符号学角度考虑,可以看做是由很多互不相关的小的区块构成,而 HTML 和 W3C 的模式则认为“页面”模式应该是叙述完备的,故事性的相关信息区块构成的。

各种情况的详细说明

清除浮动和自动扩展适应高度

浮动元素会被 layou 元素自动包含。这是很多新手经常遇到的问题:在 IE 下完成的页面到了标准兼容浏览器下所有未清除的浮动元素都伸出了其包含容器之外。

相反的情况:如果确实需要一个浮动元素伸出其包含容器,也就是自动包含不是想要的效果时,该怎么办?你很可能也会遇到这种头疼的问题,下面的深入讨论就是一个例子:

在IE中,一个浮动元素总是“隶属于”它的 layout 包含容器。而后面的元素会受这个 layout 包含容器影响而不是这个浮动元素影响。

这个特性和IE6的那个自动扩展以适应内部内容宽度的特性,都可以看成是受这个规则影响的:“由它的边界矩形框决定”。

更糟的问题:clear 无法影响其 layout 包含容器之外的 float 元素。如果依赖这个 bug 在 IE 中布局的页面要转到标准兼容浏览器中,只有全部重做。

IE 的自动包含浮动元素也是经常需要的效果,它在其他浏览器中也可以达到:参考我们的 “和 CSS 规范类似的地方” 这一部分来了解一下包含浮动元素的相关内容。

浮动元素旁边的元素

当 一个块级元素紧跟在一个左浮动元素之后时,它应该——作为一个块级元素——忽略这个浮动元素,而它的内容则应该因这个浮动元素而移位:一个紧跟在左浮动元 素后的块级元素内的文字内容,应该沿着浮动元素的右边顺序排列并会(如果它的长度超过浮动元素)继续排列到浮动元素下方。但是如果这个块级元素有 layout,比如由于某种原因被设置了宽度,那么这整个元素则会因浮动元素而移位,就好像它自己也是一个浮动元素一样,因此其中的文字就不再环绕这个左 浮动元素了(而会形成一个矩形区域,保持在它的右边。)

在 IE5 中一个块级元素的百分比宽度是基于浮动元素旁边的剩余空间计算的,而在 IE6 中则是依照整个父块级元素的可用空间计算的。所以在 IE6 中设置 width: 100% 会导致某种浮动元素旁边的溢出现象,于是各种布局问题也会因此而来。

一些关于浮动块旁边的 hasLayout 块的测试案例:

与此类似,和浮动元素相邻的相对定位元素,它的位置偏移量应该参照的是父元素的补白(padding)边缘(例如,left: 0; 应该将一个相对定位元素叠放于它前面的浮动元素之上)。在 IE6 中,偏移量 left: value; 是从浮动元素的右边距(margin)边缘开始算起的,这会因浮动元素所占的宽度变化导致水平方向的错位(一个解决方法是用 margin-left 代替,但是也要注意如使用百分值时会有一些怪异问题)。

根据规范所述,浮动元素应该与其后的盒子交织在一起。而对于没有交叉的二维空间中的矩形而言这是无法实现的。

如 果谁真的需要向 IE 的这种不当行为屈服,那么如何让标准兼容浏览器中的盒子也有类似行为——即类似于 layout 盒子会自动“收缩”而给其前置的浮动元素让出空间的行为——就是一个问题了。我们给出的方法是跟着一个浮动元素创建一个新的块级格式化范围(block formatting context),这在我们的“和 CSS 规范类似的地方” 有讨论。

可以(再次)访问下面这个页面:

我 们可以看到跟在一个浮动元素后的 layout 元素不会显示这个3px间隙的 bug,因为浮动元素外围的3px硬边无法影响一个 layout 元素的内部内容,所以这个硬边将整个 layout 元素右推了3px。好比一个防护罩,layout 可以保护其内部内容不受影响,但是浮动元素的力量却将整个防护罩推了开来。

列表

无论是列表本身(ol, ul) 还是单个的列表元素(li), 拥有 layout 后都会影响列表的表现。不同版本 IE 的表现又有不同。最明显的效果就体现在列表符号上(如果你的列表自定义了列表符号则不会受这个问题影响)。这些符号很可能是通过某种内部机制附到列表元素 上的(通常是附着在它们外面)。不幸的是,由于是通过“内部机制”添加的,我们无法访问它们也无法修正它们的错误表现。

最明显的效果有:

  • 列表获得 layout 后,列表符号会消失或者被放置在不同的或者错误的位置。

有时它们又可以通过改变列表元素的边距而重新出现。这看起来似乎是以下事实导致的结果:layout 元素会试图裁掉超出其边界的内部内容。

进一步又有一个问题就是(在有序列表中)任何具有 layout 的列表元素似乎都有自己独立的计数器。比如我们有一个含五个列表元素的有序列表,只有第三个列表元素有 layout。我们会看到这样:

1… 2… 1… 4… 5…

此外,如果一个有 layout 的列表元素跨行显示时,列表符号会底部对齐(而不是按照预料的顶部对齐)。

以上某些问题还是无法解决的,所以如果需要列表符号的时候最好避免让列表和列表元素获得 layout。如果需要限定尺寸,最好给别的元素设定尺寸,比如给整个列表外面套一个元素并设定它的宽度,又或者比如给每个列表元素中的内容设定高度等等。

另一个IE中列表的常见问题出现在当某个 li 中的内容是一个 display: block 的锚点(anchor)时。在这种情况下,列表元素之间的空格将不会被忽略而且通常会显示成额外的一行夹在每个 li 之间。一种避免这种竖直方向多余空白的解决方法是赋予这些锚点 layout。这样还有一个好处就是可以让整个锚点的矩形区域都可以响应鼠标点击。

表格

table 总是有 layout 的,它总表现为一个已定义宽度的对象。在IE6中,table-layout: fixed 通常和一个宽度设为100%的表格相同,同时这也会带来很多问题(一些计算方面的错误)。另外在IE5.5和IE6的quirks模式下还有一些别的需要注意的情况

相对定位元素(r.p.)

注意,由于 position: relative 并不触发 hasLayout,所以很多诸如内容消失或错位的渲染错误就会因此而起。这些现象可能会在刷新页面、调整窗口大小、滚动页面、选中内容等情况下出现。原 因是 IE 在据这个属性对元素做偏移处理时,却似乎忘了发出信号让其 layout 孩子元素进行“重绘”(而如果是一个layout元素,那么在其重绘事件的信号链中,这个传给其孩子的信号是会正常发出的)。

以上是一些相关问题的描述。作为经验之谈,相对定位一个元素时最好给予其 layout。再有,我们也需要检查拥有这种结构的父元素是否也需要 layout 或者position: relative亦或二者都需要,如果涉及到浮动元素这点就十分重要。

绝对定位元素(a.p.):包含区块,什么是包含区块?

理解 CSS 的包含区块概念很重要,它回答了绝对定位元素是相对哪里定位的问题:包含区块决定了偏移起点,包含区块定义了百分比长度的计算参考。

对于绝对定位元素,包含区块是由其最近的定位祖先决定的。如果其祖先都没有被定位,那么就使用初始包含区块 html

通常情况下我们会用 position: relative 来设定任意包含区块。这就是说,我们可以让一个绝对定位元素所参考的原点和长度等不依赖于元素的排列顺序,这可以满足诸如“内容优先”这种可访问性概念的需要,也可以给复杂的浮动布局带来方便。

但 是由于 layout 概念的存在,这种设计理念的效果在IE中就要打个问号了:因为在IE中绝对定位只有当其包含元素拥有 layout 时才会计算正确,而且绝对定位元素的百分比宽度参考也搞错了对象。这里 IE5 和 IE6 的行为不同但都有问题。IE7b2 的行为就要好很多,虽然有些小地方还是有错误。总之尽可能的让绝对元素的包含区块拥有 layout,而且尽量让其就是绝对定位元素的父级元素(也就是说这个包换元素和绝对定位元素之间没有绝对定位元素的别的祖先了)。

假设一个无 layout 的父元素被相对定位了——我们就得给它赋予 layout 才能使偏移量起作用:

假设一个未定位的父元素需要特定尺寸,而且页面设计是基于百分比宽度的——我们就可以放弃这个想法了,因为浏览器支持不佳:

滤镜

MS专有的滤镜属性 filter 是只适用于 layout 元素的。同时它们也会显示出自身特有的缺陷

对已渲染元素的重排(re-flow)

当所有元素都已渲染完成时,如果有一个因鼠标经过而引起的变化产生(比如某个链接的 background 有变化),IE会对其 layout 包含区块进行重排。有时一些元素就会因此被排到了新的位置,因为当这个鼠标经过发生时,IE已经知道了所有相关元素的宽度、偏移量等数据了。这在文档首次 载入时则不会发生,那时由于自动扩张的特性,宽度还无法确定。这种情况会导致在鼠标经过时页面出现跳变。

这些和重排问题相关的 bug 会给百分比边距和补白使用较多的流动布局带来不少麻烦。

背景原点

MS专有的这个 hasLayout 还会影响背景的定位和扩展。比如,根据 CSS 规范background-position: 0 0 应该指元素的“补白边缘(padding edge)”。而在 IE/Win 下,如果 hasLayout = false 则指的是“边框边缘(border edge)”,当 hasLayout=true 时指的才是补白边缘:

边距重叠

hasLayout 会影响一个盒子和其子孙的边距重叠。根据规范,一个盒子如果没有上补白和上边框,那么它的上边距应该和其文档流中的第一个孩子元素的上边距重叠:

在 IE/Win 中如果这个盒子有 layout 那么这种现象就不会发生了:似乎拥有 layout 会阻止其孩子的边距伸出包含容器之外。此外当 hasLayout = true 时,不论包含容器还是孩子元素,都会有边距计算错误的问题出现。

hasLayout 会影响一个块级别链接的鼠标响应区域(可点击区域)。通常 hasLayout = false 时只有文字覆盖区域才能响应。而 hasLayout = true 则整个块状区域都可响应。添加了 onclick/onmouseover 等事件的任意块级元素也有同样的现象。

在页面内使用键盘浏览:探索中

当使用 tab 在页面中浏览时,如果进入了一个页内链接(in-page link),那么接下来再按的 tab 键就不会正常继续了:

tab 键会把用户带到(这通常是错误的)其最近的 layout 祖先中的第一个目标(如果这个祖先是由 tabledivspan 或某些别的标签构成)。

收缩包围(shrink-wrapping)现象

给已经有 width: auto 的元素添加某些属性会导致它们在计算自身宽度时使用一种收缩包围的算法。比如这些属性 float: left|right, position: absolute|fixed, display: table|table-cell|inline-block|inline-table.

这些属性造成的现象在IE/Win中也存在,当然这是只对那些它支持的属性而言。但是当一个应该收缩包围的元素中包含一个拥有“layout”的块级元素时,在绝大多数情况下,这个孩子元素的宽度会尽可能地扩展而与其中包含的内容无关,同时也阻止了父元素的收缩包围现象。

例子
一个浮动的纵向导航无序列表并没有收缩包围,因为其中的链接为了消除列表的多余空白bug并扩展可点击区域而拥有了 layout:a {display: block; zoom: 1;}

这时收缩包围现象只有在以下情况仍然有效:拥有 layout 的孩子元素同时也被赋予了一个特定宽度,或者这个孩子元素本身也是一个具有收缩包围特性的元素,比如浮动元素。

边缘裁切

通常而言,当一个盒子包含了诸如伸出其边缘的内容这种更复杂的结构时,这个容器就经常需要“hasLayout”来避免一些渲染错误。但使用这种常用方法又会在边界处理时左右为难,因为一个获得“layout”的元素会变成某种自封闭的盒子。

内部的内容盒子会被裁切,比如使用负边距向外移动时。

被裁掉的部分当内容盒子触发了“layout”时可以再次出现,但在 IE6 中需要同时拥有 position: relative 才行。IE7 在这方面要略有改观,它不再需要额外的 position: relative 了。

堆叠,分层和 layout

IE/Win 中似乎有两种分层和堆叠顺序:

  • 一种是(伪)试图采用CSS的模式:Effect of z-index value to RP and AP blocks
  • 还 有一种是由“hasLayout”及其孪生兄弟“contenteditable”的行为产生的堆叠顺序。正如在上面相对定位的例子中展现的那样,在 layout 影响下的堆叠现象就好像 Harry Houdini (译者注:魔术师,以纸牌魔术成名)的拿手戏法儿一样。

两 种堆叠模式虽互不相容,但却共存于IE的渲染引擎中。经验之谈:调试的时候,两种情况都要考虑到。我们可能会有规律地在下拉菜单或者类似的复杂菜单中看到 相关问题,因为它们往往牵涉到堆叠,定位和浮动等诸多令人头疼的问题。给那些 z-index 定位的元素 layout 是一种可能的修正方法,不过也不限于此,这里只是提醒一下。

混乱的 contenteditable

如果给一个 HTML 标签设定 contenteditable=true 属性,比如<body contenteditable=true>,将会允许对该元素以及其 layout 子元素进行实时的编辑、拖动改变尺寸等操作。你可以把这属性用在浮动元素或者一个有序列表中的 layout 列表元素上看看效果。

为了对元素进行操作(编辑它们),“contenteditable”和“hasLayout”为那些 hasLayout 返回 true 的元素引入了一套单独的堆叠顺序。

Editing Platform(此文已从 MSDN 删除2)继承了 layout 概念,对 layout 的误解多是因 contenteditable 而起即可作为证明(那些某种程度上集成了 IE 编辑引擎的应用软件多暗含着对 layout 概念的某种强制向后兼容性)。

和 CSS 规范类似的地方

你的 MSIE 页面在别的浏览器中一团糟?我们可没必要让这种事情发生。如果使用恰当,任何好的浏览器都能摆平 MSIE 的页面——只要你使用一些正确的 CSS。

利用 hasLayout 和“新的块级格式化范围”之间的细微相似之处,我们可以有几种方法在标准兼容浏览器中重新实现 hasLayout 的“包含浮动元素”效果,和一些“浮动元素旁边的元素”所特有的效果。

Quirks 模式

关于这种渲染模式的的信息,请参考我们的 quirks 模式章节。

Layout ——结论

整个 layout 概念和一些基本 CSS 概念是不兼容的,即包含,排列,浮动,定位和层叠等。

由于页面中元素或有或没有 layout,会导致 IE/Win 的行为和 CSS 规范相违背。

拥有 layout ——另外一个引擎?

IE 的对象模型看起来是文档模型和他们传统的应用程序模型的糅合。我之所以提到这点是因为它对于理解IE如何渲染页面很重要。而从文档模型切换到应用程序模型的开关就是给一个元素“layout”。

(Dean Edwards)

有时候要解释清楚某种行为是不可能的:就比如 hasLayout,会根据它的状态选择两种不同渲染引擎的一种使用,而且每一种都有其自己的 bug 和怪异之处。

不可消除的 bug

软件 bug 是由于在制作过程中对完整性和逻辑问题考虑不周等人为错误而导致的。这是人类的固有缺陷,目前还没有什么好的解决方法。

同样由于这种缺陷,任何试图不重写软件而修复 bug 的做法,都将会不可避免的导致软件中出现更复杂的bug。

所有依赖别的软件的软件——当然包括依赖操作系统,也会同样依赖他们的 bug。于是我们会从所有关联的软件中得到一连串的 bug,这也更说明找到一个无 bug 软件是几乎不可能的。

(Molly, the cat‛)

  1. 原文在 MSDN 上被修改过了。我们在 Internet Archive 上找到了一个存档版本(Controlling Presentation with Measurement and Location Properties)。
  2. 原文在 MSDN 上已被删除,这里是 Internet Archive 上的一个存档版本(The MSHTML Editing Platform in Internet Explorer 5.5)。

(译文原文:http://old9.blogsome.com/2006/04/11/onhavinglayout/

关于width:100%

2条评论»
<!--css-->
#layout{
  position:absolute;
  min-width:400px;
  _width:400px;
  min-height:300px;
  _height:300px;
  border:1px solid #F00;
  background:#EEE;}
  #title,#content{
  white-space:nowrap;
  background:#CCC;
  border-bottom:2px solid #000;
  font-weight:bold;
}
#content{
  border:none;
  padding:10px 0;
  background:#FFF;
  font-size:12px;
  font-weight:normal;
}
<!--css-->
<!--xhtml-->
<div id="layout">
  <h2 id="title">如何用 Javascript</h2>
  <p id="content">坦白说,起先我对短短的五行代码</p>
</div>
<!--xhtml-->

测试无忧上一个问题引出的另外一个问题。由于设置了min-width和width,white-space在FF和IE中都会因为内容过多将#layout宽度撑开。按道理#title和#content的宽度都会自动伸展到与#layout一致,但是IE6中并不会自动伸展到和#layout一致的宽度~···只保持在最初#layout宽400px时100%的宽度~···

同时发现,当为#title,#content设置width:100%的时候,IE7也会出现和IE6同样的问题,个人觉得可能是hasLayout引发的~···

这个问题现在人没找到合理的解决办法,记下~···

一个分辨率自适应的典型布局

发表评论»
<!--
*{color:#000; font-size:18px; font-family:Arial, Helvetica, sans-serif, "宋体";}
#header{height:100px; background:#999;}
#layout{position:relative; margin-top:10px;}
#left{height:400px; width:200px; background:#EEE; position:absolute;left:0;top:0;}
#right{height:400px; width:200px; background:#EEE;position:absolute;right:0;top:0;}
#center{margin:0 210px; height:600px; background:#666;}
-->
<!--xhtml-->
<div id="header">header</div>
<div id="layout">
  <div id="left">left</div>
  <div id="center">center</div>
  <div id="right">right</div>
</div>
<!--xhtml-->

刚才在BI上有人问,嘿嘿,好像平时很少做这些东西,即使做了也没印象,很长一段时间都是埋着头写,很简单的代码。一直不喜欢用绝对定位,但是渐渐发现绝对定位用好了,也是很爽的呀~···