Skip to content

Latest commit

 

History

History
355 lines (224 loc) · 21.2 KB

再次阅读《精通CSS-高级Web标准解决方案(第二版)》.md

File metadata and controls

355 lines (224 loc) · 21.2 KB

再次阅读《精通CSS-高级Web标准解决方案(第二版)》

标签: CSS 读后感


昨天(2015年11月21日) 在我们学校举行了大型招聘会。我面试了三家企业。有一家企业是先做笔试题的,做完后发现自己还是很多细节处理得不够。无论还有没有二面,我还是要重新把《精通CSS》和《JavaScript高级程序设计》这两本书重新看一遍。

《精通CSS》

第一章:

语义化的好处:

  1. 自己更易处理(搜索和避免不必要的代码膨胀)
  2. 利用SEO
  3. 屏幕阅读的用户可以依靠标题进行页面导航

div(division,部分)对块级元素进行分组,span对行内元素进行分组或标识。

XHTML 1.0和 HTML 4.01之间主要差异是它遵守XML编码约定:所有XHTML属性必须包含引号,所有元素必须是封闭的

DTD(文档类型定义)是一组机器可读的规则,它们定义XML或HTML的特定版本中允许有什么,不允许有什么。在解析网页时,浏览器将使用这些规则检查页面的有效性并且采取相应的措施,浏览器通过分析页面的 DOCTYPE 声明来了解要使用哪个DTD。

DOCTYPE当前有两种风格:严格(strict) 和过渡 (transitional)。后者的目的是帮助开发人员从老版本迁移到新版本。因此,HTML 4.01和XHTML 1.0过渡版本仍然允许使用已废弃的元素(如font),但这些语言的严格版本禁止使用废弃的元素。

浏览器模式:标准模式和混杂模式

第二章:

选择器:

  1. 常用选择器: 类型选择器(元素选择器)、后代选择器

  2. 伪类: 链接伪类 :link和:visited,只能用于锚元素

    动态伪类 :hover、:active和:focus。理论上可应用于任何元素。IE6 只能对 锚链接 应用:active 和:hover选择器,完全忽略:focus (已验证)。 IE 7在任何元素上都支持:hover,但忽略:active和:focus(书上原话),但在IE11选择IE7文档模式或IETester时,a标签是支持:active。

    最后,可以把伪类组合使用,以至可创建更复杂的行为,如 a:visited:hover{} 让已访问与未访问链接实现不同的鼠标悬停效果。

  3. 通用选择器:*

  4. 高级选择器( CSS 2.1和CSS3选择器): 大多数现代浏览器(IE7及以上)支持这些高级选择器,但IE6和更低版本不支持。

    • 子选择器>(IE7及以上),但在IE7中有个小Bug,如果父元素和子元素之间有HTML注释,就会出问题(测试时,发现并没有问题)。当然,对于IE6,可以利用通用选择器 * 模拟这个效果,div p{/*设置效果*/} div p *{/*还原原来的值*/}
    • 相邻同胞选择器+,同样,在IE7,与自选择有同样的BUG,导致失效(已验证)。
    • 后面兄弟选择器~(书上没有),经测试,IE7支持。
    • 属性选择器:a[title]、a[rel="nofollow"] 等全部属性选择器IE7都支持

层叠和特殊性

  • 特殊性 !important > 行内样式 > ID > 类、伪类和属性选择器 > 类型选择器(元素选择器)和伪元素选择器
  • 层叠:当两个规则具有相同的特殊性时,后定义的规则优先
  • 继承 直接应用于元素的任何样式总会覆盖继承而来的样式。这是因为继承而来的样式的特殊性为空。 这就解释了“为什么a标签和标题标签要单独指定的样式”这个问题。如下图,chrome浏览器下。a标签和h2标签的默认样式。 此处输入图片的描述
    此处输入图片的描述

第三章 可视化格式模型

盒模型

页面上每个元素都被看作一个矩形框,该框由元素的内容、内边距、边框和外边距(透明的)组成。

