深入解析css

第一章 层叠、优先级和继承

css里的c代表cascade,层叠,层叠决定了如何解决冲突,是css语言的基础。层叠会依据三种条件解决冲突。

(1) 样式表的来源:样式是从哪里来的,包括你的样式和浏览器默认样式等。

(2) 选择器优先级:哪些选择器比另一些选择器更重要。

(3) 源码顺序:样式在样式表里的声明顺序。

声明:color: black;
包含在大括号内的一组声明被称作一个声明块。
声明块前面有一个选择器.
选择器和声明块一起组成了规则集(ruleset)

1
2
3
body {
color: black;
}
  1. 样式表的来源

    你添加到网页里的样式表并不是浏览器唯一使用的样式表,还有其他类型或来源的样式表。你的样式表属于作者样式表,除此之外还有用户代理样式表,即浏览器默认样式。用户代理样式表优先级低,你的样式会覆盖它们.

    ! important声明会被当作更高优先级的来源,因此总体的优先级按照由高到低排列如下所示:
    (1) 作者的!important
    (2) 作者的样式表
    (3) 用户代理样式表

    层叠规则顺序:不同来源的声明-内联声明-选择器优先级声明-源码顺序声明

  2. 理解优先级

    浏览器将优先级分为两部分:HTML的行内样式和选择器的样式。

  3. 行内样式
    如果用HTML的style属性写样式,这个声明只会作用于当前元素。实际上行内元素属于“带作用域的”声明,它会覆盖任何来自样式表或者<style>标签的样式。行内样式没有选择器,因为它们直接作用于所在的元素

  4. 选择器优先级
    伪类选择器(:hover)和属性选择器([type=”input”])与一个类选择器的优先级相同。
    通用选择器(*)和组合选择器(>,+,~)对优先级无影响。

  5. 源码顺序
    层叠的第三步,也是最后一步,是源码顺序。如果两个声明的来源和优先级相同,其中一个声明在样式表中出现较晚,或者位于页面较晚引入的样式表中,则该声明胜出。

  6. 层叠值
    浏览器遵循三个步骤,即来源,优先级,源码顺序来解析网页上每个元素的每个属性。
    处理层叠的两条通用法则:
    1.在选择器中不要使用ID
    2.不要使用!important

  7. 继承

    如果一个元素的某个属性没有层叠值,则可能继承祖先元素的值。比如给<body>元素加上font-family,
    就不必给每个元素明确指定字体。但不是所有属性都能被继承。只有特定属性能被继承,主要和文本相关的
    属性:
    color、font、font-family、font-size、font-weight、font-variant、font-style、
    line-height、letter-spacing、text-align、text-indent、text-transform、white-space
    word-spacing

    还有一些其他属性能被继承,比如列表属性:
    list-style、list-style-type、list-style-position、list-style-image

    表格的边框属性: border-collapse、border-spacing 也能被继承

  8. 特殊值

    有两个特殊值可以赋给任意属性,用于控制层叠:inherit和initial

  9. inherit关键字
    可以用继承代替一个层叠值,比如覆盖另一个值,这样该元素就会继承其父元素的值。

  10. initial关键字
    每个css属性都有初始默认值,给属性设置initial会有效将其重置为默认值,比如给<body>设置color: #111; 那么默认的其子元素文本颜色都继承这个属性值,给其设置color: initial,会使其文本颜色变为
    color: black; 因为黑色是color属性的初始值。

    注:声明display: initial等价于display: inline。不管应用于哪种类型的元素,他都不会等于display:block。因为initial重置的是属性的初始值,而不是元素的初始值。inline才是display属性
    的初始值。

  11. 简写属性

    简写属性是用于同时给多个属性赋值的属性。比如font是一个简写属性,还有:background,border,border-width

  12. 简写属性会默默覆盖其他样式
    大多数简写可以省略一些值,只指定我们关注的值,但这样仍然会设置省略的值,即它们会被隐式的设置为初始值initial.这样会覆盖其他定义的样式

  13. 理解简写值的顺序
    可以设置border: 1px solid black或者border: black 1pxsolid,两者都会生效。这是因为浏览器知道宽度、颜色、边框样式分别对应什么类型的值。但是有很多属性的值很模糊。在这种情况下,值的顺序很关键

    (1)上、右、下、左
    margin、padding、边框属性
    (2)水平、垂直
    上右下左只适合给盒子设置四个方向的值的属性。还有一些属性只支持最多指定两个值,这些属性包括background-position、box-shadow、text-shadow,比如box-shadow: 10px 2px #000;
    指定水平方向偏移量10px,垂直方向偏移量2px,先水平再垂直

