使用CSS有些年头了,但是很惭愧从来没有系统的看过一本书,基本都是“问题和需求”驱动的学习。最近比较闲,搞本《CSS权威指南》来看看,把一些之前忽略的问题总结一下,留待后用。
引言
1. CSS的意义: 在保持HTML结构化的同时丰富页面效果;缩减文件大小
出于这个意义,在css出现后,我们在书写html代码时,应该尽量避免使用样式标签,如<b> <font>等。
2. CSS的名称的含义: 样式+层叠
3. HTML元素的分类:替换元素 | 非替换元素
4. CSS2中引入的新分类:块级元素(block-level) | 行内元素(inline-level)
5. 引入方式:
a <link>,外部样式表(external style sheet)
b <style>,文档样式表(document style sheet)
可以使用@import在样式表中引入css文件
c style, 内联样式(inline style)
选择器
1. 选择器类型:
类:.
多类:IE7以前的浏览器不支持多类,只会识别多类中的最后一个
ID:#
属性:[],IE以前不支持属性选择器
具体属性:[foo = "bar"]
部分属性:[foo~="bar"], 比如用在class属性上,以及img标签的title属性上选择title中包含某个关键字的图像。
子串属性:不是所有浏览器都支持
[foo^="bar"] 属性值以"bar"开头的所有元素
[foo$="bar"] 属性值以"bar"结尾的所有元素
[foo*="bar"] 属性值包含"bar"子串的所有元素
特定属性:[foo|="bar"] 这个没明白
后代:
子元素:parent > child 与后代的区别是child是parent的直接子元素
IE6之前不支持
相邻元素:me + sibling 处于同级,拥有相同parent
IE6之前不支持
伪类:
三个静态伪类:
:link —— 未访问锚以及无href属性的锚
:visited —— 已访问过的锚
:first-child —— 比如p:first-child,指的不是p的第一个子元素,而是说某元素的p型并且为第一个的子元素。
:lang(fr) —— 语言选择
三个动态伪类:IE6以前只允许动态伪类选择超链接,不允许选择其它元素
IE7支持对所有元素都能应用:hover,但是不支持对表单元素应用:focus
:focus —— 拥有输入焦点的元素
:hover —— 鼠标停留在的元素
:active —— 激活的元素
伪元素: 之所以叫伪元素,是因为它会在html文档中生成一个遐想元素,而不是修饰元素
:first-letter —— 设置首字母样式 >>> 只能应用在块级元素
:first-line —— 设置第一行样式(这个第一行是动态的, 会根据外层的宽度来决定)>>> 只能应用在块级元素
:before —— 设置之前元素的样式
:after —— 设置之后元素的样式
结构和层叠
1. 由于继承特性,样式声明一般是向下传播,(CSS权威指南中说,有一个例外:应用到body的背景样式可以传播到html元素。这个说法是对的,但并不是说body的样式可以覆盖html的样式,而是只有html自己没有background设置时,才会使用body的样式)
2. 有一些属性不会继承: border,背景
字体
1. 五种通用字体系列:
Serif字体 —— 有上下短线,字母不等宽(Times, Georgia, New Century Schoolbook)
Sans-Serif字体 —— 无上下短线,字母不等宽(Helvetica, Geneva, Verdana, Arial, Univers)
Monospace字体 —— 不一定有无短线,字母等宽 (Courier, Courier New, Andale Mono)
Cursive字体 —— 模仿人的手写体 (Zapf Chancery, Author, Comic Sans)
Fantasy字体 —— 无任何特征定义 (Western, Woodblock, Klingon)
2. 理论上任何字体都会落入上述五种通用系列中。
3. 设置font-family时,既可以使用字体系列中的某一个特定字体,也可以直接使用字体系列,但是最稳妥而又能尽可能达到开发这预期的设置方法是,在特定字体后追加设置一个通用系列,如:font-family: Georgia, serif;
这样,如果读者没有安装Georgia字体,那么浏览器会选择一种安装了的serif字体,虽然这个字体并是Georgia,但是毕竟足够接近了。你也可以连续写几个你认为类似的字体让浏览器顺序选择。
4. 字体font-family的多个字体使用","连接,当某个字体包含空格或#,$之类的特殊字符时,需要使用单引号括起来。
注:我们平写网页的时候,网页内容基本上都是中文为主的,在 CSS 中写入中文字体的方法一般采用 font-family:"微软雅黑","黑体"这样的表达方式,而为了防止因为忘记转换编码而导致中文无法在utf8平台上正常生效的情况,也常将这些中文通过英文或unicode形式表达。参见 http://hotoo.googlecode.com/svn/trunk/labs/css/css-fonts.html。但是这种表达也不是在所有浏览器里面都通用的,比如firefox就不能识别这些别名,因此还是写会中文方式,然后记得转换编码。
文本属性
1. text-indent 作用于所有块级元素,且有继承性,如果缩进值为百分数,则会缩进其父元素的相应百分比。
2. text-align 作用于块元素,且只对其中的行元素或文字生效,而不会对块级子元素有效。如果要使块级元素本身居中,则需要通过margin或padding等属性控制。
3. line-height 作用于所有元素,指的是文本行基线之间的距离。
对于行内元素:某一font-size下的文本的内容区的实际高度在不同浏览器下是不同的。比如,20px的微软雅黑字体在firefox下是27px,而在chrome下是28px。line-height属性指的相邻两行文本基线之间的距离。第一行的比较对象是行元素的prev元素的最后一行基线。
对于块级元素:line-height的属性决定块级元素的高度 —————— 需要研究下。。。。
4. 行内框:(lineHeight - fontSize)/2,将这个值分别应用于内容区的顶部和底部就得到元素的行内框
5. 行框:确定了一行中所有元素的行内框,则行框的高度就是恰好足以包含最高行内框的顶端和最低行内框的底端。(在IE7及以前,似乎行框的高度不会受line-height的影响,也就是说如果line-height设置成大于行所需的最小高度,则行框高仍然是最小的那个包裹高度,而不是line-height)
6.父元素的line-height为相对值(em),子元素从父元素继承该值时,则实际line-height值要以父元素的font-size为标准计算,而不是在子元素。但是如果line-height是一个缩放因子型值(1,2等),则此时以子元素的font-size为基准计算。
7. vertical-align 作用与行内元素和表单元格。应用到表单元格的时候,只能识别baseline、top、middle、bottom
baseline: 要求一个元素的基线(如果是替换元素,则是替换元素的底端)与其父元素的基线对齐
sub/super: 用于表达上标和下标。代表其基线相对于父元素的基线降低(升高),但是降低(升高)的距离没有规范,不同用户代理距离可能有所不同。
top/bottom: 元素行内框的底端(顶端)与行框的底端(顶端)对齐。
text-top/text-bottom: 元素行内框的底端(顶端)与行内纯文本的底端(顶端)对齐(IE不是这么理解的,它所理解的元素顶端是元素内容区的顶部,这个概念在图片这类替换元素上没影响,但是对于文本,则会产生巨大效果差异)。
middle: 把行内元素框的中点与父元素基线上方0.5ex处的一个点对齐。因为多数用户代理会把1ex处理为0.5em,因此,middle往往将元素的垂直中点与父元素基线上方0.25em处的一个点对齐。不过有些浏览器不是这样。
vertical-align这个属性的表现在标准浏览器(IE)和现代浏览器(firefox,chrome)之间有很大的差异和不同,这部分内容可以参见张鑫旭的分析文章,写的蛮细致的。
8. white-space
空白符 换行符 自动换行
pre-line 合并 保留 允许
normal 合并 忽略 允许
nowrap 合并 忽略 不允许
pre 保留 保留 不允许
pre-wrap 保留 保留 允许
综上:vertical-align这个属性极不好兼容,能少用就少用。。。。
基本视觉格式化
1. 块级元素的七大水平格式化的属性中,只有width和左右外边距可以使用auto定义,其余都必须是特定的值,默认为0.
2. 块级元素的七大水平格式化的属性中,只有左右外边距可以使用负数定义,其余都至少为0.
3. 下面说下几种auto组合的效果:
a 全部auto —— 左右边距置为0,width填满其包含块
b 左右边距置为auto —— 左右边距被置为相等宽度,即元素块居中显示(但是1999年2月以前发布的浏览器无法正确处理)
c 其中一个边距置为auto —— 这个边距会被置为:包含块的宽度 - 元素宽度 - 元素另一个边距
d 宽度置为auto,边距确定值 —— 宽度会被置为:包含块的宽度 - 元素左边距 - 元素右边距
e 全部不为auto —— 对于从左到右阅读的语言,会把margin-right重置为auto;对于从右到左的语言,则将margin-left强制为auto
4. 由于水平属性值的总和总是等于父元素的width,因此,可以通过设置负值的margin来增加子元素的宽度,使它超越父元素宽度的限制。
5. CSS允许浏览器为width设置为一个最小值;块级元素的width不能小于这个值。比如IE6浏览器,就对于宽度和高度为1px的无效。
IE6出现这方面的问题的原因是这个最小高度是文字的高度,针对这个原因目前有三种兼容方法:
(一)
{ font-size:0px; height:1px; line-height: 1px; }
然后在块级元素中增加一个
(二)
{ font-size:0px; height:1px; overflow: hidden; }
(三)
{ border-top: 1px solid #fff }
我在平时开发中遇到需要这种兼容的情况就是用1px高度的细线拼圆角
6. 两个元素的水平外边距不会合并
7. 块级元素的七大垂直格式化的属性中,只有height和上下外边距可以使用auto定义,其余都必须是特定的值,默认为0.
8. 块级元素的七大垂直格式化的属性中,只有上下外边距可以使用负数定义,其余都至少为0.
9. 垂直属性中,为height和上下外边距置auto都不会有垂直居中的效果:height置为auto,这个值只会受它的内容高度影响,如果没有内容就是0;其余两个则无论怎样都会置为0。
10. 垂直属性的外边距合并情况比水平属性稍复杂。
行内元素:垂直外边距会合并(此情况发生在:子元素的外边距与包含块的内外边距之间;相邻元素的外边距之间)
块级元素:包含块不做任何特殊处理时,与行内元素的情况相同;如果在包含块样式中增加边框或内边距,则外边距不会发生合并情况。
11. display属性
inline:为块级元素赋予行内元素的特性
block:为行内元素赋予块级元素的特性
inline-block:拥有该属性的元素则同时拥有了块级元素和行内元素的特性
block:外边距不合并;宽度高度,text-align有效
inline:作为替换元素放在行中,底端默认位于文本的基线上
inline-block这个属性并不是所有浏览器都支持,不支持的如firefox2,IE6,IE7,下面是分别的兼容方法:
firefox2: 使用私有属性 -moz-inline-stack,据说这个有一个bug,就是当外层元素是display:inline时,会导致超链接不可点,此时使用position:relative解决(我没试过,有机会检测下)
IE6、7:对于块级元素,触发hasLayout属性(一般用zoom:1),然后设置display:inline,此时的效果与inline-block相似。我猜想是hasLayout=true让块级元素保持块级的margin和宽度等特性,inline则在布局显示上生效,这个分工上确实与inline-block本身很相似。(有一个例子里面说要设置一个min-height,我觉得这个可能关键看你希望一个什么效果的inline-block)
这里顺便贴个min-height的IE6兼容:IE6虽然不支持min-height,但是他自己对于height属性的理解其实就差不多跟min-height一样,对于超出height的内容,IE6会把区域自动撑大。所以只要设置一个只针对IE6的_height:xxpx就行了。
需要注意的一点:display虽然能够改变元素的显示,但是却无法改变元素的本质,也就是说原来”行内元素无法承载块级元素“(当然,只是在xhtml标准下),改变显示方式后这个准则仍然有效。
浮动
1. 浮动属性的要点:
a 无继承性,默认值none
b 元素会以某种方式从文档的正常流中被删除,但删除后还是会影响布局
c 浮动元素的外边距不会合并(前文说过,行内元素和块元素的垂直外边距都会合并)
d 如果要浮动非替换元素,则须为该元素声明width,否则,根据CSS规范,元素的宽度趋于0(这个宽度与浏览器设置的最小width有关)。
e 设置了浮动属性的元素会生成一个块级框,而无论元素本身是什么,因此没有必要再增加display:block的声明
2. 浮动规则
a 浮动元素的左(或右)外边界不能超出其包含块的左(或右)内边界
b 浮动元素的左(或右)外边界线必须是源文档中之前出现的左浮动(或右浮动)元素的右(左)外边界线,除非后出现浮动元素的顶端在先出现浮动元素的底端下面
c 左浮动元素的右外边界不会在其右边右浮动元素的左外边界的右边。一个右浮动元素的左外边界不会在其左边左浮动元素的右外边界的左边。
e 一个浮动元素的顶端不能比起父元素的内顶端更高。如果一个浮动元素在两个合并外边距之间,放置这个浮动元素时就好像在两个元素之间有一个块级父元素。
f 浮动元素的顶端不能比之前所有浮动元素或块元素的顶端更高
g 如果源文档中一个浮动元素之前出现另一个元素,浮动元素的顶端不能比包含该元素所生成框的任何行框的顶端更高。
h 左(或右)浮动元素的左边(右边)有另一个浮动元素,前者的右外边界不能在其包含块的右(左)边界的右边(左边)
i 浮动元素必须尽可能高地放置
j 左浮动元素必须向左尽可能远,右浮动元素则必须向右尽可能远。位置越高,就会向右或向左浮动得越远
3. 规则导致的意外
—— 强制高度
—— 父元素增加overflow:hidden,IE7及以下浏览器还要加zoom:1(或其他触发haslayout的属性)
—— 将父元素置为浮动元素
<html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style type="text/css"> body, div, p, h1 {margin:0;padding:0} .fl { float: left; margin: 10px;} .fr { float: right;} </style> </head> <body> <div> <p style="line-height:20px; text-align:left; padding-left: 50px; width:200px;"> <img class="fl" src="http://tp3.sinaimg.cn/1809099542/50/39999121812/0"/> </p> <span style="background:#DDD;">我是行元素我是行元素</span> <h1 style="background:#DDD;">标题测试标题测试</h1> </div> </body></html>
图1
—— 行内框与一个浮动元素重叠时,其边框、背景和内容都在该浮动元素”之上“显示。
—— 块框与一个浮动元素重叠时, 其边框、背景在该浮动元素”之下“显示,而内容在浮动元素”之上“显示。
<html><head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style type="text/css"> body, div, p, h1 {margin:0;padding:0} .fl { float: left; margin: 10px;} .fr { float: right;} </style> </head> <body> <div> <p style="line-height:20px; text-align:left; padding-left: 50px; width:200px;"> <img style="margin:10px -15px;" class="fl" src="http://tp3.sinaimg.cn/1809099542/50/39999121812/0"/> </p> <span style="background:#DDD;">我是行元素我是行元素</span> <h1 style="background:#DDD;">标题测试标题测试</h1> </div> </body></html>
4. 清除浮动
—— 对浮动层后面的元素增加 clear:left|right|both 属性
清除原理:在CSS1和CSS2时代,就是为元素增加上外边距,把它挤到浮动元素的下面。因此,如果为该元素手动增加margin-top属性,其实最后是会被忽略的。但是在CSS2.1以后,会为元素引入一个清除区域,该清除区域的高度正好保证元素被挤到浮动元素下面(但是这个区域的高度并没有严格定义,firefox下看起来是正好等于浮动元素高度的,当然这个浮动元素是替换元素)。但清除区域与CSS2中的上外边距不同,当元素的margin-top超出这个清除区域的高度时,元素就会被继续向下推。
—— 在浮动层后面追加具有clear属性的元素:这个就是比较通用的”clearfix“方法,但是因为要添加新元素,所以并不太受欢迎。
—— 利用【after:】增加具有clear属性的伪元素:先看下代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <style type="text/css"> body, div, p, h1 {margin:0;padding:0} .fl { float: left;} .clearfix:after{ clear:both; content: " "; visibility: hidden; display: block; font-size: 0; height: 0; } </style> </head> <body> <div style="position:relative; padding:20px;"> <div style="line-height:20px; text-align:left; padding-left: 50px; width:200px;"> <div class="fl clearfix" style="width:20px;height:20px;background:#DDD;">dfsdfsdf</div> </div> <span style="background:#DDD;">我是行元素我是行元素</span> <h1 style="background:#DDD;">标题测试标题测试</h1> </div> </body></html>
上面这段代码是一个典型错误。写的时候大概预想的是在fl元素后面增加一个空的clear了的content,但其实仔细查看“after:”的用法会发现,这个content是被加到fl元素的内容里的,而不是fl元素的后面。因此,这个空元素的clear是无效的。
但是把这个clearfix类加到父容器上,父容器的浮动影响被清除,高度自适应;但是父容器内浮动元素后面的元素依然是没有清除浮动的。
因此,利用after:伪元素的方法一般用于解决浮动元素造成的“父容器高度无法自适应”的问题;而解决这个问题还有一个CSS中提及的方法,就是为父元素也设置float:left|right属性,但是这个方法显然在复杂文档中极其不好控制,所以不建议使用。
<div id="left" style="float:right;width:100%; height:200px;"> <div style="margin-right:200px;height:200px;background-color:red;"></div> </div> <div id="right" style="float:right;margin-right:-100%;width:200px;height: 200px;background-color:green;">当然,这个例子其实也可以使用overflow:hidden的方法实现。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <base href="pointEditor" /> <title>table</title> <style> body { margin:0;} .talignC{ text-align: center; } .outter { margin: 0 auto; overflow:hidden; position: relative; } .leftCol { float: left; width: 300px; background: #c3c3c3; } .rightCol { overflow: hidden; zoom: 1; background: #f2f2f2; } .leftCol, .rightCol { margin-bottom:-10000px; padding-bottom:10000px; } </style> </head> <body> <div class="header"> <h1>等高两列,高度自适应,左列宽度自适应</h1> </div> <div class="outter"> <div class="leftCol">我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高我高 </div> <div class="rightCol"></div> </div> </body> </html>
定位
1. 定义
2. 包含块
—— 如果这个祖先是行内元素,包含块则设置为该祖先元素的内容边界。
—— 如果没有父元素,则包含块就是初始包含块。
3. 偏移属性
待续。。。