CSS2.1的outline属性,轮廓绘制在元素框(个人认为:即不包括外边距的矩形框)上,所以不影响元素的大小或定位(这里,对我产生一个误区,即定位是按元素框定位(即不包括外边距),其实定位是包括外边距的,即矩形框)。支持IE8及以上。

IE6的混杂模式下,拥有类似box-sizing:border-box的特性,即指定的宽度是内容、内边距和边框的宽度总和。

外边距叠加:即当两个或更多垂直外边距相遇时,它们将形成一个外边距(高度为较大者)。情况有如下几种: 1. 两个同级上下元素 2. 祖先元素与内嵌元素(没有内边距或边框隔开,就祖先元素overflow:hidden/auto/scroll可有隔开的作用,避免叠加) 3. 本身是空元素时,自身上下外边距也会重合(没有边框或内边距隔开) 4. 当然前面几种情况可以结合发生。

只有普通文档流中,块框的垂直外边距才回发生叠加。行内框、浮动框或绝对(个人认为包括绝对定位和固定定位)定位框之间的外边距不会发生叠加。

可视化格式模型

CSS中有3种基本的定位机制:普通流、浮动和绝对定位。

行内框:垂直内边距、边框和外边距不影响行内框的高度。同样,显式设置高度或宽度也没有影响。修改行内框尺寸的唯一方法是修改行高或水平内边距、边框、外边距。

行框:由一行形成的水平框称为行框。行框的高度总是足以容纳它包含的所有行内框。

display:inline-block; 让元素像行内元素一样水平依次排列,但框的内容仍然符合块级框的行为。支持IE8及以上。

绝对定位:绝对定位的元素的位置是相对于最近的已定位祖先元素,如无,则根据用户代理的不同,初始包含块可能是画布(是iframe吗?)或HTML元素。

在IE6中有个BUG:相对于相对定位的框的右边或顶部设置绝对定位的框的位置,那么需要确保相对定位的框已设定了尺寸(测试时发现,块级元素只需设置高度)。否则,绝对定位元素会错误地相对于画布定位这个框(已验证)

固定定位:IE6不支持,IE7部分支持,但是实现中有许多bug。

浮动:浮动的框可左右移动,直到它的外边缘(包括外边距)碰到包含框或另外一个浮动框的边缘。因为浮动框不在文档的普通流,所以文档的普通流中的块框表现得就像浮动框不存在一样。 此处输入图片的描述
如果包含块太窄,以致不能同时水平排列3个浮动元素,且浮动元素的高度不同,那么当它们向下移动时,可能被其它浮动元素卡主。

前面说到浮动会让元素脱离文档流,不再影响不浮动的元素。实际上,框的文本内容(不止文本)会受到浮动元素的影响,会移动以留出空间,用技术术语来说,浮动元素旁边的行框被缩短,从而给浮动元素留出空间,因此行框围绕浮动框。 此处输入图片的描述
此处输入图片的描述
此处输入图片的描述

要想阻止行框围绕在浮动框的外边,需要对包行这些行框的元素应用clear属性。清除浮动时,浏览器给元素顶上添加足够的外边距,使元素的顶边缘下降到浮动框下面。

