“html/css”分类下所有日志

详解CSS的优先权

展开/收缩

转载出处:http://www.planabc.net/2008/05/06/css_specificity/

发现很多朋友对 CSS 的优先权不甚了解,规则很简单。需要说明的一点,如果你的样式管理需要深层判断 CSS 的优先权,更应反思自己的 CSS 代码,是否合理?是否优化?

CSS2.1 中规定了关于 CSS 规则 Specificity(特异性)的计算方式,用一个四位的数字串(注:CSS2 中是用三位)来表示,最后以 Specificity 的高低判断 CSS 的优先权。

Specificity 具体的计算规则:

    * 元素的 style 样式属性,加 1,0,0,0。
    * 每个 ID 选择符(#id),加 0,1,0,0。
    * 每个 class 选择符(.class)、每个属性选择符(例 [attr=”"] )、每个伪类(例 :hover),加 0,0,1,0。
    * 每个元素或伪元素(例 :firstchild)等,加 0,0,0,1。
    * 其他选择符(例 全局选择符 *,子选择符 >),加 0,0,0,0。

最后逐位相加数字串,得到最终的 Specificity 值,按照从左到右的顺序逐位比较。

除了 Specificity 还有一些其他规则:

    * !important 声明的规则高于一切,如果 !important 声明冲突,则比较优先权。
    * 如果优先权一样,则按源码中“后来者居上”的原则。
    * 由继承而得到的样式属性不参与 specificity 的计算,低于一切其他规则(例 全局选择符 * )。

范例分析:

h1 {color: red;}
/* 只有一个普通元素加成,结果是 0,0,0,1 */
body h1 {color: green;}
/* 两个普通元素加成,结果是 0,0,0,2 */
/*0,0,0,1 小于 0,0,0,2 ,后者胜出*/

h2.grape {color: purple;}
/* 一个普通元素、一个class选择符加成,结果是 0,0,1,1*/
h2 {color: silver;}
/*一个普通元素,结果是 0,0,0,1 */
/*0,0,1,1 大于 0,0,0,1 ,前者胜出*/

html > body table tr[id=”totals”] td ul > li {color: maroon;}
/* 7个普通元素、一个属性选择符、两个其他选择符(子选择符 >),结果是0,0,1,7 */
li#answer {color: navy;}
/* 一个ID选择符,一个普通选择符,结果是0,1,0,1 */
/*0,0,1,7 小于 0,1,0,1,后者胜出*/

节选 old9 的《CSS的优先权》(无法穿越 GFW)

css命名规范

展开/收缩

良好的命名规范可以为团队合作开发推波助澜,无论在项目开发,还是产品维护上都起到了至关重要的作用。应该说命名规范是一种约定,也是程序员之间良好沟通的桥梁。

另外古人相信只要知道一个人真正的名字就会获得凌驾于那个人之上的不可思议的力量。只要给事物想到正确的名字,它就可以带来比代码更强的力量。如果所有的命名都与其自然相适合,则关系清晰,含义可以推导得出,一般人的推想也能在意料之中。

CSS+DIV的命名规则:

登录条:loginBar
标志:logo
侧栏:sideBar
广告:banner
导航:nav
子导航:subNav
菜单:menu
子菜单:subMenu
搜索:search
滚动:scroll
页面主体:main
内容:content
标签页:tab
文章列表:list
提示信息:msg
小技巧:tips
栏目标题:title
友情链接:friendLink
页脚:footer
加入:joinus
指南:guild
服务:service
热点:hot
新闻:news
下载:download
注册:regsiter
状态:status
按钮:btn
投票:vote
合作伙伴:partner
版权:copyRight

1.CSSID的命名
外套:wrap
主导航:mainNav
子导航:subnav
页脚:footer
整个页面:content
页眉:header
页脚:footer
商标:label
标题:title
主导航:mainNav(globalNav)
顶导航:topnav
边导航:sidebar
左导航:leftsideBar
右导航:rightsideBar
旗志:logo
标语:banner
菜单内容1:menu1Content
菜单容量:menuContainer
子菜单:submenu
边导航图标:sidebarIcon
注释:note
面包屑:breadCrumb(即页面所处位置导航提示)
容器:container
内容:content
搜索:search
登陆:login
功能区:shop(如购物车,收银台)
当前的current

2.样式文件命名
主要的:master.css
布局版面:layout.css
专栏:columns.css
文字:font.css
打印样式:print.css
主题:themes.css

说明:均为class,需要扩展,则在当前命名内以“_“(下划线)后缀自定名称。
我习惯称列表页为list,新闻列表则为newslist,图片列表为piclist,
内容页为view,
/**/
整体大框架:#wrapper
大框架内:#inwrapper
/////////////////////////////////////////////////////////////////////////////////////////////////////////
顶部及banner:.top
顶部及banner内:.intop
Logo:.logo
Banner:.banner
导航:.menu
导航内:.inmenu
        .Menuul
        .Menuul li
        .Menuul li a
下拉菜单:.inmenu_xiala
          .Inmenu_xialaul
          .Inmenu_xialaul li
          .Inmenu_xialaul li a
///////////////////////////////////////////////////////////////////////////////////////////////////////////
主体内容:.mainWrapper
主体内容内:.inmainwrapper
左侧拦:.sideleft
左侧内:.insideleft
右侧栏:.sideright
右侧内:.insideright
中间:.sidecenter
中间内:.insidecenter
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
底部:.foot
底部内:.infoot
////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*其他命名*/
搜索:.search
搜索内:.insearch
搜索条:.searchselect
搜索按钮:.serachbuttom
输入文本框:.input
.select

/*表格样式*/
表格整体框架:.listbox
表格的宽度:.listbox-table
表格头部文字样式:.listbox-header
表格正文文字样式:.listbox-entry
/*通用型*/
通用:.GM/*这个有点郁闷,英文太差…*/
通用内:.INGM
通用左浮动:.GMfl(GM FLOAT LEFT)
通用右浮动:.GMfr(GM FLOAT RIGHT)
/*通用图片样式*/
通用图片样式:.img
/*清除浮动*/
清除所有浮动:.clear
清除左侧浮动:.clearleft
清除右侧浮动:.clearright
/*文字样式*/
文字:.font
/*新闻列表*/
新闻列表:.fontnews
/*View页字体总样式*/
VIEW页字体:.fontview

商 标:  label
标 题:  title
主导航:  mainbav(globalnav)
顶导航:  topnav
边导航:  sidebar
左导航:  leftsidebar
右导航:  rightsidebar
旗 志:  logo
标 语:  banner
菜单内容1: menu1 content
菜单容量: menu container
子菜单:  submenu
边导航图标:sidebarIcon
注释:   note
面包屑:  breadcrumb(即页面所处位置导航提示)
容器:   container
内容:   content
搜索:   search
登陆:   Login
功能区:  shop(如购物车,收银台)
当前的   current
报头:   masthead
摘要, 概要  summary或general
左边的浮动照图片 photoleft
右边的浮动图片 photoright
标题   title
条目底端    entrybottom
更多    extended或.more
容器背景 containerbg
服务   service
服务链接   servicelink
线   line
文本   text
右边   rightside
版权   copyright
新闻   news
书皮   wrapper
介绍      intro-part1
专栏   column
路径   pathways
片断   section
模块   module
上导航   subnav
2.另外在编辑样式表时可用的注释可这样写:

<– Footer –>
内容区
<– End Footer –>

3.样式文件命名

主要的 master.css
布局,版面 layout.css
专栏 columns.css
文字 font.css
打印样式 print.css
主题 themes.css

4.样式表中的注示
实例一
/* GLOBAL ————————— */
/* LINKS ————————— */
/* FORMS ————————— */
/* IDS ————————— */
/* HEADER ————————— */
/* COLUMN 1 ————————— */
/* COLUMN 2 ————————— */
/* CLASSES ————————— */

实例二

HTML

实例三(网易)

CSS
#UrsLogin
#LogoNav
#Column
#Content1
#bNav
#Copyright
#UrsLogin
#LogoNav
#SearchArea
#ChannelArea
#HotNews
#NewsCenter
.keyword
#MallArea
#city
#aboutus

……………………
常见命名

包含 wrapper和container
页头 header 或缩写为hd
页尾 footer 或缩写为ft
导航 nav
您的位置 breadcrumbs
二级导航 sub_nav
侧栏 sidebar或side-column
模块 module

数据库中的命名规则

数据库涉及字符规则

采用26个英文字母(区分大小写)和0 -9这十个自然数,加上下划线_组成,共63个字符。不能出现其他字符(注释除外)。

数据库对象命名规则

数据库对象包括表、视图(查询)、存储过程(参数查询)、函数、约束。对象名字由前缀和实际名字组成,长度不超过30。前缀:使用小写字母。

例如:表-tb 视图-vi 存储过程-sp 函数-fn

实际名字

实际名字尽量描述实体的内容,由单词或单词组合,每个单词的首字母大写,其他字母小写,不以数字和_开头。

例如:表 User_Info 视图 UserList 存储过程 UserDelete

因此,合法的对象名字类似如下。

表 tbUser_Info、tbMessage_Detail

视图 vi_MessageList

存储过程 sp_MessageAdd

数据库表命名规则

字段由前缀和实际名字组成。实际名字中首单词一个系统尽量采取同一单词。

前缀:使用小写字母tb,表示表。

例如:tbMember   tbMember_Info   tbForum_Board   tbForum_Thread1

字段命名规则

数字、字符、日期/时间、lob(大对象)、杂项,字段由表的简称、下划线,实际名字加后缀组成。

后缀:使用小写字母,代表该字段的属性。

例如:  User_Idint     User_Namestr     User_RegDatedtm

视图命名规则

字段由前缀和实际名字组成,中间用下划线连接。

前缀:使用小写字母vi,表示视图。

例如:vi_User    vi_UserInfo

存储过程命名规则

字段由前缀和实际名字组成,中间用下划线连接。
前缀:使用小写字母sp,表示存储过程。
例如:sp_User

数据库设计文档规则

所有数据库设计要写成文档,文档以模块化形式表达。大致格式如下:

‘——————————————-

‘  表名:  tbUser_Info  

‘  建立人:UAM_Richard

‘  日期:  2004-12-17

‘  版本:  1.0

‘  描述:  保存用户资料

‘  具体内容:

‘  UserId  int,自动增量  用户代码

‘  UserName  char(12)  用户名字

‘  ……

‘——————————————–
CSS类及id中的命名规则

Web开发人员可以通过创建CSS类及id名称并使用这些名称来对div以及其他的格式页面元素进行标识。对开发人员来说,在命名重新定义 XHTML标记(tags)的CSS selectors时,必须保证其与预定义的标记准确匹配,但就类以及id选择器名称而言,则仁者见仁,智者见智。然而随心所欲的为这些类以及id命名则并不是个好的习惯。

1、直观命名

当在设计Web页面以及需要对一个div进行标识的时候,最自然的想法就是使用可以描述元素所在页面位置的词汇来对其命名。

例如:top-panel

horizontal-nav

left-side

center-column

right-col

这些是CSS以及XHTML类和id的有效命名方式。这些词汇简单并且能够使人顾名思义,因此满足了标识页面元素以及相应的CSS样式的需要。

但问题是这样的名称同页面内容的特定表达方式相关联。这些命名参考了某种特定页面布局中的页面元素位置,因此在这样的布局之外使用就会显得不合适甚至造成理解混乱。这些命名没有涉及文档内容的结构。因此,下面给出了对CSS类以及ID命名更好的方法。

2、结构化命名

这些是CSS以及XHTML类和id的有效命名方式。这些词汇简单并且能够使人顾名思义,因此满足了标识页面元素以及相应的CSS样式的需要。这些是CSS以及XHTML类和id的有效命名方式。这些词汇简单并且能够使人顾名思义,因此满足了标识页面元素以及相应的CSS样式的需要。

有标记的相关信息都是用来描述文档的结构而不是外观。这样的特点使得我们可以通过简单的改变CSS的方式来对不同外观格式下的内容(content)以及标记(markup)进行重用。当你理解这种方式时,很容易就可以发现采用页面位置来为类以及id命名的方式在处理如音频(audio)等外观格式上显得非常不合适。因此,应当根据在文档中的使用目的而非出现位置来对类以及id进行结构化命名。

可以按照如下所示的结构化方式来对类以及id名称命名:

例如:branding

main-nav

subnav

main-content

sidebar

这些名字同直观命名方式一样非常易懂,但他们描述了页面元素的作用而非位置。这使得代码更加符合使用纯粹的结构化标记(structural markup)的初衷,即开发人员可以在不改变标记的情况下对各种各样媒体下的显示格式进行处理。

即使你不打算在其他的媒体上对Web页面进行格式修改,使用结构化命名方式还可以帮助你在日后的站点升级或重新设计中更为轻松。例如,结构化命名避免了当一个div同id right-column移动到页面左边后所带来的混乱。对div sidebar的采用这样的命名方式就显得更加适当,因为无论它出现在页面的哪一边,这个名字仍然对开发人员来说直观易懂。

3、惯例

Andy Clarke分析了40份由推崇标准化Web设计理念的开发人员所设计的Web站点的源代码。尽管类以及id名称很不统一,但是还是发现了一些频繁出现的常用名称。这里给出了最常用类/id名称的示例列表:

例如:header

content

nav

sidebar

footer

3.基于成员的命名规范
基于成员的命名规范是指按照文件,文件夹的从属关系,通过归类的方法进行命名,这样可以使文件的排列具有较强的逻辑性.
例如:一个图片文件是在鼠标点击之前为”file_on”.而在点击后的图片文件命名为”file_off”根据这个类别命名.更加的清晰.

4.基于属性的命名规范
例如:装饰性小图片按照”<图片内容说明>_<颜色>_<图片尺寸>_<序号>.*”来表现.这个为”heart_red_401*334_1.jpg”

5.基于序数的命名规范
在网页中一般为了减少图片的下载时间把图片分隔成一小部分,组成一个整体图.这时可以用二维数组的方式命名.
例如:     

这个图片为”donghua_11.jpg”

这个图片为”donghua_12.jpg”

这个图片为”donghua_21.jpg”

这个图片为”donghua_22.jpg”

这些组成一幅图片.

6.基于枚举的命名规范

第一个为书的侧面为”ddd_cemian.jpg”
第二个为书的封皮为”ddd_fengpi.jpg”
第三个为书的封底为”ddd_fengdi.jpg”

还有的网站上图片的欣赏也有不同的大小,可根据用户的意愿查看.

例如:”ddd_cemian_401*334.jpg”和”ddd_cemian_1024*768.jpg”

这些供大家建设网站参考.

为避免代码冲突(这样做也会让你的代码更为通用),就要使用命名法则,这是一个很好的编程习惯。好啦,这里介绍一些常用的法则。

◆命名变量、方法、以及属性

变量、方法和属性的名称的第一个字母应该大写,并且名称应该能表达出它们的用途(或者说是意义)。

变量
.NET 命名
匈牙利命名
描述

Cstring
EmployeeName
szName
Name of an employee.

Int
AttendanceCounter
nCounter
A counter of type long.

Long
NumberOfBytes
lBytes
A long type variable stores bytes.

有时我们习惯于在定义中使用下划线 “_”,例如: Add_Data(int a, int b). 按照新的命名法则,这不是一个好的编程习惯,虽然它并没有错。你应该将定义 Add_Data 改为 AddData。这不是微软的标准,你也不是必须按照这些法则。但是,在一些地方你会明白下边这些法则的合理性。

就我个人而言,我更喜欢匈牙利命名法。当然,变量也使用同样的法则。如果你记得匈牙利命名法的话,一个布尔型的变量定义以”b”打头,比如:

BOOL bFlag = TRUE;

新的法则不推荐使用Flag 和 “b”:

bool IsFileFound = true;

你可以浏览一下MSDN,那里边有更多有关新的法则的说明。

◆命名组件以及集合(Assemblies)

为避免代码冲突, 按照命名法则给你的库(在 .NET 中称为assembly)命名是一个良好的编程习惯。假定你是MindCracker 公司的,你在开发一个用于扩充C# database 类的库, 把它的名字命名为MindCracker.DatabaseAssembly.ADOSet 要比MyAssembly.Database.ADOSet好的多。

再假定你的库有一个方法,它是从表中读取数据,并返回一个数据集。你如果取名为 DataSet return_data()的话,改为DataSet ReturnData()好啦.

你还应该在命名中遵循一个统一的单词顺序。例如,你有俩个表,分别为Employee 和 Manager ,并且你还为它们分别定义了一个向表里边插入一条记录的方法, 那么方法名AppendEmployee 和 AppendManager 要比AppendEmployee 和 ManagerAppend要好。
我更喜欢的二种方法,因为很容易清楚一个块儿结构和嵌套块儿结构。

◆匈牙利命名法(efoxxx附)

匈牙利命名法是一名匈牙利程序员发明的,而且他在微软工作了多年。此命名法就是通过微软的各种产品和文档传出来的。多数有经验的程序员,不管他们用的是哪门儿语言,都或多或少在使用它

这种命名法的基本原则是:

变量名=属性+类型+对象描述

即一个变量名是由三部分信息组成,这样,程序员很容易理解变量的类型、用途,而且便于记忆。

下边是一些推荐使用的规则例子,你可以挑选使用,也可以根据个人喜好作些修改再用之。

⑴属性部分:

全局变量: g_

常量 : c_

类成员变量: m_

⑵类型部分:

指针: p

句柄: h

布尔型: b

浮点型: f

无符号: u

⑶描述部分:

初始化: Init

临时变量: Tmp

目的对象: Dst

源对象: Src

窗口: Wnd

将介绍匈牙利命名法,后面的例子里也会尽量遵守它和上面的代码风格。还是那句话,并不是要求所有的读者都要去遵守,但是希望读者作为一个现代的软件开发人员都去遵守它。

a       Array                                 数组

b       BOOL (int)                            布尔(整数)

by      Unsigned Char (Byte)                  无符号字符(字节)

c       Char                                  字符(字节)

cb      Count of bytes                        字节数

cr      Color reference value                 颜色(参考)值

cx      Count of x (Short)                    x的集合(短整数)

dw      DWORD   (unsigned long)                 双字(无符号长整数)

f       Flags   (usually multiple bit values)   标志(一般是有多位的数值)

fn      Function                              函数

g_      global                                全局的

h       Handle                                句柄

i       Integer                               整数

l       Long                                  长整数

lp      Long pointer                          长指针

m_      Data member of a class                一个类的数据成员

n       Short int                             短整数

p       Pointer                               指针

s       String                                字符串

sz      Zero terminated String                以0结尾的字符串

tm      Text metric                           文本规则

u       Unsigned int                          无符号整数

ul      Unsigned long (ULONG)                 无符号长整数

w       WORD (unsigned short)                 无符号短整数

x,y     x, y coordinates (short)              坐标值/短整数

v       void                                  空

下边举例说明:

hwnd: h表示句柄,wnd表示窗口,合起来为“窗口句柄”。

m_bFlag: m表示成员变量,b表示布尔,合起来为:“某个类的成员变量,布尔型,是一个状态标志”。

C# .net 命名规范
一个好的命名规范如此难找,还是自己收藏一个比较好

1 ADO.NET          命名规范          数据类型          数据类型简写          标准命名举例        
Connection          con          conNorthwind        
Command          cmd          cmdReturnProducts        
Parameter       parm          parmProductID        
DataAdapter      dad          dadProducts        
DataReader      dtr          dtrProducts        
DataSet          dst          dstNorthWind        
DataTable        dtbl          dtblProduct        
DataRow          drow          drowRow98        
DataColumn         dcol          dcolProductID        
DataRelation      drel          drelMasterDetail        
DataView          dvw          dvwFilteredProducts        

WinForm          Control          命名规范

数据类型          数据类型简写          标准命名举例        
Label            lbl          lblMessage        
LinkLabel       llbl          llblToday        
Button          btn          btnSave        
TextBox          txt          txtName        
MainMenu          mmnu          mmnuFile        
CheckBox          chk          chkStock        
RadioButton      rbtn          rbtnSelected        
GroupBox          gbx          gbxMain        
PictureBox       pic          picImage        
Panel             pnl          pnlBody        
DataGrid          dgrd          dgrdView        
ListBox          lst          lstProducts        
CheckedListBox    clst          clstChecked        
ComboBox          cbo          cboMenu        
ListView          lvw          lvwBrowser        
TreeView          tvw          tvwType        
TabControl          tctl          tctlSelected        
DateTimePicker     dtp          dtpStartDate        
HscrollBar          hsb          hsbImage        
VscrollBar          vsb          vsbImage        
Timer              tmr          tmrCount        
ImageList          ilst          ilstImage        
ToolBar           tlb          tlbManage        
StatusBar          stb          stbFootPrint        
OpenFileDialog      odlg          odlgFile        
SaveFileDialog      sdlg          sdlgSave        
FoldBrowserDialog   fbdlg          fgdlgBrowser        
FontDialog          fdlg          fdlgFoot        
ColorDialog          cdlg          cdlgColor        
PrintDialog          pdlg          pdlgPrint        

3          WebControl          命名规范

数据类型          数据类型简写          标准命名举例        
AdRotator          adrt          Example        
Button             btn          btnSubmit        
Calendar          cal          calMettingDates        
CheckBox          chk          chkBlue        
CheckBoxList       chkl          chklFavColors        
CompareValidator   valc          valcValidAge        
CustomValidator     valx          valxDBCheck        
DataGrid           dgrd          dgrdTitles        
DataList           dlst          dlstTitles        
DropDownList       drop          dropCountries        
HyperLink          lnk          lnkDetails        
Image             img          imgAuntBetty        
ImageButton      ibtn          ibtnSubmit        
Label            lbl          lblResults        
LinkButton       lbtn          lbtnSubmit        
ListBox          lst          lstCountries        
Panel            pnl          pnlForm2        
PlaceHolder     plh          plhFormContents        
RadioButton          rad          radFemale        
RadioButtonList          radl          radlGender        
RangeValidator          valg          valgAge        
RegularExpression          vale          valeEmail_Validator        
Repeater                    rpt          rptQueryResults        
RequiredFieldValidator      valr          valrFirstName        
Table              tbl          tblCountryCodes        
TableCell          tblc          tblcGermany        
TableRow          tblr          tblrCountry        
TextBox            txt          txtFirstName        
ValidationSummary    vals          valsFormErrors        
XML                xmlc          xmlcTransformResults        

.NET中的命名规则

名称空间的命名 

命名名称空间的一般规则如下:
CompanyName.TechnologyName
这样,我们看到的名称空间应该是这样的:  
Microsoft.Office
PowerSoft.PowerBuilder                               

注意:这只是一个原则。第三方公司可以选择其它的名字。
避免用公司名称或其它著名品牌的名称作为名称空间的前缀,这样会造成两个公布的名称空间有同一个名称的可能性。
例如: 将微软提供的Office自动类命名为Microsoft.Office

使用Pascal大写方式,用逗号分隔逻辑成分。
例如:Microsoft.Office.PowerPoint

如果你的品牌使用的是非传统大写方式,那么一定要遵循你的品牌所确定使用的大写方式,即使这种方式背离了通常的名称空间大写规则。
例如:NeXT.WebObjects
ee.cummings

类和类成分的命名

类的命名原则是用名词或名词短语命名类,使用Pascal大写。减少类名中缩写的使用量。不要使用任何类前缀(比如C),不要使用带下划线的字符。
例如:public class FileStream {}
public class Button {}
public class String {}

CSS 类和ID的常用命名:

网站头部:    head/header(头部) top(顶部)导航:   nanv 导航具体区分:topnav(顶部导航)、mainnav(主导航)、mininav(迷你导航)、textnav(导航文本)、subnav(子导航/二级导航)
旗帜、广告和商标:logo(旗帜)、brand(商标)、banner(标语)
搜索:sreach(搜索)、sreachbox(搜索框)、sreachbtn(搜索按钮)、sreachinput(搜索输入框)
注册和登录:login(登录)、regsiter(注册)、userbox(用户名/通行证的文本框)、password(密码)
布局、分栏和框:   layout(布局)、bigdiv(大div)、leftdiv(左分栏)、rightdiv(右分栏)、leftfloat(左浮动)、rightfloat(右浮动)、mainbox()、subpage(子页面/二级页面)
页脚/底部:foot/footer(页脚/底部)、copyright(版权信息)、sitemap(网站地图)
其他:content(内容)、skin(皮肤)、title(标题)、from(表单)、pic(图片)、news(新闻)、shop(购物区)、 list(列表/清单)、newslist(新闻列表)、downloadlist(下载列表)、piclist(图片列表)、dropmenv(下拉菜单)、cor/corner(圆角)、homepage(首页)、crumb(当前位置导航)
实际上上面的id命名我会经常用大小写和_来区分,比如主导航就是MainNav,如果还有必要在区分就是MainNav_1,MainNav_2等等。也可以使用”类型+变量名称”的规则来命名,比如写一个红色字体的class,可以
.f_red {}(f是font 字体的缩写)。总之原则是:大小写、_、缩写,大大增强代码的可读性。

另外我还经常使用”in”的写法做子divd的命名,写法in+父div,这样可以避免前面命名过了后面div不知道怎么去命名。比如intop、inbox、infrom、inlogin等等。

详解IE的haslayout

展开/收缩

这篇文章太好了,我就征得译文作者的同意转到此处。
出处:http://old9.blogsome.com/2006/04/11/onhavinglayout

译者注:一篇很好的文章,很久以前在blog上就推荐过,这两天断断续续花了点时间翻译了一下,推荐读读。
英文原文在此。
http://www.satzansatz.de/cssd/onhavinglayout.htm
文中所有的 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.
(Dean Edwards)

4月16日修订的内容
将quirks模式这一部分单独移动到一篇文章中讲述。
添加:边缘裁切。
添加:收缩包围(shrink-wrapping)现象。

5月17日修订的内容
重写了了浮动元素旁边的元素这一部分。
部分章节小的修正:属性,有关内联级别元素,CSS hacks。
重新整理了部分章节的语言:定义,数据,问题种种,分析,清除浮动和自动扩展适应高度,绝对定位元素。

On having layout

本文修订中
当前版本:Rev. 7 2006–05–17
http://www.satzansatz.de/cssd/onhavinglayoutrev07-20060517.html
修订历史
http://www.satzansatz.de/cssd/layoutchangelog.html
各种语言版本
目录

介绍

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 http://msdn.microsoft.com/worksh … rties/haslayout.asp 为此被设为了 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>, <select>, <textarea>, <button> <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 http://www.brunildo.org/test/InlineBlockLayout.html
width: 除 “auto” 外的任意值
很多人遇到 layout 相关问题发生时,一般都会先尝试用这个来修复。
height: 除 “auto” 外的任意值
height: 1% 就在 Holly Hack 中用到。
zoom: 除 “normal” 外的任意值 (MSDN) http://msdn.microsoft.com/worksh … properties/zoom.asp
MS专有属性,无法通过校验。 不过 zoom: 1 可以临时用做调试。
writing-mode: tb-rl (MSDN) http://msdn.microsoft.com/worksh … ies/writingmode.asp
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 http://msdn.microsoft.com/worksh … rties/haslayout.asp可以用来检测一个元素是否拥有 layout:举个例子,如果它的 id 是“eid”,那么只要在 IE5.5+ 的地址栏里输入 javascript: alert(eid.currentStyle.hasLayout) 即可检测它的状态。
IE的 Developer Toolbar http://www.microsoft.com/downloa … &displaylang=en可以实时检查一个元素的当前样式;如果 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 http://www.communitymx.com/conte … age=2&cid=C37E0

复制内容到剪贴板

代码:

/* \*/   * html .gainlayout { height: 1%; }   /* */

可以让 IE5+ 的任意元素获得 layout,除了标准兼容模式 IE6 中的内联元素。
一般都很有效,除了在某些极少情况下,需要用 height:0 或者 1px 更好一些。
和 overflow: hidden 不相容,除非在 IE6 的标注兼容模式下(因为这时如果父元素没有定高,那么height: 1% 会被变回 height: auto)。

或者我们可以用 underscore hack:http://wellstyled.com/singlelang.php?lang=en&page=css-underscore-hack.html

复制内容到剪贴板

代码:

.gainlayout { _height: 0; }

另外,更具有向后兼容性的方法是使用 条件注释(conditional comments):http://msdn.microsoft.com/workshop/author/dhtml/overview/ccomment_ovw.asp

复制内容到剪贴板

代码:

<!--[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: 0 和 1px —— 并主张始终使用 height 除非它和别的什么东西冲突 (overflow: hidden)。对于取值,我们则倾向于避免 1% ,因为它可能会(虽然很少)引起一些问题。http://www.brunildo.org/test/relayout.html
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 就可以考虑使用了。

复制内容到剪贴板

代码:

<!--[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 和别的解决方法(特别是通过使用 height 或 width 属性的)往往对 IE Mac 来说是有害的,所以需要对其隐藏。更多的关于 IE Mac 相关的问题可以在 IE Mac, bugs and oddities pages http://www.l-c-n.com/IE5tests/找到。

MSDN 文档

MSDN 中涉及到 hasLayout 这个 MS 属性的地方寥寥无几,而具体解释 layout 和 IE 渲染模型之间关系的则少之又少。
在IE4的时候,除了未经绝对定位也未指定宽高的内联元素,几乎所有元素都有某种 layout(MSDN)。http://msdn.microsoft.com/worksh … mentandlocation.asp在这种早期的layout概念中,像 border, margin, padding 这些属性被称作“layout属性”,它们是不能应用到一个简单的内联元素上的。换句话说,“拥有layout”就可以粗略理解成:“可以拥有这几个属性”。
MSDN 上仍然使用 layout 属性这种说法, 只是含义变了,它们和拥有 layout 的元素已经没有什么关系了。在 IE5.5 中方才引入了 MS 的这个专有属性 hasLayout,http://msdn.microsoft.com/worksh … rties/haslayout.asp也只是某种内部的标志位而已。
在 IE5.5 中,MSHTML Editing Platform(即可以通过设置来允许用户实时编辑、拖动 layout 元素以及调整其尺寸等)的文档中描述了三个和 layout 相关的重要特性:
如果一个 layout 元素中有内容,内容的排版布局将由它的边界矩形框决定。
拥有 layout 的意思基本上就是表示某元素是一个矩形。
从内部来说,拥有 layout 意思就是一个元素将自己负责绘制其内部内容。

(Editing Platform) http://msdn.microsoft.com/librar … mshtmleditplatf.asp

和 layout 自身相关的内部工作机制直到2005年8月才有相应文档描述,当时由于 The Web Standards Project http://www.webstandards.org/和微软的特别工作小组的原因,Markus Mielke [MSFT] 打开了深入讨论的大门:
一般来说,在 Internet Explorer 的 DHTML 引擎中,元素是不对自己的位置安排负责的。虽然一个 div 或者一个 p 元素都在源码中有一个位置,在文档流有一个位置,但是它们的内容却是由它们最近的一个 layout 祖先(经常是 body)控制安排的。这些元素依赖它们祖先的 layout 来为他们处理诸如决定大小尺寸和测量信息等诸多繁重的工作。

(HasLayout概述)http://msdn.microsoft.com/library/default.asp?url=/library/en-us/IETechCol/cols/dnexpie/expie20050831.asp

分析

我们的分析试图解释在已知案例下发生了什么事情,这种分析也应该可以作为未知案例下的指导。但我们这种试图利用种种测试案例投石探路的黑箱测试方法,是注定无法消除黑箱的神秘感的——我们无法回答“为什么”的问题。我们只能去尝试了解整个“hasLayout”模式的工作框架,以及它会怎样影响网页文档的渲染。因此,最终我们只能提供一些指导方针(而且只能是指导方针,而不是绝对的解决方案)。
我们认为他们所指的是一个小窗体。一个 layout 元素的内部内容是完全独立的,而且也无法影响其边界外的任何内容。
而 MS 属性 layout 只是某种标志位:一旦它被设定,这个元素就会拥有 layout“特性”,这包括体现在其自身以及其非 layout 孩子元素身上的特殊性能——比如浮动和层叠等。
这种独立性也许正可以解释为什么 layout 元素通常比较稳定,而且它们可以让某些 bug 消失。这种情况的代价有二,一是偏离了标准,二是它没有考虑到今后可能因此出现的 bug 和问题。
MS 的“页面”模式,从符号学角度考虑,可以看做是由很多互不相关的小的区块构成,而 HTML 和 W3C 的模式则认为“页面”模式应该是叙述完备的,故事性的相关信息区块构成的。

各种情况的详细说明

清除浮动和自动扩展适应高度
浮动元素会被 layou 元素自动包含。这是很多新手经常遇到的问题:在 IE 下完成的页面到了标准兼容浏览器下所有未清除的浮动元素都伸出了其包含容器之外。
Containing Floats http://www.complexspiral.com/publications/containing-floats
how to clear floats without structural markup http://positioniseverything.net/easyclearing.html

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

在IE中,一个浮动元素总是“隶属于”它的 layout 包含容器。而后面的元素会受这个 layout 包含容器影响而不是这个浮动元素影响。
这个特性和IE6的那个自动扩展以适应内部内容宽度的特性,都可以看成是受这个规则影响的:“由它的边界矩形框决定”。
更糟的问题:clear 无法影响其 layout 包含容器之外的 float 元素。如果依赖这个 bug 在 IE 中布局的页面要转到标准兼容浏览器中,只有全部重做。
IE 的自动包含浮动元素也是经常需要的效果,它在其他浏览器中也可以达到:参考我们的 “和 CSS 规范类似的地方” 这一部分来了解一下包含浮动元素的相关内容。
浮动元素旁边的元素
当一个块级元素紧跟在一个左浮动元素之后时,它应该——作为一个块级元素——忽略这个浮动元素,而它的内容则应该因这个浮动元素而移位:一个紧跟在左浮动元素后的块级元素内的文字内容,应该沿着浮动元素的右边顺序排列并会(如果它的长度超过浮动元素)继续排列到浮动元素下方。但是如果这个块级元素有 layout,比如由于某种原因被设置了宽度,那么这整个元素则会因浮动元素而移位,就好像它自己也是一个浮动元素一样,因此其中的文字就不再环绕这个左浮动元素了(而会形成一个矩形区域,保持在它的右边。)
在 IE5 中一个块级元素的百分比宽度是基于浮动元素旁边的剩余空间计算的,而在 IE6 中则是依照整个父块级元素的可用空间计算的。所以在 IE6 中设置 width: 100% 会导致某种浮动元素旁边的溢出现象,于是各种布局问题也会因此而来。
一些关于浮动块旁边的 hasLayout 块的测试案例:
by using width http://dev.l-c-n.com/IEW2-bugs/float-layout.php
by using min-width (IE 7) and zoom (IE 6) http://dev.l-c-n.com/IEW2-bugs/float-adjecant.php

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

根据规范所述,浮动元素应该与其后的盒子交织在一起。而对于没有交叉的二维空间中的矩形而言这是无法实现的。
如果谁真的需要向 IE 的这种不当行为屈服,那么如何让标准兼容浏览器中的盒子也有类似行为——即类似于 layout 盒子会自动“收缩”而给其前置的浮动元素让出空间的行为——就是一个问题了。我们给出的方法是跟着一个浮动元素创建一个新的块级格式化范围(block formatting context),这在我们的“和 CSS 规范类似的地方” 有讨论。
可以(再次)访问下面这个页面:
three pixel text-jog http://positioniseverything.net/explorer/threepxtest.html

我们可以看到跟在一个浮动元素后的 layout 元素不会显示这个3px间隙的 bug,因为浮动元素外围的3px硬边无法影响一个 layout 元素的内部内容,所以这个硬边将整个 layout 元素右推了3px。好比一个防护罩,layout 可以保护其内部内容不受影响,但是浮动元素的力量却将整个防护罩推了开来。
列表
无论是列表本身(ol, ul) 还是单个的列表元素(li),拥有 layout 后都会影响列表的表现。不同版本 IE 的表现又有不同。最明显的效果就体现在列表符号上(如果你的列表自定义了列表符号则不会受这个问题影响)。这些符号很可能是通过某种内部机制附到列表元素上的(通常是附着在它们外面)。不幸的是,由于是通过“内部机制”添加的,我们无法访问它们也无法修正它们的错误表现。
最明显的效果有:
列表获得 layout 后,列表符号会消失或者被放置在不同的或者错误的位置。

有时它们又可以通过改变列表元素的边距而重新出现。这看起来似乎是以下事实导致的结果:layout 元素会试图裁掉超出其边界的内部内容。
列表元素获得 layout 之后,会有和上面一样的问题出现,更多参考 (extra vertical space between list items)http://www.brunildo.org/test/IEWlispace.php

进一步又有一个问题就是(在有序列表中)任何具有 layout 的列表元素似乎都有自己独立的计数器。比如我们有一个含五个列表元素的有序列表,只有第三个列表元素有 layout。我们会看到这样:
1… 2… 1… 4… 5…
此外,如果一个有 layout 的列表元素跨行显示时,列表符号会底部对齐(而不是按照预料的顶部对齐)。
以上某些问题还是无法解决的,所以如果需要列表符号的时候最好避免让列表和列表元素获得 layout。如果需要限定尺寸,最好给别的元素设定尺寸,比如给整个列表外面套一个元素并设定它的宽度,又或者比如给每个列表元素中的内容设定高度等等。
另一个IE中列表的常见问题出现在当某个 li 中的内容是一个 display: block 的锚点(anchor)时。在这种情况下,列表元素之间的空格将不会被忽略而且通常会显示成额外的一行夹在每个 li 之间。一种避免这种竖直方向多余空白的解决方法是赋予这些锚点 layout。这样还有一个好处就是可以让整个锚点的矩形区域都可以响应鼠标点击。
表格
table 总是有 layout 的,它总表现为一个已定义宽度的对象。在IE6中,table-layout: fixed http://msdn.microsoft.com/worksh … ies/tablelayout.asp通常和一个宽度设为100%的表格相同,同时这也会带来很多问题(一些计算方面的错误)。另外在IE5.5和IE6的quirks模式下还有一些别的需要注意的情况。http://dev.l-c-n.com/tables_2/
相对定位元素(r.p.)
注意,由于 position: relative 并不触发 hasLayout,所以很多诸如内容消失或错位的渲染错误就会因此而起。这些现象可能会在刷新页面、调整窗口大小、滚动页面、选中内容等情况下出现。原因是 IE 在据这个属性对元素做偏移处理时,却似乎忘了发出信号让其 layout 孩子元素进行“重绘”(而如果是一个layout元素,那么在其重绘事件的信号链中,这个传给其孩子的信号是会正常发出的)。
r.p. parent and disappearing floated child http://www.satzansatz.de/cssd/rpfloat.html
disappearing list-background bug http://positioniseverything.net/explorer/ie-listbug.html

以上是一些相关问题的描述。作为经验之谈,相对定位一个元素时最好给予其 layout。再有,我们也需要检查拥有这种结构的父元素是否也需要 layout 或者position: relative亦或二者都需要,如果涉及到浮动元素这点就十分重要。
绝对定位元素(a.p.):
包含区块,什么是包含区块?
理解 CSS 的包含区块概念很重要,它回答了绝对定位元素是相对哪里定位的问题:包含区块决定了偏移起点,包含区块定义了百分比长度的计算参考。
对于绝对定位元素,包含区块是由其最近的定位祖先决定的。如果其祖先都没有被定位,那么就使用初始包含区块 html。
通常情况下我们会用 position: relative 来设定任意包含区块。这就是说,我们可以让一个绝对定位元素所参考的原点和长度等不依赖于元素的排列顺序,这可以满足诸如“内容优先”这种可访问性概念的需要,也可以给复杂的浮动布局带来方便。
但是由于 layout 概念的存在,这种设计理念的效果在IE中就要打个问号了:因为在IE中绝对定位只有当其包含元素拥有 layout 时才会计算正确,而且绝对定位元素的百分比宽度参考也搞错了对象。这里 IE5 和 IE6 的行为不同但都有问题。IE7b2 的行为就要好很多,虽然有些小地方还是有错误。总之尽可能的让绝对元素的包含区块拥有 layout,而且尽量让其就是绝对定位元素的父级元素(也就是说这个包换元素和绝对定位元素之间没有绝对定位元素的别的祖先了)。
假设一个无 layout 的父元素被相对定位了——我们就得给它赋予 layout 才能使偏移量起作用:
Absolutely Buggy II http://www.positioniseverything.net/abs_relbugs.html

假设一个未定位的父元素需要特定尺寸,而且页面设计是基于百分比宽度的——我们就可以放弃这个想法了,因为浏览器支持不佳:
absolutely positioned element and percentage width http://www.satzansatz.de/cssd/tmp/apboxpercentagewidth.html
滤镜
MS专有的滤镜属性 filter http://msdn.microsoft.com/workshop/author/filter/filters.asp是只适用于 layout 元素的。有些滤镜扩展了对象的边界。它们会显示出自身特有的缺陷。http://www.satzansatz.de/cssd/tmp/alphatransparency.html
对已渲染元素的重排(re-flow)
当所有元素都已渲染完成时,如果有一个因鼠标经过而引起的变化产生(比如某个链接的 background 有变化),IE会对其 layout 包含区块进行重排。有时一些元素就会因此被排到了新的位置,因为当这个鼠标经过发生时,IE已经知道了所有相关元素的宽度、偏移量等数据了。这在文档首次载入时则不会发生,那时由于自动扩张的特性,宽度还无法确定。这种情况会导致在鼠标经过时页面出现跳变。
Jump on :hover http://www.satzansatz.de/cssd/pseudocss.html#hoverjump
quirky percentages: the reflow http://www.positioniseverything.net/explorer/percentages.html

这些和重排问题相关的 bug 会给百分比边距和补白使用较多的流动布局带来不少麻烦。
背景原点
MS专有的这个 hasLayout 还会影响背景的定位和扩展。比如,根据 CSS 规范,http://www.w3.org/TR/CSS21/colors.html#q2background-position: 0 0 应该指元素的“补白边缘(padding edge)”。而在 IE/Win 下,如果 hasLayout = false 则指的是“边框边缘(border edge)”,当 hasLayout=true 时指的才是补白边缘:
Background, Border, hasLayout http://www.brunildo.org/test/BackgroundBorderLayout.html

边距重叠
hasLayout 会影响一个盒子和其子孙的边距重叠。根据规范,一个盒子如果没有上补白和上边框,那么它的上边距应该和其文档流中的第一个孩子元素的上边距重叠:
Collapsing Margins http://www.w3.org/TR/CSS21/box.html#collapsing-margins
Uncollapsing Margins http://complexspiral.com/publications/uncollapsing-margins

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

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

在页面内使用键盘浏览:探索中
当使用 tab 在页面中浏览时,如果进入了一个页内链接(in-page link),那么接下来再按的 tab 键就不会正常继续了:
hasLayout Property Characterizes IE6 Bug http://jimthatcher.com/news.htm#haslayout
Keyboard Navigation and Internet Explorer http://juicystudio.com/article/ie-keyboard-navigation.php
tab 键会把用户带到(这通常是错误的)其最近的 layout 祖先中的第一个目标(如果这个祖先是由 table, div, span 或某些别的标签构成)。

收缩包围(shrink-wrapping)现象
给已经有 width: auto 的元素添加某些属性会导致它们在计算自身宽度时使用一种收缩包围的算法。比如这些属性 float: left|right, position: absolute|fixed, display: table|table-cell|inline-block|inline-table.
这些属性造成的现象在IE/Win中也存在,当然这是只对那些它支持的属性而言。但是当一个应该收缩包围的元素中包含一个拥有“layout”的块级元素时,在绝大多数情况下,这个孩子元素的宽度会尽可能地扩展而与其中包含的内容无关,同时也阻止了父元素的收缩包围现象。
例子: http://dev.l-c-n.com/IEW2-bugs/shrinkwrap.php
一个浮动的纵向导航无序列表并没有收缩包围,因为其中的链接为了消除列表的多余空白bug并扩展可点击区域而拥有了 layout:a {display: block; zoom: 1;}。

这时收缩包围现象只有在以下情况仍然有效:拥有 layout 的孩子元素同时也被赋予了一个特定宽度,或者这个孩子元素本身也是一个具有收缩包围特性的元素,比如浮动元素。
边缘裁切
通常而言,当一个盒子包含了诸如伸出其边缘的内容这种更复杂的结构时,这个容器就经常需要“hasLayout”来避免一些渲染错误。但使用这种常用方法又会在边界处理时左右为难,因为一个获得“layout”的元素会变成某种自封闭的盒子。
内部的内容盒子会被裁切,比如使用负边距向外移动时。
Clipping of negative margined blocks in a hasLayout container http://dev.l-c-n.com/IEW2-bugs/min-width-clip.php

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

堆叠,分层和 layout

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

两种堆叠模式虽互不相容,但却共存于IE的渲染引擎中。经验之谈:调试的时候,两种情况都要考虑到。我们可能会有规律地在下拉菜单或者类似的复杂菜单中看到相关问题,因为它们往往牵涉到堆叠,定位和浮动等诸多令人头疼的问题。给那些 z-index 定位的元素 layout 是一种可能的修正方法,不过也不限于此,这里只是提醒一下。
混乱的 contenteditable
如果给一个 HTML 标签设定 contenteditable=true 属性,比如,将会允许对该元素以及其 layout 子元素进行实时的编辑、拖动改变尺寸等操作。你可以把这属性用在浮动元素或者一个有序列表中的 layout 列表元素上看看效果。
为了对元素进行操作(编辑它们),“contenteditable”和“hasLayout”为那些 hasLayout 返回 true 的元素引入了一套单独的堆叠顺序。
Editing Platform http://msdn.microsoft.com/librar … mshtmleditplatf.asp继承了 layout 概念,对 layout 的误解多是因 contenteditable 而起即可作为证明(那些某种程度上集成了IE编辑引擎的应用软件多暗含着对layout概念的某种强制向后兼容性)。
More on contenteditable http://annevankesteren.nl/2005/07/more-contenteditable

和 CSS 规范类似的地方

你的 MSIE 页面在别的浏览器中一团糟?我们可没必要让这种事情发生。如果使用恰当,任何好的浏览器都能摆平 MSIE 的页面——只要你使用一些正确的 CSS。
利用 hasLayout 和“新的块级格式化范围”http://www.w3.org/TR/CSS21/visuren.html#q15之间的细微相似之处,我们可以有几种方法在标准兼容浏览器中重新实现 hasLayout 的“包含浮动元素”http://www.w3.org/TR/CSS21/visudet.html#root-height效果,和一些“浮动元素旁边的元素”http://www.w3.org/TR/CSS21/visuren.html#floats所特有的效果。
Reverse engineering series http://www.gunlaug.no/contents/wd_example_01.html
Simulations http://dev.l-c-n.com/IEW/simulations.php

Quirks 模式

关于这种渲染模式的的信息,请参考我们的 quirks 模式 http://www.satzansatz.de/cssd/quirksmode.html章节。
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‛)

本文创建于2005年6月30日,最后一次修改于2006年4月2日。
编者:
Holly Bergevin http://positioniseverything.net/
Ingo Chao http://www.satzansatz.de/css.html
Bruno Fassino http://www.brunildo.org/
John Gallant http://positioniseverything.net/
Georg Sørtun http://www.gunlaug.no/
Philippe Wittenbergh http://emps.l-c-n.com/

特别致谢给予此项目支持的:
Dean Edwards, and Molly ‚the cat‛

各种语言版本:
Original(English)
Brazilian Portuguese by          Mauricio Samy Silva
中文版本 by old9
Italian by Gabriele Romanato

相关讨论:
dean.edwards.name/weblog/

[url=mailto:spam.layout@satzansatz.de]联系作者:[/url]

版权说明:
本文基于创作共用协议发布。

目录

介绍
hasLayout —— 定义
术语
问题种种
Layout 从何而来
默认 layout 元素
属性
有关内联级别元素
脚本属性 hasLayout
CSS hacks
Hack整理
关于 IE Mac 的小问题
MSDN文档
分析
各种情况的详细说明
清除浮动和自动扩展适应高度
浮动元素旁边的元素
列表
表格
相对定位元素(r.p.)
绝对定位元素(a.p.):包含区块,什么是包含区块?
滤镜
对已渲染元素的重排(re-flow)
背景原点
边距重叠
块级别的链接
在页面内使用键盘浏览:探索中
收缩包围(shrink-wrapping)现象
边缘裁切
堆叠,分层和 layout
混乱的 contenteditable
和 CSS 规范类似的地方
Quirks 模式
Layout —— 结论
拥有 layout —— 另外一个引擎?
不可消除的 bug

>>
后台管理 github RSS 微博 简历
RSS订阅