第二章 相对单位

1.em
em的复杂之处在于同时用它指定一个元素的字号和其他属性。这时,浏览器必须先计算字号,然后使用这个计算值去算出其余的属性值。这两类属性可以拥有一样的声明值,但是计算值不一样。
例如:

1
2
3
4
5
6
7
body {
font-size: 16px;
}
.title {
font-size: 1.2em; // 计算值为16*1.2=19.2px
padding: 1.2em; // 计算值为19.2*1.2=23.04px
}

字体缩小的问题

1
2
3
4
5
6
body {
font-size: 16px;
}
ul {
font-size: 0.8em;
}
1
2
3
4
5
6
7
8
9
<ul> <!-- font-size: 16px * 0.8 -->
<li>top level</li>
<ul><!-- font-size: 16px * 0.8 * 0.8 -->
<li>second level</li>
<ul><!-- font-size: 16px * 0.8 * 0.8 * 0.8-->
<li>third level</li>
</ul>
</ul>
</ul>

2.rem
在文档中,根节点是所有其他元素的祖先节点。根节点有一个伪类选择器(:root),可以用来选中它自己。这等价于类型选择器html,但是html的优先级相当于一个类名,而不是一个标签.
rem是root em的缩写。rem不是相对于当前元素,而是相对于根元素的单位.不管在文档的什么位置使用rem,1.2rem都会有相同的计算值:1.2乘以根元素的字号.

1
2
3
4
5
6
:root {  /*  :root伪类相当于类型选择器html */
font-size: 1em; /* 根元素上的em是相对于浏览器默认值的,16px */
}
ul {
font-size: 0.8rem;
}

拿不准的时候,用rem设置字号,用px设置边框,用em设置其他大部分属性.

em和rem都是相对于font-size定义的。

3.视口的相对单位
视口——浏览器窗口里网页可见部分的边框区域。它不包括浏览器的地址栏、工具栏、状态栏。

vh:视口高度的1/100。
vw:视口宽度的1/100。
vmin:视口高度的1/100。1. vw:视口宽度的1/100。
vmax:视口宽、高中较大的一方的1/100。

当一个元素的宽和高为90vmin时,不管视口的大小或者方向是什么,总会显示成一个稍小于视口的正方形

vw可以结合calc()设置字号,对于iphone6 375到1200px,字号从11.75到20px

1
2
3
:root {
font-size: calc(0.5em + 1vw);
}

4.自定义属性即css变量

1
2
3
4
5
6
:root {
--main-foot: Arial, sans-serif;
}
p {
font-family: var(--main-foot);
}

var()函数接受第二个参数,它指定了备用值。如果第一个参数指定的变量未定义,那么就会使用第二个值

如果var()函数算出来的是一个非法值,对应的属性就会设置为其初始值。比如,如果在padding: var(–brand-color)中的变量算出来是一个颜色,它就是一个非法的内边距值。这种情况下,内边距会设置为0.

自定义属性就像作用域变量一样,自定义属性就像作用域变量一样

1
2
3
4
5
6
7
8
9
:root {
--main-color: black;
}
.panel {
--main-color: white
}
p {
color: var(--main-color);
}
1
2
3
4
5
6
<body>
<p>黑色</p>
<div class="panel">
<p>白色</p>
</div>
</body>

使用js改变属性:

1
2
var rootElement = document.documentElement;
rootElement.style.setProperty('--main-color', '#ccc');

第三章 盒模型

1.盒模型
box-sizing: content-box; 设置元素宽高只设置内容盒子大小
box-sizing: border-box; width和height属性会设置内容、内边距及边框的大小总和。

{
1
2
3
4
5
6
7
  box-sizing: border-box;
}
*,
::before,
::after {
box-sizing: .inherit;
}

盒模型通常不会被继承,但是使用inherit关键字可以强制继承.这样可以不覆盖第三方组件的盒模型.

2.垂直居中
如果给块级元素设置vertical-align:middle;块级元素的内容不会垂直居中,vertical-align声明只会影响行内元素或者table-cell元素。对于行内元素,它控制着该元素跟同一行内其他元素之间的对齐关系。比如一行内图片和文字对齐方式。

3.负外边距
负外边距的具体行为取决于设置在元素的哪边。如果设置左边或顶部的负外边距,元素就会相应地向左或向上移动,导致元素与它前面的元素重叠,如果设置右边或者底部的负外边距,并不会移动元素,而是将它后面的元素拉过来。给元素底部加上负外边距并不等同于给它下面的元素顶部加上负外边距