子元素浮动后,脱离文档流,不能撑起父元素高度,要撑起父元素高度的方法有:

  1. overflow:hidden/auto
  2. 父元素也浮动
  3. .clearfix:after{content:" ";height:0;visibility:hidden;display:block;clear:both}.clearfix:after{content:" ";display:table;clear:both}。由于IE6/7不支持:after伪元素,所以要使用以下hack: .clearfix{zoom:1; //trigger IE haslayout}
  4. 增加额外标签,然后clear

第四章 背景图像效果

CSS规范不允许混合使用多种单位。实际上,浏览器是支持的。

opacity:IE8及以下不支持,但是可以用 filter:alpha(opacity=80) 指定透明度。opacity 是继承的,它的后台元素都会受影响。另外也是可以叠加的,父元素0.8,子元素0.8,那么子元素是0.64。

rgba:IE8及以下不支持,是针对opacity而生的,不影响后代元素。

IE7 支持 min-height、max-height

许多流行的屏幕阅读器会忽略那些display值为none或visibility为hidden的元素。所以这会造成严重的可访问性问题。

解决办法是:通过设置非常大的负值文本缩进:text-indent:-5000em;(text-indent适用于块级元素)

IE6不直接支持PNG透明度的,对于IE6,书上列出两种方法(网上更多):

  1. 在针对IE6的CSS文件里: filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/img/my-image.png', sizingMethod='crop');/* 网上说,路径是相对于html的,而不是CSS的。*/ background:none;/* 取消原来的背景图,防止遮住该过滤器。*/

  2. IE PNG fix技术。利用Microsoft专有的CSS扩展——行为(behavior)。下载合适的.htc文件,并在IE6专用的样式表引用。

    img, div{
      behavior:url(iepngfix.htc)
    }
    

备注:屏幕阅读器是指将屏幕显示内容转为声音或布莱叶盲文显示,以帮助视力障碍者使用电脑的软件。

第五章 对链接应用样式

为提高页面的可访问性,在定义鼠标悬停状态时,最好在链接上添加:focus伪类。在通过键盘移动到链接时,也可以让链接显示的样式与鼠标悬停时相同。

a:hover, ac:foucs{} /* 这也是bootstrap用到的 */

正确写法:

a:link, a:visited{text-decoration: none;}

a:hover, a:focus, a:active{text-decoration:underline}

如果次序反过来,则下划线效果就不起作用(因为层叠造成的,当两个规则具有相同的特殊性时,后定义的规则优先):

对于a标签,最好按以下顺序: a:link, a:visited, a:hover, a:focus, a:active (LVHFA)

对于不支持背景图动画的,常会显示第一帧,以确保平稳退化。(连IE5都支持 --!)

第六章 对列表应用样式和创建导航条

初始化 ul{margin:0;padding:0;list-style-type:none;}

不对应用列表项应用样式,而是对其中包含的锚链接应用样式,由此提供更好的浏览器兼容性。

第七章 对表单和数据表格应用样式

表格:

表格特有的元素:capiton用于指定表格的标题;summary属性用于描述表格内容。

<table summary="I am a Description">
    <caption>表格标题</caption>
</table>

 一个table里,thead 、tfooter只能使用一个,而tbody可以将复杂的表格划分为多个部分。

这里有三个注意点:
1)thead和tfoot在一张表中都只能有一个,而tbody可以有多个。
2)tfoot必须出现在tbody前面,这样浏览器在接收主体数据之前,就能渲染表尾,有利于加快表格的显示速度。这一点对大型表格尤其重要。
3)thead、tbody和tfoot里面都必须使用tr标签。

CSS的border-spacing属性可以控制单元格之间的距离。但IE7及以下不支持。因此需要老式但可靠的cellspacing属性(支持IE6和IE7)。严格来说,该属性是表现性的。

表单:

对于表单,对于必填域和提示,最适合用em或strong元素。

OS X等许多系统为了保持一致,禁止修改input按钮样式,但button不受限制。

对于需要隐藏的label,将display设置为none会住址许多屏幕阅读器访问它们。其中有两种方法:

  1. 设置较大的负文本缩进将标签定位到屏幕外(书上的)

  2. Bootstrap的.sr-only

    .sr-only{
        position:absolute;
        width:1px;
        height:1px;
        padding:0;
        margin: -1px;
        overflow:hidden;
        clip:react(0,0,0,0);
        border:0;  
    }
    

第八章 布局

IE6 不支持margin:auto居中(在IETester是支持的),解决办法是:body{text-align:center} .wrapper{text-align:left} /* 因为IE将text-align误解为让所有东西居中,而不只是文本 */

