原文地址:http://justclear.github.io/css-stylin-with-css-note-1css
因为 CSS 做用的对象是 HTML ,因此做者在这章主要先讲了一些基本的 HTML 标签的用法和结构。html
做者在这节主要讲了一个 HTML 页面所需的最基本的文档结构以下:html5
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <!-- 这里是网页内容 --> </body> </html>
首先 <!DOCTYPE html>
是 HTML5 中新的文档类型声明语法,相比 HTML4 的冗长文档类型声明语法来讲 HTML5 是大大的简化了。git
做者在这一节介绍了两个比较重要的概念————块级元素和行内元素,默认状况下块级元素会始终占居一行,而行内元素并不会。除了 table 元素的 display 属性比较特殊之外,基本上全部的 HTML 元素的 display 的属性值要么是 block,要么是 inline。做者的一个思想是,不管你想了解哪一个 HTML 元素,第一个要问的问题就是:它是块级元素仍是行内元素,而后在编写标记的时候预想到这个元素在初始状态下是如何定位的,这样才能进一步想好未来怎么用 CSS 从新定位它,由于块级元素和行内元素在定位上有很大的区别,后面的拓展会详细说明。github
块级元素盒子(一个很重要的概念————盒模型,后面会详细说明)会扩展到与父元素同宽,这也是为何块级元素会占居一行的缘由了,由于全部块级元素的父元素都是 body,而它的默认宽度就是浏览器的视口(viewport)大小,因此默认状况下块级元素的宽度也和浏览器的视口同样宽,这样以来,一个块级元素旁边也就没有空间来容纳另外一个块级元素了。canvas
相比于块级元素会扩展到与父元素同宽,然而行内元素的行为倒是偏偏相反,它会尽可能的「收缩包裹」其内容(也是盒模型的概念),这也就是为何几个行内元素会并排显示在一行直到它们排满一行才会另起一行,而每一个块级元素会直接另起一行的缘由了。浏览器
拓展:ide
做者在这一节中并无对块级元素和行内元素的一些其余特性进行详细的解释,在这里笔者对它们的一些特性知识进行拓展。首先先列出一些常见的块级元素和行内元素:布局
<!-- 常见的块级元素 --> div, form, table, header, aside, section, article, figure, figcaption, h1~h6, nav, p, pre, blockqoute, canvas, ol, ul, dl <!-- 常见的行内元素 --> span, a, img, label, input, select, textarea, br, i, em, strong, small, button, sub, sup, code
以前做者提到过不管你想了解哪一个 HTML 元素,第一个要问的问题就是:它是块级元素仍是行内元素,由于它们在盒模型上的表现有很大的不一样,不过在了解它们的不一样以前咱们还得先知道另一个概念————替换元素和非替换元素,其中替换元素就是指浏览器是根据元素的属性来判断具体要显示的内容的元素,好比 img
标签,浏览器是根据其 src
的属性值来读取这个元素所包含的内容的,常见的替换元素还有 input
、textarea
、 select
、 object
、 iframe
和 video
等等,这些元素都有一个共同的特色,就是浏览器并不直接显示其内容,而是经过其某个属性的值来显示具体的内容,好比浏览器会根据 input
中的 type
的属性值来判断到底应该显示单选按钮仍是多选按钮亦或是文本输入框。而对于非替换元素,好比 p
、label
元素等等,浏览器这是直接显示元素所包含的内容。看到这里你应该大概的知道了什么是替换元素和非替换元素了。性能
对着两个概念有了大概的了解后就能够对 block
和 inline
在盒模型上的表现差别进行了解了,首先是 margin
,W3C 对其所支持了元素对象是这么定义的:
Applies to: all elements except elements with table display types other than table-caption, table and inline-table
英语不是很好,没太明白这句话的意思,个人理解就是全部元素都支持 margin
除了 display
属性值为 table-caption
和 table-inline
之外的全部表格显示类型好比 table-row-group
、 table-cell
、 table-row
和 table-header-group
等等,可是为了验证个人理解,我发先 display
属性值为 table
的元素也支持,多是我对原文标准的理解有误。但还有一个要特别注意的是 margin-top
和 margin-bottom
两个属性比较特殊,它们对非替换行内元素没有效果,下面是 W3C 上对于 margin-top
和 margin-bottom
支持对象的介绍:
Applies to: all elements except elements with table display types other than table-caption, table and inline-table
These properties have no effect on non-replaced inline elements.
前面一句和以前对 margin
的描述是同样的,这毫无疑问,下面这句话的意思是这些( margin-top
和 margin-bottom
)属性对非替换行内元素没有效果好比 a
和 span
,注意这里是非替换行内元素而不仅仅是非替换元素或者是行内元素。好比 img
就是一个行内元素, margin-top
和 margin-bottom
对它是有效果的,由于它是一个替换元素而不是非替换元素,因此对于「 margin-top
和 margin-bottom
对行内元素没有效果」这种说法是不对的。
而对于 padding
的支持对象,W3C 是这么描述的:
all elements except table-row-group, table-header-group, table-footer-group, table-row, table-column-group and table-column
上面这句话的意思是除了表格显示类型为 table-row-group
、 table-header-group
、 table-footer-group
、 table-row
, table-column-group
和 table-column
的元素不支持,其余全部的元素都支持。
但这里有些特殊状况须要注意的是,对行内元素好比 span
和 img
设置左右内边距的效果是可见可,可是对行内元素设置上下内边距在有些状况下是不可见的,这些状况又要分为是否为替换元素和是否设置了背景色,为了能更直观的了解这些概念,我在这里作了个表格:
<!-- -->
padding-top 和 padding-bottom 对于行内元素是否可见:
<div class="table-responsive">
替换元素(e.g: input) | 非替换元素(e.g: span) | |
---|---|---|
设置背景色 | 可见,影响行高,会撑开父元素 | 可见,不影响行高,不会撑开父元素 |
没有设置背景色 | 可见,影响行高,会撑开父元素 | 不可见,不影响行高,不会撑开父元素 |
</div>
因此对于「 padding-top
和 padding-bottom
对行内元素没有效果」这种说法也是不对的,由于它们只是对于没有设置背景色的行内非替换元素效果不可见而已,而对于行内替换元素来讲,无论是否设置了背景色都是有效果了,而且会把父元素撑开。
说了这么多 block
和 inline-block
的区别,其实除了这两个常见的 display
属性之外还有一个属性也是很是常见的,那就是 inline-block
,没错,这就是前面两种状况的结合体,它既有 block
的特性又有 inline
的特性,好比把一个 display
属性值为 block
或者 inline
的元素属性值设置成 inline-block
后,既能够用只对行内元素有效的 text-align: center;
声明对其进行居中之外,还能够用 padding-top
和 padding-bottom
对元素设置上下内边距而无需对其设置背景色,而且能把父元素撑开。
对于块级元素和行内元素的拓展就暂时到这,若是有不明白或者不对的地方也欢迎指出。
做者在这一小节只要介绍了 HTML 结构所对应的文档对象模型(DOM,Document Object Model),DOM 是从浏览器的视角来观察页面中的元素以及每一个元素的属性,由此能够得出这些元素的一个家族树。经过 DOM 能够很清晰的看出文档中每一个元素之间的关系。好比下面的 HTML 代码的 DOM 的家族树就以下图:
<body> <section> <h1>The Document Object Model</h1> <p>The page's HTML markup structure defines the DOM.</p> </section> </body>
上面是一个很是简单的 DOM 结构图,由此你能够和直观的看出 HTML 文档流中每一个元素之间的关系,好比究竟是父子元素仍是兄弟元素。
做者在本章主要讲解了 HTML 标签是怎么为内容提供结构的,以及每一个元素会在屏幕上生成什么样子的盒子,好比是行内盒子仍是块级盒子,最后又简单的讲解了什么是 DOM ,它是浏览器中文档的模型,而 CSS 能够修改 DOM 中的元素样式属性,从而修改页面自己的布局和外观。
在本章中做者主要讲解了 CSS 如何对 HTML 添加样式的,而且解释了层叠的工做机制好比当元素的同一个属性被屡次设置样式后到底应该选择何种样式,这就要靠 CSS 的层叠机制来决定最终应用哪一种样式了。
每一个 HTML 元素都有一组样式属性,这些属性涉及元素在文档流中显示时的不一样方面,好比在文档流中的位置、边框、背景、颜色等等。CSS 就是一种先选择 HTML 元素,而后设定选中元素 CSS 属性的机制。CSS 选择符和要应用的样式构成一条 CSS 规则。
上下文选择器的格式以下:
标签1 标签2 { 声明}
其中标签2就是咱们要选择的目标,并且只有在标签1是标签2的祖先元素(不必定是父级元素)的状况下才会被选中。上下文选择器严格来说应该叫「后代组合式选择器(Descendant Comninator Selector)」。
还有一点要注意的是,上下文选择器以空格做为分隔符,而分组选择器则以逗号做为分隔符,不要弄混。
前面一节做者介绍的上下文选择器是以某个祖先元素做为上下文的,只要目标元素在 DOM 结构「上游」存在这么一个祖先元素便可,不管这个祖先元素和目标元素隔了多少层级都没有关系,但有的时候咱们须要比「某个祖先元素」更具体的上下文,这时候咱们就可使用一些特殊的选择器了,好比自选择器 >
、 紧邻兄弟选择器 +
、通常兄弟选择器 ~
和通用选择器 *
。
标签1 > 标签2
这里的标签2必须是标签1的子元素,也就是说标签1必须是标签2的父元素,而不能是标签2的任何其余祖先元素。
标签1 + 标签2
在这里标签2必须紧跟在兄弟标签1的后面,不然无效。
标签1 ~ 标签2
在这里标签2必须跟(不必定要紧跟,只需在标签1的后面便可)在其兄弟标签1后面。
*
通用选择器 *
是一个是一个通配符,表明文档流中的任意元素,不过通用选择器 *
一般会搭配一些其余选择器来使用,好比:
section > *
表明 section
的全部子元素,不过通常状况下不多经过通配符来选择某个元素下的全部子元素,由于这涉及到浏览器性能问题,它会影响网页的渲染时间,咱们写的时候是从左到右写的,可是浏览器渲染倒是从右到左的,就上面这段代码来讲,浏览器会先遍历全部的元素,而后在找出哪些元素的父元素是 section
,另外举一个例子,有选择器:
div.container #main > .article {}
浏览器在渲染时,先把全部类中包含 article
的元素取出来组成一个集合,而后对每个集合中的元素进行遍历,若是元素的父元素的 id
不为 main
则把元素从集合中删去。 再而后从这个元素的父元素开始向上找,没有找到一个标签名为 div
而且类名中有 container
的元素,就把元素从集合中删去,直到匹配全部的条件,因此在能不使用通配符的状况就尽可能不要使用它。
做者在这一节介绍了 id
和 class
选择器,为咱们选择元素提供了另外一种手段,利用它们能够不考虑元素在文档流中的层次结构,只要在元素中添加了 id
和 class
属性和值,咱们就能够经过它们的值来找到目标元素。
能够给
id
和class
属性设定任何值,但不能以数字或者特殊符号开头。
id
的用途是在页面中惟一地标识元素,因此每一个页面中每个 id
属性值都是独一无二的。而 class
的目的是为了标识一组具备相同特征的元素,也就是说一个页面中能够出现多个相同的类。
对于何时用 id
这个问题做者的观点是:
每个顶级区域都应该添加一个
id
,从而获得很是明确的上下文关系,以便编写 CSS 时只选择嵌套在相应区域内的标签。
对于何时使用 class
,因为 class
的目的是为了标识一组具备相同特征的元素,因此若是当页面中有一组元素具备某种相同的特征,就应该绝不犹豫的时候 class
了。
可是这里也应该注意不要乱用类,避免形成类泛滥,例如:
<nav> <ul> <li class="boy"><a href="#">Alan</a></li> <li class="girl"><a href="#">Andrew</a></li> <li class="boy"><a href="#">Angela</a></li> <li class="boy"><a href="#">Angus</a></li> <li class="girl"><a href="#">Anne</a></li> <li class="girl"><a href="#">Annette</a></li> </ul> </nav>
上面这个例子就是一个典型的类泛滥。
对于何时用 id 和何时用 class,我想每一个人都有不一样的见解,这里写说一下笔者的观点,笔者认为能不实用 id
就尽可能不使用 id
,实际状况是笔者基本不在 CSS 中使用 id
,由于在 CSS 的层叠机制中,id
的权重是 class
的10倍,其实不少状况下对某个元素设置某个不同的样式来覆盖以前的样式并无效果就是由于以前的样式权重过高,而为了达到效果就要编写权重更高的选择器,因此只有在某个元素须要被 JavaScript 找到的时候才会在某个元素中添加 id
,以即可以经过 document.getElementById()
方法来快速获取须要的元素。
属性选择器包括属性名选择器和属性值选择器,它们是经过元素的属性和值来获取元素的:
标签名[属性名] 标签名[属性名="属性值"]
例如:
img[title] {border: 2px solid blue;} a[target="_blank"] {background-image: url(_blank.png);}
上面第一段代码意思是,若是某个 img
标签带有 title
这个属性,那么就为它添加一个宽度为 2px 的蓝色实线边框。第二段代码的意思是,若是某个 a
标签带有 target
这个属性,而且这个属性的值为 _blank
那么就为这个元素添加一个背景图。
拓展:
其实除了以上两种属性选择器,还有其余几种属性选择器做者并无列出来,这里这几种其余的属性选择器做一个简单的介绍:
标签名[name^="value"] 让你匹配属性为 `name` 而且属性值以 `value` 开始的标签,如:a[href^= "http://"]则匹配全部具备 `href` 属性而且属性值以 `http://` 开始的标签。 标签名[name$="value"] 让你匹配属性为 `name` 而且属性值以 `value` 结束的标签,如:a[href$=".com"]则匹配全部具备 `href` 属性而且属性值以 `http://` 结束的标签。 标签名[name*="value"] 让你匹配属性为 `name` 而且属性值包含 `value` 的标签,如:a[href*= "renren"]则匹配全部具备 `href` 属性而且属性值包含 `http://` 的标签。 标签名[name|="value"] 让你匹配属性为 `name` 或者以 `name-` 开始的标签,如:p[lang|= "en"]则匹配具备 `lang` 属性的 `p` 标签,无论其属性值是 `en` 仍是 `en-us` 。 标签名[name~="value"] 让你匹配属性为 `name` 而且其属性值是具备多个空格分隔的值,其中一个值为 `value`,若有: <a title="I'm title for learn more">Learn More</a> 就能够用 p[title~="learn"] 来选择这个元素。
你应该注意到了这些属性选择器与前面两种属性选择器之间的差异了,经过这些属性选择器咱们能够很容易的作出许多意想不到的效果,好比:
a[href$=".pdf"] {background-image: url(pdf.png);}
好比上面这段代码就为连接是 pdf 文档链接的 a
标签添加一个表示这个连接是 pdf 文档的图片,而其余 href
属性的值不是以 .pdf
结尾的 a
标签就不会应用这条样式声明,让用户很清楚的判断这是一个什么类型的连接。
伪类这个叫法源自它们与类类似,但实际上并无类会附加到标记中的标签上,伪类分为两种:
UI(User Interface,用户界面)伪类:会在 HTML 元素处于某个状态时(好比鼠标指针位于链接上),为该元素应用 CSS 样式。
结构化伪类:会在标记中纯在某种结构上的关系时(好比某个元素是一组元素的第一个或者最有一个元素),为相应的元素应用 CSS 样式。
连接伪类
link: 连接就在那儿等着用户点击。
visited:用户此前点击过这个连接。
hover:鼠标指针正悬停在链接上。
active:连接正在i被点击(鼠标在元素上按下,尚未释放)。
注意以上几种连接伪类要按必定的顺序才有效果,为了方便记忆做者是这么建议的:"LoVe?HA!",大写字母就是每一个伪类的第一个字母,其实也能够这么记: "LoVe,HAte",其实都差很少就是了。
一个冒号(:)表示伪类,两个冒号(::)表示 CSS3 新增的伪元素。
:focus 伪类
表单中的文本字段在用户单击它时会得到焦点,例如:
input:focus {border: 1px solid blud;}
这段代码的意思就是当用户单击表单中的文本字段的时候,为该 input
标签添加宽度为 1px 的蓝色实线边框,须要注意的是,伪类的冒号要紧跟着标签名,之间不能有空格,不然该声明无效。
:target 伪类
若是用户点击一个指向页面中其余元素的连接,则哪一个元素就是目标(target),能够用 :target
伪类选中它,好比:
<a href="#more-info">More Information</a>
位于页面其余地方、id
为 more-info
的那个元素就是目标元素,该元素多是这样的:
<h2 id="more=info">This is the information you are looking for.</h2>
那么 CSS 规则以下:
#more-info:target {background: #eee;}
此时会在用户点击连接转向 id
为 more-info
的元素时,该目标元素的背景就会变成浅灰色。
first-child 、 last-child 和 nth-child(n)
e:first-child e:last-child
first-child
和 last-child
分别表明一组同胞元素中的第一个元素和最后一个元素,而 nth-child(n)
则表明一组同胞元素中的任何一个元素,其中 n 表示一个整数(也能够是 odd-奇数 或 even-偶数)或者也能够是一个算数表达式(2n + 1),例如:
<ul> <li>My Fast Pony</li> <li>Steady Trotter</li> <li>Slow Ol' Nag</li> </ul> ul li:first-child {color: black;} ul li:nth-child(2) {color: red;} ul li:last-child {color: blue;}
上面的 HTML 应用了上面的 CSS 规则后,无序列表的第一个元素字体颜色就会变成黑色,第二个元素变成红色,最后一个元素就变成蓝色。
顾名思义,伪元素就是文档中如有实无的元素,下面是几个比较经常使用的伪元素。
::first-letter 伪元素,好比:
p::first-letter {font-size: 300%;} 这样 `p` 标签的第一个字母大小就会变成原来的 3 倍了,而其余元素则不会。
::first-line 伪元素:能够选中文本段落的第一行。
::before 和 ::after 伪元素
e::before e::after 可用在特定元素前面或后面添加特殊内容,好比: <p class="age">25</p> .age::before { content: "Age: ";} .age::after { content: " years";} 这里须要注意的是,对于 `::before` 和 `::after` 伪元素,其 `content` 属性是必须的,还有就是搜索引擎不会取得伪元素的信息(由于它在文档流中并不存在),所以不要经过伪元素添加一些对搜索引擎来讲是重要的内容。
拓展:
其实伪元素前面冒号能够是两个也能够是一个,可是为了区别伪类,笔者建议你们仍是使用两个冒号。还有一个要注意的是,好比经过 ::before
和 ::after
伪元素为 class
为 pseudo-element
添加两个伪元素,则生成的两个伪元素分别处于 pseudo-element
元素的内部,也就是说是 pseudo-element
元素的子元素,而且分别位于 pseudo-element
元素的内容的最前面和最后面,代码以下:
<div class="pseudo-element"> <p>Pseudo Element</p> </div> .pseudo-element::after, .pseudo-element::before { content: ""; }
如上图所示,生成的两个伪元素分别处于 pseudo-element
元素的内部,而且分别位于 pseudo-element
元素的内容 p
标签的前面和后面,而不是以下图所示的位于 pseudo-element
元素外部的前面和后面:
层叠就是层叠样式表中的层叠,是一种样式在文档层次中逐层叠加的过程,目的是让浏览器面对某个标签特定属性值的多个来源肯定最终使用哪一个值。
层叠是 CSS 的核心机制,理解了它才能以最经济的方式写出最容易改动的 CSS,让文档外观在达到设计要求的同时,也给用户留下一些空间,让他们能根据须要更改文档的显示效果。
做者在这一节中介绍了样式的几种来源:
浏览器默认样式表
用户样式表
做者连接样式表
做者嵌入样式
做者行内样式
做者在书中是这么描述的:
浏览器会按照上面的顺序依次检查每一个来源的样式,并在有定义的状况下,更新对每一个标签属性值的设定,整个检查更新过程结束后,再将每一个标签以最终设定的样式显示出来。
做者在这一节主要介绍了特指度的计算方法,相比做者个计算方式,笔者我的仍是比较喜欢本身以前的计算方式,虽然差很少,以下:
// 首先规定四个等级:A - B - C - D
A 等级表明内联样式:例如 style=" "
,权值为:1000;
B 等级表明 ID 选择器:例如 #main
,权值为:100;
C 等级表明类、伪类和属性选择器: .class
和 [title]
,权值为:10;
D 等级表明元素(标签)名或者伪元素选择器:例如 p
和 ::after
,权值为:1。
//计算完每一个值后再将每一个值加起来,哪一个值大哪一个值的权重就高。
例如:
body #main .class a[title]::after {}
咱们先分析它由哪些选择器构成,上面这条规则有一个 id
选择器(#main
),一个类选择器(.class
),一个属性选择器([title]
)、一个伪元素选择器(::after
)和两个标签名选择器(body
和 a
),因此它的权重就等于:
100 × 1 + 10 × 2 + 1 × 3 = 123
还有一点要注意的是,权重值 001(12) 与 0020 相比,任然是 0020 的权重更高,对于权重同样的状况,则后声明的样式更高。
做者在本章介绍了 CSS 的一些规则,好比各类选择器的使用,层叠机制,还有权重的计算。