• 高质量CSS之一 DTD、怪异模式、如何组织CSS


    怪异模式和DTD

     
           为了确保向后兼容,浏览器厂商发明了标准模式和怪异模式这两种方法来解析网页。在标准模式中,浏览器根据规范表现页面;而怪异模式通常模拟老式浏览器(比如Microsoft IE 4Netscape Navigator 4)的行为以防止老站点无法工作。这两种模式的差异比较大,比较典型的就是IE对盒模型的解析:在标准模式中,网页元素的宽度是由padding、border、width三者的宽度相加决定的;而在怪.异模式中,width本身就包括了padding和border的宽度。此外,标准模式下块级元素的经典居中方法——设定width,然后margin.left:auto,margin-right:auto——在怪异模式下也无法正常工作。
     
           同样的代码,在怪异模式和标准模式下的表现很可能相差甚远。因为发明怪异模式的目的就是为了兼容老式浏览器下的代码,它的很多解析方式是不符合标准的。所以,一般情况下,我们应该避免触发怪异模式,应选用标准模式。
     
     
            怪异模式是如何被触发的呢?与DTD有关。DTD全称Document Type  Definition,即义档类型定义。 DTD是一种保证HTML文档格式正确的有效方法,可以通过比较HTML文档和DTD文件来看文档是否符合规范,以及元素和标签使用是否正确。一个DTD文档包含元素的定义规则、元素间关系的定义规则、元素可使用的属性、可使用的实体或符号规则。
     
     
        在网页中最常用的DTD类型包括代码清单1中所示的4种。
     
     
        1、用于HTML 4.01的严格型
     
    1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
     
       
        2、用于HTML 4.01的过渡型
    1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
       
     
        3、用于XHTML 1.0的严格型
    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
       
     
     
        4、用于XHTML 1.0的过渡型
       
    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 


     

           按照W3C的标准,我们需要在HTML的最开始声明文件的DTD类型。如果漏写DTD声明,Firefox仍然会按照标准模式来解析网页,但在IE中(包括IE 6、IE 7、IE 8)就会触发怪异模式。在table布局时代,盒模型和CSS我们都接触得比较少,所以DTD声明并不是很重要,被我们忽视了。到了CSS布局时代,DTD的声明就变得非常重要了。为了避免怪异模式给我们带来不必要的麻烦,我们要养成书写DTD声明的好习惯。
     
     
     

    如何组织CSS

            我们应用CSS的能力应该分成两部分:一部分是CSS的API,重点是如何用CSS 控制页面内元素的样式;另一部分是CSS框架,重点是如何对CSS进行组织。前者属于基础部分,这部分的能力是用“对”和“错”来评判的,比如说,要把文字设置为红色,只能用color:red:这样的写法是对的,其他任何写法都是错的,不存在“好”和“坏”的区别,只有“对”和“错”。 CSS的API并不多,掌握到“会用”的程度并不难,但如果要用得“好”,我们需要在前者的基础上更进一步,研究如何组织CSS,如何组织CSS是一个见仁见智的问题,不是用“对”和“错”来评判的,我们更可能会用“好”、“比较好’’、“很烂”、“非常棒”这样的字眼来评判。
     
     
          正因为见仁见智,所以如何组织CSS可以有多种角度,例如按功能划分:将控制字体的CSS集中在font.CSS文件里,将控制颜色的CSS集中在color.CSS文件里,将控制布局的CSS放在layout.CSS文件里;或者按区块划分:将头部的CSS放在head.CSS里,底部放在foot.CSS里,侧边栏放在sidebar.css里,主体放在main.CSS里。不同角度的组织方法都有自己的道理,也有自己的优点和缺点。
     
          这里推荐笔者最喜欢的一种组织CSS的方法:base.css + common.css + page.CSS。将网站内的所有样式,按照职能分成三大类:base、common和page。在一般情况下,任何一个网页的最终表现都是由这三者共同完成的。这三者不是并列结构,而是层叠结构,如图1所示。
    base.css + common.css + page.CSS层叠结构


     

        1base层

           这一层位于三者的最底层,提供CSS reset功能和粒度最小的通用类——原子类。这一层会被所有页面引用,是页面样式所需依赖的最底层。这一层与具体UI无关,无论何种风格的设计都可以引用它,所以base层要力求精简和通用。如果将用CSS控制页面样式比喻为建房子,这一层的核心职能是为房子打好地基(CSS reset),并将建房用的砖块(原子类)准备充足。因为几乎所有的房子都要打地基,也都需要砖块,所以
    base层具有高度可移植性,不同设计风格的网站可以使用同一个base层。因为这一层的内容很少,所以可以简单地放在一个文件里,例如base.CSS。
     
        base层相对稳定,基本上不需要维护。
     
     
     

        2common层

         这一层位于中间,提供组件级的CSS类。提到组件,就不得不提“模块化”。“模块化”可以从样式和行为两个层面来考虑,与common层相关的是样式的模块化。我们可以将页面内的元素拆分成一小块一小块功能和样式相对独立的小“模块”,这些“模”有些是很少重复的,有些是会大量重复的,我们可以将大量重复的“模块”视为一个组件。我们从页面里尽可能多地将组件提取出来,放在common层里。common层就相当于MVC模式中的M(Model,模型)。为了保证重用性和灵活性,M需要尽可能将内部实现封装,对可能会经常变化的部分提供灵活的接口。关于common层的技巧,详4.4节。(引用)
     
        common层就像建房时用到的门窗,不同风格的房子会用到不同样式的门窗,各个房间用到的门窗的数量和位置可以不同,但样式相同。门窗有自己的小元件,比如玻璃、门闩、门框、门板、钥匙孔等。门窗可以整体移动、增减,但门窗本身的构造是相对稳定的。不同风格的房子就好比不同风格的网站,房子选用的门窗就好比这个网站选用的UI组件。门窗最好与整个房子的风格保持一致,同样,网站最好让UI组件的风格保持相同。 UI组件是网站中的单位,在网站内部可以高度重用,但不同的网站可能会用不同的UI组件。
     
     
          所以,common层是网站级的,不同的网站有不同的common层,同一个网站只有一个common层。 common层是放在一个common.CSS文件里,还是按照功能划分放在诸common_form.CSS、common_imagelist.css的多个文件里,需要根据网站规模来决定。在团队合作中,common层最好由一个人负责,统一管理。
     
     

         3page层

         网站中高度重用的模块,我们把它们视为组件,放在common层;非高度重用的模块,可以把它们放在page层。page层位于最高层,提供页面级的样式。同样以建房了为比喻,page层就好比是房间内的装饰画,不同的房间张贴的装饰画各不相同。它不像砖块,所有房子都相同:也不像门窗,同一房子里都相同。它对重用性没有要求,可根据各个房间布置的需要任意张贴。
     
        page层是页面级的,每个页面都可能会有自己的page层CSS。 page层的文件可以<style type="text/CSS">标签内置于页面中,但这么做没有将样式彻底从HTML文件中分离出来。也可以根据页面写在诸如page1.css、page2.SSS、page3.CSS的文件里,这样做可以将样式很好地从HTML中分离出来,但可能会产生大量CSS文件,有些CSS文件可能非常小,带来维护上的麻烦。如果网站规模不会过于庞大,笔者建议将网站内所


     

     
    page层的代码放在一个page.CSS文件里,根据页面配上注释,分块书写,便于维护,如代码清单2所示。
     
        代码清单2 page.css的注释
     
    1. /*首页*/ 
    2. .test{}  
    3. .test2{}  
    4.  
    5. /*关于我们*/ 
    6. .test3{}  
    7. .test4{}  
    8.  
    9. /*联系我们*/ 
    10. .test5{}  
    11. .test6{} 
         这么做可能会带来些冗余,比如,“首页”的CSS文件里带有“关于我们”、“联系我们”页的page层CSS文件,而这些对首页的样式毫无影响。对于文件过于分散和集中的问题并没有完美的解决办法,我们需要根据实际情况做些适当的折
    中。比起让page层的CSS文件过于繁多和零散,把它们集中在一个文件中更便于维护,且便于浏览器缓存,浏览网站时只有首页的下载时间较长,浏览其他页面时反而较快。当然,page.CSS还是应当越精简越好,能用base层和common层的CSS解决的,就尽量不要用到page层。
     
     
        base层基本上不需要维护,common层修改的幅度不会很大,通常只由一个人负责维护,但到了page层,代码可能由多人开发,如何避免冲突是个需要注意的问题。通常我们通过命名规则来避免这种冲突。(引用)
     
     
     

    推荐的base.CSS

        base层是高度重用的基础层,它提供的通用类是否够用直接关系到网站的开发效率CSS文件的总大小,对于一个网站来说,base层设计是否良好非常重要。因为它具有无视美工设计,适用于任何网站的特点,所以不同于common层和page层,可脱离具体网站来讲解。下面是一个笔者推荐使用的base.css代码,如代码清单3所示。
    1.  
    2.  
    3.         /*CSS reset*/ 
    4.        body, div, dl,dt,dd, ul,ol,li,h1,h2,h3, h4,hS,h6,pre,form,fieldset,input, textarea,p,blockquote, th, td {margin:O;padding:O;}  
    5.         table {border-collapse:collapse;border-spacing:O;}  
    6.         fieldset, img {border:O}  
    7.         address,caption, cite, code,dfn, em, strong, th,var {font-style:normal;font- weight:normal}  
    8.        ol,ul {list-style:none}  
    9.        caption, th {text-align:left}  
    10.        hl,h2,h3,h4,h5,h6 (font-size:lOO%;font-weight:normal}  
    11.        q:before,q:after {content:''}  
    12.        abbr,acronym { border:0 }  
    13.          /*文字排版*/ 
    14.         .fl2{font-size:12px}  
    15.         .fl3{font-size:13px}  
    16.         .f14{font-size:14px}  
    17.         .fl6{font-size:16px}  
    18.         .f20{font-size:20px}  
    19.         .fb{font-weight:bold}  
    20.         .fn{font-weight:normal}  
    21.         .t2{text-indent:2em}  
    22.         .lh15O{line-height:l5O%}  
    23.         .lh18O{line-height:l8O%}  
    24.         .lh200{line-height:200%}  
    25.         .unl{text-decoration:underline;}  
    26.         .no unl{text-decoration:none;}  
    27.         /*定位*/ 
    28.         .tl{text-align:left}  
    29.         .tc{text-align:center}  
    30.         .tr{text-align:rlght}  
    31.         .bc{margin-left:auto;margin-right:auto;}  
    32.         .fl{float:left;display:inline}  
    33.         .fr{float:right;display:inline}  
    34.         .cb{clear:both}  
    35.         .cl{clear:left}  
    36.         .cr{clear:right}  
    37.         .clearfix:after{content:".";display:block;height:O;clear:both;visibilityhidden}  
    38.         .clearfix{display:inline-block}  
    39.         * html .clearfix{height:1%}  
    40.         .clearfix {display:block}  
    41.         .vm{vertical-align:middle}  
    42.         .pr{position:relative}  
    43.         .pa{position:absolute}  
    44.         .abs-right{position:absolute;right:0}  
    45.         .zoom{zoom:l}  
    46.         .hidden{visibility:hidden}  
    47.         .none{display:none}  
    48.         /*长度 高度*/ 
    49.         .w10{width:10px}  
    50.  
    51.    
    52.  
    53. .w20{width:20px}  
    54. .w30{width:30px}  
    55. .w40{width:40px}  
    56. .w5O{width:50px}  
    57. .w60{width:60px}  
    58. .w70|width:70px}  
    59. .w8O{width:80px}  
    60. .w90{width:90px}  
    61. .w1OO{width:lOOpx}  
    62. .w200{width:200px}  
    63. .w250{width:250px}  
    64. .w300{width:300px}  
    65. .w400{width:400px}  
    66. .w500{width:500px}  
    67. .w600{width:600px}  
    68. .w700|width:700px}  
    69. .w800{width:800px}  
    70. .w{width:l00%}  
    71. .h50{height:50px}  
    72. .h80{height:80px}  
    73. .h1OO{height:1OOpx}  
    74. .h200{height:200px}  
    75. .h{height:100%}  
    76. .m1O{margin:1Opx}  
    77. .m15{margin:15px}  
    78. .m30{margin:30px}  
    79. .mt5{margin-top:5px}  
    80. .mt10{margin-top:10px}  
    81. .mt15{margin-top:15px}  
    82. .mt20{margin-top:20px}  
    83. .mt30{margin-top:30px}  
    84. .mt5O(margin-top:50px}  
    85. .mt100{margin-top:100px}  
    86. .mb5{margin-bottom:5px}  
    87. .mb10(margin-bottom:10px}  
    88. .mbl5{margin-bottom:15px}  
    89. .mb20{margin-bottom:20px}  
    90. .mb30(margin-bottom:30px}  
    91. .mb50{margin-bottom:50px}  
    92. .mb100{margin-bottom:100px) .ml5{margin-left:5px}  
    93. .ml10{margin-left:10px}  
    94. .ml15(margin-left:15px}  
    95. .ml20(margin-left:20px}  
    96. .ml30(margin-left:30px}  
    97. .ml50(margin-left:50px}  
    98. .ml100{margin-left:100px}  
    99. .mr5{margin-right:5px}  
    100. .mr10(margin-right:10px}  
    101. .mr15(margin-right:15px}  
    102. .mr20{margin-right:20px}  
    103. .mr30{margin-right:30px}  
    104.  
    105.    
    106.  
    107.    
    108. .mr50{margin-right:50px}  
    109. .mr100{margin-right:100px}  
    110. .p10{padding:10px;}  
    111. .p15{padding:15px;}  
    112. .p30{padding:30px;}  
    113. .pt5{padding-top:5px}  
    114. .pt10{padding-top:10px}  
    115. .pt15{padding-top:15px}  
    116. .pt20{padding-top:20px}  
    117. .pt30{padding-top:30px}  
    118. .pt50{padding-top:50px}  
    119. .pb5{padding-bottom:5px}  
    120. .pb10{padding-bottom:10px}  
    121. .pb15{padding-bottom:15px}  
    122. .pb20{padding-bottom:20px}  
    123. .pb30{padding-bottom:30px}  
    124. .pb50{padding-bottom:50px}  
    125. .pb100(padding-bottom:100px} .p15{padding-left:5px}  
    126. .pl10{padding-left:10px}  
    127. .pl15{padding-left:15px}  
    128. .pl20{padding-left:20px}  
    129. .pl30{padding-left:30px}  
    130. .pl50(padding-left:50px}  
    131. .pl100{padding-left:100px}  
    132. .pr5{padding-right:5px}  
    133. .pr10{padding-right:10px}  
    134. .prl5{padding-right:15px}  
    135. .pr20(padding-right:20px}  
    136. .pr30{padding-right:30px}  
    137. .pr50{padding-right:50px}  
    138. .pr100{padding-right:100px}  


      

        这个base.CSS文件可以分为两大部分:CSS reset和通用原子类。
     
     
        什么是CSS reset呢?HTML标签在浏览器里有默认的样式,例如p标签有上下边距,strong标签有字体加粗样式,em标签有字体倾斜样式。不同浏览器的默认样式之间也会有差别,例如ul默认带有缩进的样式,在IE下,它的缩进是通过margin实现的,而在Firefox下,它的缩进却是由padding实现的。在切换页面的时候,浏览器的默认样式往往会给我们带来麻烦,影响开发效率。现在很流行的解决办法是一开始就将浏览器的默认样式全部去掉,更确切地说,应该通过重新定义标签的样式,“覆盖”掉浏览器提供的默认样式,这就是CSS reset。
     
     
         关于CSS reset,有一种写法相信大家都很熟悉,即“* {margin:0; padding:0;}”,因为浏览器默认的边距是最影响CSS布局的,所以很多人都会在CSS文件的最开始加入这么一句代码。这应该是最早的CSS reset了。但一方面它并不完善,更好的写法还应该去掉ol和ul的列表样式,th的加粗,caption的居中,h系列标签的加粗、字号等;
     
         另一方面它本身也存在性能问题,“*”是个通配符,表示所有标签,其中包括大量生僻标签和为向前兼容而留下来的淘汰标签。
     
     
         更好的写法是将常用的标签显式地罗列出来,避免使用“*”,例如"body,div,dl, dt, dd, ul, ol, li, hi, h2, h3, h4, h5, h6, pre, form, fieldset, input, textarea,p,blockquote,th,td{margin:0;padding:0} " 。有些工程师虽然使用了这种方法,但他们除了margin和padding,还喜欢将color、font-size之类的样式写进去,例如“body, div, dl, dt, dd, ul, ol,li,hi, h2, h3, h4, h5, h6, pre, form,fieldset, input, textarea,p,blockquote, th, td{margin:0;padding:0;color:#000;font-size:12px;}", 这种做法非常不好,因为CSS的很多样式是具有继承性的,但继承性的权重非常低,比标签选择符的权重更低,(引用) 这种写法会破坏CSS的继承性,设置样式时会额外增加很多代码。
     
     
         代码清单3所示的base.css中,CSS reset部分来自于YUI(雅虎的前端框架,详见:http://developer.yahoo.com/yui/),这是段很成熟的代码,推荐大家都使用它来进行CSS reset。
     
         通用原子类是一系列常用的基本类,包括:文字、定位、长宽和边距。除了极少数特殊类,绝大部分通用原子类都只包含一句CSS,例如“.fl2{font-size: 12px)"。通用原子类具有两个特点:“通用性”和“原子性”。 “通用性”表现在它们是网站最常用的类,任何页面都可以随意使用它们,“原子性”表现存它们是最基础的样式,一个类只设置一个样式,不可再分。由于它们具有通用性,所以在保证命名有语义的前提下,命名应尽量简短,方便调用。例如“fontSize 12"可以写成“f12’,“paddingTop20可以写成“pt20.这样既方便记忆又方便调用。关于CSS命名的更多问题(引用)
     
     
        通用原子类里有几个类比较特殊,需要特别说明一下。
     
        口“.fl”类和“.fr”类。这两个类,除了设置float:left和float:right之外,还设置display:inline.熟悉CSS Bug的工程师应该一眼就能认出其作用——解决IE 6的双外边距Bug。在IE 6下,如果对元素设置了浮动,同时又设置了margin-left
    或者margin-right,margin值会加倍。例如,设置margin-left: 10px在IE 6下会显示为margin-left:20px。解决这个Bug的办法就是设置display:inline。我们在设计通用原子类时,将display:inline直接添加到“.fl和“.fr”类里,可以避免挂浮动类时引入Bug。
     
        口“.bc"类。这个类的全称是“.blockCenter",作用为使块级元素居中。直接使用它是不足以使块级元素居中的,我们还需设定宽度。通常情况下,我们可以把它和“.w100"、“.w200"类同时使用,例如:“<div class=¨bc w200¨></div>"。
     
        口“.clearfix”类。这个类用于在父容器直接清除予元素浮动。通常情况下,为了让浮动元素的父容器能够根据浮动元素的高度而自适应高度,有三种做法:
        ◆让父容器同时浮动起来,例如:“<div class="fl"><div class="fl"></div></div>”;
        ◆让浮动元素后面紧跟一个用于清除浮动的空标签,例如“<div><div class="fl"></div><div class="cb"></div></div>:
        ◆给父容器挂一个特殊class,直接从父容器清除浮动元素的浮动,例如“<div    class="clearfix"><div  class="fl"></div></div>”。
     
          第一种方法会让父容器也浮动起来,影响父元素后面的元素的布局,有副作用。
          第二种方法增加了一个空标签,破坏了语义化。第二种方法没有任何副作用,推荐使用。
     
     
     
        口".zoom“类。这个类有些特殊,它设置的样式是zoom:1,可能有些工程师对这个样式比较陌生。它并不是CSS标准中的标准属性,而是IE的专有属性。提到zoom属性,就不得不提到IE的hasLayout问题(引用)。在IE 7发布之前,有些人推荐设置height:1%来触发hasLayout,因为IE 6会将height按照min-height来解析,所以height::1%不会引入副作用,但IE 7发布以后,这种方式就不适用了。更好的触发hasLayout的方式是设置zoom:1.不用担心引入任何副作用。
     
     
         除了以上这几个类,读者可能还会注意到用于设置边距的其他的类,例如“.mt5.mt10、“.mt20。这些类虽然繁杂,但依笔者的经验来看,它们非常有用,设置大量这样的类有助于减少page层的代码量,也为CSS的模块化提供了帮助(引用)
  • 相关阅读:
    软阈值迭代算法(ISTA)和快速软阈值迭代算法(FISTA)
    伍德伯里矩阵恒等式(Woodbury matrix identity)
    压缩感知:一种新型亚采样技术
    运输层--------运输层与网络层的关系、UDP、TCP
    单链表的基本操作(二)
    单链表的基本操作(一)
    c++中的数据类型转换
    链表总的首元结点、头结点、头指针的区别
    封装设计基础知识点
    git的使用总结
  • 原文地址:https://www.cnblogs.com/csdttnk/p/2848381.html
Copyright © 2020-2023  润新知