IE6 因为是考虑元素内容的尺寸,而不是元素本身尺寸。在符合标准的浏览器中,如果元素的内容太大,它只会超出框之外。但是在IE6中,如果元素内容太大,则整个元素就会扩展(包括宽和高)。即设定的width表现得像 min-width 此处输入图片的描述此处输入图片的描述

流式布局:百分比

弹性布局:字号em

创建高度相等的列:关键点是给每个框设置大的padding-bottom,然后用数值相近的负margin-bottom抵消这个高度。然后在#wrapper设置 overflow:hidden。

从这个案例可以看出:加入把框看作是一个垂直于屏幕的立体,那么margin是最底层的,而元素之间的间距是靠margin隔开的。又因为padding-bottom在margin之上,所以处于外层padding让我们看到背景色,而负值margin则让旁边的元素处于其padding下方。 此处输入图片的描述 (Firefox 3D布局)

<div id="wrapper">
    <div class="box"></div>
    <div class="box"></div>
    <div class="box"></div>
</div>

// 假设.box因为内容不一样而高度不同

#wrapper{
  overflow:hidden;
}
.box{
  width:   30%;
  float:left;
  padding-bottom:520px;
  margin-bottom: -500px;
}

第九章 bug和修复bug

 拥有布局:IE6的bug最多,IE6与其它浏览器表现不同的原因之一是,显示引擎使用一个称为布局(layout)的内部概念。布局问题是许多IE/WIN显示BUG的根源。

什么是布局? Window上的IE使用布局概念来控制元素的尺寸和定位。那些“拥有布局(haslayout)”的元素负责本身及其子元素的尺寸设置和定位。如果一个元素“没有拥有布局”,那么它的尺寸和位置由最近的拥有布局的祖先元素控制。

  IE显示引擎利用布局概念减少它的处理开销。在理想的情况下,所有元素都控制自己的尺寸和定位。但是,这会在IE中导致很大的性能问题。因为,IE开发团队决定只将布局应用于实际需要它的那些元素,这样就可以充分地减少性能开销。

在默认情况下拥有布局的元素包括:body、html(标准模式中)、table、tr、td、img、hr、input、select、textarea、button、iframe、embed、object、applet、marquee。

布局概念是Window上的IE特有的,而且它不是CSS属性。尽管设置某些CSS属性会使元素拥有布局,但是在CSS中无法显示地设置布局。可以使用JavaScript函数hasLayout查看一个元素是否拥有布局。如果元素拥有布局,这个返回true,反之,返回false。hasLayout是一个只读属性,所以无法使用JavaScript进行设置。

设置以下CSS属性会自动地使元素拥有布局:

  1. float:left或right
  2. display:inline-block
  3. width:任何值
  4. height:任何值 ⑤zoom:任何值
  5. writing-mode:tb-rl

在IE7中,以下属性也成了布局触发器:

  1. overflow:hidden、scroll或auto
  2. min-width:任何值
  3. max-width:除了none之外的值。

布局的效果

布局是许多IE显示BUG的根源。

  1. 一个文本段落靠着一个浮动元素,那么我们期望文本围绕这个元素。但是在Window上的IE6,如果段落拥有布局(如设置高度),那么它就被限制为矩形,因此阻止文本围绕浮动元素。 此处输入图片的描述
  2. 在IE6中,拥有布局的元素会错误地扩展以便适应内容的尺寸。width和height更像是min-width和min-height。
  3. 其他问题:
    1. 拥有布局的元素不会收缩(什么意思?)
    2. 布局元素对浮动元素自动清理(所以.clearfix{zoom:1})
    3. 相对定位的元素没有布局
    4. 在拥有布局的元素之间外边距不叠加
    5. 在没有布局的块级链接上,单机区域只覆盖文本
    6. 在滚动时,列表项上的背景图像间歇性地显示和消失。

所以,如果遇到一个IE BUG,首先应该做的一件事情是尝试通过应用规则迫使元素拥有布局。

在IE7中,已经修复大多数与布局相关的问题。但是该团队的解决方法是找到常见的显示BUG,然后通过在代码中创建列外来处理它们,而不是解决顶层问题。因此,可能有一些不显著的布局bug还没有被发现。

