《精通csss》
添加样式
css选择符
类型与后代选择符是最基本的选择符。
-
类型选择符用于选择特定类型的元素,比如段落or标题元素。类型选择符也被称为元素选择符
p { color: black; }
-
后代选择符用于选择某个或某族元素的后代。后代选择符的写法是在两个选择符之间添加空格
blockquote p { padding-left: 2em; }
子选择符与同辈选择符
使用相邻同辈选择符(+),可以选择位于某个元素后面并与该元素拥有共同父元素的元素。
h2 + p {
font-ize: 1.4em;
font-weight: bold;
color: #777;
}
>
和+
被称为组合子,因为它们描述了自身两侧的选择符组合的方式。
一般同辈组合子: ~
。
用前面的例子来说明,使用一般同辈组合子可以选择 h2 元素后门的所有段落
h2 ~ p {
font-size: 1.4em;
font-weight: bold;
color: #777;
}
相邻同辈选择符和一般同辈选择符都不会选择前面的同辈元素
属性选择符
- 要匹配以某些字符开头的属性值,在等号前面加上插入符(^)
a[href^="http:"]
- 要匹配以某些字段结尾的属性值,在等号前面加上美元符号($)
img[src$=".jpg"]
- 要匹配包含某些字符的属性值,在等号前面加上星号(*)
a[href*="/about/"]
- 要匹配以空格分隔的字符串中的属性值(如
rel
属性的值),在等号前面家还是那个波浪号(~)
a[rel~=next]
- 选择开头是指定值或指定值后连着一个短划线的情况(en-us),在等号前面加上竖线(|)
a[lang|=en]
这条规则可以匹配属性值
en
和en-us
,暗示这个选择符很适合选择属性中的语言代码,因为语言代码都是以短划线分隔的。
理论上可以对一个 class 属性使用这个选择符,比如用来匹配 message 和 message-error,但实际上这种方法不够灵活,万一以后 message 类前面有添加了别的类名,比如 class="box message"
,这个选择符就会失效
伪元素
-
::first-letter
伪元素可以选择一段文本的第一个字符 -
::first-line
伪元素可以选择一段文本的第一行
使用伪元素插入内容时要注意,不能插入对交互有实质影响的内容,以避免CSS不能正确加载。
另外,屏幕阅读器也没有统一的方式解释伪元素,有的会直接忽略它们,有的则会读取其中的内容
伪类
目标伪类::target
伪类
它匹配的元素有一个ID属性,该属性的只出现在当前页面URL末尾的井号(#)后边
如果打开链接 http://example/com/blog/1/#comment-3
,找到该页面中标记为:
<article class="comment" id="conment-3">...</article>
的评论,可以使用以下规则高亮该条评论
.comment:target {
background-color: #FF6666;
}
反选伪类::not()
伪类(选择符)
如果被标记为”投票否决(downvoted)“的评论都有一个特殊的类名,可以使用以下规则:
.comment:target:not(.comment-downvoted) {
background-color: #FF666;
}
结构化伪类
-
:nth-child(n)
伪类,从第一个元素正序计算匹配第n个元素
更多奇妙的用法:
-
odd(奇数) & even(偶数)
-
数值表达式(3n+4 等)
制作(模拟)CSS随机数的方法之一
-
负值
-
:nth-child(-n+3)
,只会选择前3个元素
-
-
:nth-last-child(n)
伪类,从最后一个元素倒序计算匹配第n个元素 -
:first-child
,相当于直观版的:nth-child(1)
。 -
:last-child
,相应于:nth-last-child(1)
-
:only-of-type
,相应选择特定类型的唯一子元素
明智地使用结构化伪类:
.column:nth-last-of-type(4):first-child,
.column:nth-last-of-type(4):first-child ~ .column {
/* 在有4个同类型 .column 元素的情况下应用此规则 */
}
如果以上规则适用,则意味着倒数第4个子元素同事也是正数的第1个子元素,也就是恰好有4个想同类型的子元素都有 .column
类
表单伪类
- required 属性,必填属性
<input type="text" name="field-name" id="field-name" required>
如果想对这个必填框添加独特的样式,可以使用 :required
伪类
input:required {
outline: 2px solid #000;
}
- optional 属性,非必填属性,使用方式和 required 一样
使用 :optional
伪类对非必填框设置样式
input:required {
border-color: #CCC;
}
-
:valid
伪类,有效消息 -
:invaild
伪类,无效消息
更多伪类设置,参考MDN文档:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-classes
层叠
CSS的关于层叠的层级概念:
- 作者样式表,即由网站开发者所编写的样式
- 用户样式表,用户可以通过浏览器的设置选项,为网页应用自己的样式
- 浏览器的默认样式表
CSS允许用户使用
!important
覆盖任何规则,包括网站作者使用的!important
标注的规则。也就是说,在
!important
面前,用户样式是最大的
之间的层级关系是:
用户 !impotant
> 作者 !important
> 作者样式表 > 用户样式表 > 浏览器默认样式
当层级相等时,后面定义的规则优先应用,即后来者覆盖掉前者设置的样式
特殊性(权值)
CSS对不同的情况都有不同的权值设置:
- 内联(
style=""
),权值 1000 - ID选择器(
#content
),权值 100 - 类选择器(
.class
),权值 10 - 元素选择器(
div
),权值 1 - 通用选择符(
*
),权值 0,慎用(少用为好)此选择符
权值高的规则会被优先应用
权值相同的规则,则用“后浪推前浪”的方式应用
层叠次序
伪类 :hover
、:visited
、:focus
、:active
的权值都是一样的,也就是说,伪类的设置顺序会直接影响规则是否能被正确应用
如果将 :visited
伪类设置在 :hover
之前,那么在访问过目标元素后,:hover
伪类的规则会被覆盖
控制特殊性
先为公用元素设置默认样式,然后在更特殊的元素上覆盖这些样式
简化选择符,降低特殊性:
body {
color: black;
}
.intro {
font-size: 1.2em;
color: gray;
}
.intro-highlighted {
color: black;
background: lightgray;
}
.intro-hightlighted a {
color: green;
}
a .call-to-action {
text-decoration: none;
background-color: green;
color: white;
padding: 10px;
}
去掉ID选择符,把所有选择符的特殊性降到最低。
去掉介绍性文本上下文的引用。
利用特殊性,可以为公用元素设置默认样式,然后在更特殊的元素上覆盖这些样式
继承
继承的属性值没有任何特殊性,其权值连0都说不上。
这意味着使用特殊性为0的通用选择符设置的样式都可覆盖继承的样式
* {
color: black;
}
h2 {
color: red;
}
<h2>Hello world!<em>this is CSS</em></h2>
表面上看,em 元素会继承 h2 的红色字体,但实际上 em 元素的样式被通用选择符设置的黑色字体样式覆盖了
所以更好的利用继承,可以设置 body 的样式,这样所有的元素都会继承 body 设置的样式,也就不会发生未知覆盖了
正如合理利用层叠可以简化CSS一样,合理利用继承有助于减少选择符的数量,降低复杂性。
不过如果有大量的元素继承了不同的样式,那么查找样式的来源会比较麻烦
为文档应用样式文件
link 与 style 元素
为网页引用添加css样式有两个方案(@import可以单独使用,亦可结合 link / style 元素使用)
- style元素
优点: 无需等待下载,打开即用
缺点:元素内设置的样式无法复用
- link元素
优点:相当灵活,可多次复用样式
缺点:若文件较大或网络环境不佳,页面无样式会使体验变差
- @import命令
优点:更灵活
缺点:需要下载所有被 import 的文件,下载量大
性能
度量Web性能的一个重要指标是页面打开到完全显示的时间,也称为“渲染时间” or “上屏时间”
在CSS层面提高页面性能的方法:
- 减少HTTP请求
线上网页最好把需要加载的CSS文件数量控制在1~2个。
只用一个 link 元素加载CSS文件,然后在文件中使用 @import,并不能把请求控制为1个
线上网页中尽量不要使用 @import
- 压缩和缓存内容
使用 GZIP 压缩线上资源。
- 不让浏览器渲染阻塞 JavaScript
讲js文件放置到body结束标签前的位置,且给js文件添加以下两种属性:
- async 属性,异步加载脚本,不阻塞 HTML 解析,但会在脚本加载完成执行时阻断HTML解析
- defer 属性,异步加载脚本,但在HTML解析完成后再执行加载的脚本
至于两种属性使用哪一个,要看js脚本的内容