4.外边距折叠
所有相邻的顶部和底部外边距会折叠到一起,即使两个元素不是相邻的兄弟节点也会产生外边距折叠。只有上下外边距会产生折叠,左右外边距不会折叠。
折叠外边距的大小等于相邻外边距中的最大值

第七章 定位和层叠上下文

1.固定和绝对定位可以设置top,right,bottom,left改变定位元素的大小,相对定位不可以
2.固定定位相对于视口定位,绝对定位相对于最近定位父元素定位,如果没有定位父元素,则相对于初始包含块定位
3.初始包含块是视口和html根元素之间的内容
4.相对定位,left和right, top和bottom不能同时使用,left和right一起使用时,right会被忽略,top和bottom一起使用时right会被忽略
5.通常情况下(使用定位之前),元素在HTML里出现的顺序决定了绘制的顺序。
6.浏览器会先绘制所有非定位的元素,然后绘制定位元素。默认情况下,所有的定位元素会出现在非定位元素前面。
7.相对定位依赖于文档流,绝对定位元素依赖于它的定位祖先节点。这时候需要用z-index属性来控制它们的层叠行为。
8.z-index属性的值可以是任意整数(正负都行)。z表示的是笛卡儿x-y-z坐标系里的深度方向。拥有较高z-index的元素出现在拥有较低z-index的元素前面。拥有负数z-index的元素出现在静态元素后面
9.z-index只在定位元素上生效,不能控制静态元素;给一个定位元素添加z-index属性可以创建层叠上下文。
10.一个层叠上下文包含一个元素或由浏览器一起绘制的一组元素。其中一个元素作为层叠上下文的根,比如给一个定位元素设置z-index属性,该元素就是新的层叠上下问的根。
11.层叠上下文负责决定哪些元素出现在另一些元素前面,而BFC负责处理文档流,以及元素是否会重叠
12.创建层叠上下文方式:给定位元素添加z-index属性,opacity属性小于1,transform、,filter属性,跟节点html
13.所有层叠上下文内的元素会按照以下顺序,从后到前叠放:

1.层叠上下文的根
2.z-index为负的定位元素(及其子元素)
3.非定位元素
4.z-index为auto的定位元素(及其子元素)
5.z-index为正的定位元素(及其子元素)

第八章 响应式设计

1.响应式设计的三大原则如下

(1) 移动优先。这意味着在实现桌面布局之前先构建移动版的布局。不要忘记给视口添加meta标签。
(2) @media规则。使用这个样式规则,可以为不同大小的视口定制样式。用这一语法,通常叫作媒体查询(media queries),写的样式只在特定条件下才会生效。使用媒体查询,按照视口从小到大的顺序渐进增强网页。
(3) 流式布局(fluid layout)。这种方式允许容器根据视口宽度缩放尺寸。

选择器

1.基础选择器

  1. tagname——类型选择器或者标签选择器。该选择器匹配目标元素的标签名。它的优先级是0,0,1。例如:p、h1、strong。
  2. class——类选择器。该选择器匹配class属性中有指定类名的元素。它的优先级是0,1,0。例如:.media、.nav-menu。
  3. #id——ID选择器。该选择器匹配拥有指定ID属性的元素。它的优先级是1,0,0。例如:#sidebar。
  4. *——通用选择器。该选择器匹配所有元素。它的优先级是0,0,0。

2.组合器

  1. 子组合器(>)——匹配的目标元素是其他元素的直接后代。例如:.parent > .child。
  2. 相邻兄弟组合器(+)——匹配的目标元素紧跟在其他元素后面。例如:p + h2。
  3. 通用兄弟组合器(~)——匹配所有跟随在指定元素之后的兄弟元素。注意,它不会选中目标元素之前的兄弟元素。例如:li.active ~ li。

3.伪类选择器