IE8使用全新的显示引擎,据称不使用hasLayout属性,因此解决了这些问题的根源。

IE条件注释, 在IE5首次出现。

<!--[if IE]><![endif]-->

CSS被设计成具有很强的向前兼容性。如果浏览器不理解某个选择器,则会忽略整个规则。如果不理解某个属性或值,则会忽略整个声明(某个CSS声明)。

应用星号HTML hack。针对IE6。因为IE6有一个匿名的根元素,它包围着HTML元素。所以针对IE6 可以这样应用规则: * html #content{}

常见bug及其修复方法

  1. 双外边距浮动BUG(IE6):使任何浮动元素上的外边距(左右两侧外边距)加倍。
    解决方法: display:inline

  2. 3像素文本偏移BUG(IE6):当文本与一个浮动元素相邻时,这个bug就会表现出来,例如,假设将一个元素向左浮动,并且不希望相邻段落中文本围绕浮动元素。你可能会在段落上应用一个左外边距,其宽度等于浮动元素的宽度:

    .myFloat{float:left;width:200px}
    
    p{margin-left:200px}    
    

    如果这么做,在文本和浮动元素之间就会出现一个莫名其妙的3像素间隙。
    此处输入图片的描述
    修复这个Bug需要双管齐下。

    首先,针对IE6 为文本框设置height:1%(IE6会把height当成min-height),这样文本框就会拥有布局,由前面可知,拥有布局的元素被限制为矩形。并且出现在浮动元素的旁边而不是它们的下面。添加200px的外边距实际上会在IE6中在浮动元素和段落之间产生200像素的间隙(在IETester并没有)。为了避免这个间隙,需要为IE6专门设置margin-left为0(还是要设置为0的,否则取消不了这3px)。这样文本偏移被修复了,但是现在另外一个3px间隙出现了,这一次是在浮动元素上。为了去掉这个间隙,需要在浮动元素上设置一个负的3px右外边距 .myFloat{margin-right:3px}

  3. IE6的重复字符bug

    在某些情况下,一系列浮动元素的最后一个元素中的最后几个字符会在浮动元素下面重复出现。当在一系列浮动元素的第一个和最后一个元素之间有多个注释时,就会出现这个BUG。前两个注释没有影响,但是后续的每个注释会导致两个字符重复出现。所以3个注释会导致两个重复字符,4个注释会导致4个重复字符,5个注释会导致6个重复字符。

    这个BUG似乎与前面的3px文本偏移bug相关。为了修复这个bug,可以通过设置负的右外边距从最后一个浮动元素上去掉3px,或者使容器扩大3px。但是,这两种方法可能在IE7中造成问题最好的方法是删除注释。

  4. IE6的“藏猫猫”bug

    因为在某些条件下问来看起来消失了,只有在重新加载页面时才再度出现。

    出现这个bug的条件是:一个浮动元素后面跟着一些非浮动元素,然后是一个清理元素,所有这些元素都包含在一个设置了背景颜色或图像的父元素中。如果清理元素碰到了浮动元素,那么中间的非浮动元素看起来消失了,隐藏到了父元素的背景颜色或图像后面,只有在刷新页面时才重新出现。

    解决办法:

    1. 去掉父元素上的背景颜色或图像。但是这常常不可行。
    2. 避免清理元素与浮动元素接触
    3. 容器应用了特定的尺寸,那么这个BUG视乎就不会出现
    4. 给容器指定行高
    5. 将浮动元素和容器元素的position属性设置为relative也会减轻这个问题。
  5. 相对容器中的绝对定位(IE6BUG前面有提过)

    这bug的原因在于相对定位的元素没有获得IE/win的内容layout属性。因此它不创建新的定位上下文,所有绝对定位元素相对于视口进行定位。

    解决办法:让相对容器拥有布局,height:1%。

第10章 研究案例

Reset CSS :http://meyerweb.com/eric/tools/css/reset/