伪类选择器用于选中处于某个特定状态的元素。伪类选择器始终以一个冒号(:)开始。优先级等于一个类选择器(0,1,0)

  1. :first-child——匹配的元素是其父元素的第一个子元素。
  2. :last-child——匹配的元素是其父元素的最后一个子元素。
  3. :only-child——匹配的元素是其父元素的唯一一个子元素(没有兄弟元素)。
  4. :nth-child(an+b)——匹配的元素在兄弟元素中间有特定的位置。
  5. :nth-last-child(an+b)——类似于:nth-child(),但不是从第一个元素往后数,而是从最后一个元素往前数。
  6. :first-of-type——类似于:first-child,但不是根据在全部子元素中的位置查找元素,而是根据拥有相同标签名的子元素中的数字顺序查找第一个元素。
  7. :last-of-type——匹配每种类型的最后一个子元素。
  8. :only-of-type——该选择器匹配的元素是满足该类型的唯一一个子元素。
  9. :nth-of-type(an+b)——根据目标元素在特定类型下的数字顺序以及特定公式选择元素,类似于:nth-child。
  10. nth-last-of-type(an+b)——根据元素类型以及特定公式选择元素,从其中最后一个元素往前算,类似于:nth-last-child。
  11. :not(<selector>)——匹配的元素不匹配括号内的选择器。括号内的选择器必须是基础选择器,它只能指定元素本身,无法用于排除祖先元素,同时不允许包含另一个排除选择器。
  12. :empty——匹配的元素必须没有子元素。注意,如果元素包含空格就无法由该选择器匹配,因为空格在DOM中属于文本节点。
  13. :focus——匹配通过鼠标点击、触摸屏幕或者按Tab键导航而获得焦点的元素。
  14. :hover——匹配鼠标指针正悬停在其上方的元素。
  15. :root——匹配文档根元素.
  16. :disabled——匹配已禁用的元素,包括input、select以及button元素。
  17. :enabled——匹配已启用的元素,即那些能够被激活或者接受焦点的元素。
  18. :checked——匹配已经针对选定的复选框、单选按钮或选择框选项。
  19. :invalid——根据输入类型中的定义,匹配有非法输入值的元素。例如,当的值不是一个合法的邮箱地址时,该元素会被匹配(Level4)。
  20. :valid——匹配有合法值的元素(Level4)。
  21. :required——匹配设置了required属性的元素(Level4)。
  22. :optional——匹配没有设置required属性的元素

4.伪元素选择器

伪元素类似于伪类,但是它不匹配特定状态的元素,而是匹配在文档中没有直接对应HTML元素的特定部分.
以双冒号(::)开头,尽管大多数浏览器也支持单冒号的语法以便向后兼容。伪元素选择器的优先级与类型选择器(0,0,1)相等

  1. ::before——创建一个伪元素,使其成为匹配元素的第一个子元素。该元素默认是行内元素,可用于插入文字、图片或其他形状。必须指定content属性才能让元素出现,例如:.menu::before。
  2. ::after——创建一个伪元素,使其成为匹配元素的最后一个子元素。该元素默认是行内元素,可用于插入文字、图片或其他形状。必须指定content属性才能让元素出现,例如:.menu::after。1.
  3. ::first-letter——用于指定匹配元素的第一个文本字符的样式,例如:h2::first-letter。
  4. ::first-line——用于指定匹配元素的第一行文本的样式。
  5. ::selection——用于指定用户使用鼠标高亮选择的任意文本的样式。通常用于改变选中文本的background-color。只有少数属性可以使用,包括color、background-color、cursor、text-decoration。

5.属性选择器

属性选择器用于根据HTML属性匹配元素。其优先级与一个类选择器(0,1,0)相等

以下选择器区分大小写:

  1. [attr]——匹配的元素拥有指定属性attr,无论属性值是什么,例如:input[disabled]。
  2. [attr=”value”]——匹配的元素拥有指定属性attr,且属性值等于指定的字符串值,例如:input[type=”radio”]。
  3. [attr^=”value”]——“开头”属性选择器。该选择器匹配的元素拥有指定属性attr,且属性值的开头是指定的字符串值,例如:a[href^=”https”]。
  4. [attr$=”value”]——“结尾”属性选择器。该选择器匹配的元素拥有指定属性attr,且属性值的结尾是指定的字符串值,例如:a[href$= “.pdf”]。
  5. [attr*=”value”]——“包含”属性选择器。该选择器匹配的元素拥有指定属性attr,且属性值包含指定的字符串值,例如:[class*=”sprite-“]。
  6. [attr~=”value”]——“空格分隔的列表”属性选择器。该选择器匹配的元素拥有指定属性attr,且属性值是一个空格分隔的值列表,列表中的某个值等于指定的字符串值,例如:a[rel=”author”]。
  7. [attr|=”value”]——匹配的元素拥有指定属性attr,且属性值要么等于指定的字符串值,要么以该字符串开头且紧跟着一个连字符(-)。适用于语言属性,因为该属性有时候会指定一种语言的子集(比如墨西哥西班牙语,es-MX,或者普通的西班牙语,es),例如:[lang|=”es”]。

不区分大小写的属性选择器:将i添加到结束方括号前面,input[value=”search”i]