深入CSS
一、CSS的版本(level)
css Level 1- css Level 2(CSS2.2规范)
- css Level 3
- Color Module Level 3
- Selectors Level 3
- Media Queries
- Fonts Level 3
- ...
在css2.2之前,把css所有标准放在一起去管理,这样推进起来版本升级比较难,后来在css3的版本中,将css标准分成几个模块来管理。
二、css选择器
1. 简单选择器
- 通配选择器
*
- 标签选择器
E
- 类选择器
.class-name
- Id选择器
#id_name
2. 属性选择器
/* 具有某个属性 */
[disabled]
/* 属性为指定的值 */
[type="checkbox"]
/* 属性值包含某个字符串 */
[href*="example"]
/* 属性值以某个字符串开头 */
[href^="http:"]
/* 属性值以某个字符串结束 */
[href$="jpg"]
/* 属性值以空格分割后包含某个字符串 */
[lang~="zh-cn"]
复制代码
3. 伪类选择器
a:link { ... } /* 未访问过的链接 */
a:visited { ... } /* 已访问过的链接 */
a:hover { ... } /* 鼠标移到链接上的样式 */
a:active { ... } /* 鼠标在连接上按下时的样式 */
a:focus { ... } /* 获得焦点时的样式 */
input:disabled { ... } /* 禁用时的样式 */
input:checked { ... } /* 选中时的样式 */
复制代码
4. 结构性伪类
:first-child
:last-child
:nth-child
:first-of-type
:last-of-type
:nth-of-type
:empty
复制代码
详细介绍在mdn 选择器文档
5. 组合器(combinator)
后代组合器 E F
亲子组合器 E > F
兄弟选择器 E ~ F
相邻兄弟 E + F
复制代码
6. 伪元素
::before
::after
::first-letter
::first-line
复制代码
举个栗子?
<p>莫哈韦沙漠不仅纬度较高,而且温度要稍微低些,是命名该公园
的短叶丝兰——<a href="#">约书亚树</a>的特殊栖息地。约书亚
树以从茂密的森林到远远间隔等各种形式出现。除了约书亚树森林之
外,该公园的西部包括加州沙漠里发现的最有趣的地质外观。</p>
<style>
p {
line-height: 1.7
}
p::first-letter {
line-height: 1.5;
background: #F44336;
color: #fff;
font-size: 200%;
float: left;
padding: 0 0.2em;
margin-right: 0.2em;
}
a::after {
content: '⚓'
}
</style>
复制代码
结果是这样子的:
- 利用
::first-letter
把第一个文字选中,修改样式。 - 利用
::after
把a标签文字的最后面添加一个特殊文字。
再举个栗子?
实现一个toggle
<div class="toggle">
<input type="checkbox" checked id="t">
<label for="t"></label>
</div>
<style>
.toggle {
width: 80px;
height: 26px;
background: #333;
margin: 20px auto;
position: relative;
border-radius: 50px;
box-shadow: inset 0px 1px 1px rgba(0,0,0,0.5),
0px 1px 0px rgba(255,255,255,0.2);
}
.toggle:after {
content: 'OFF';
color: #fff;
position: absolute;
right: 10px;
z-index: 0;
font: 12px/26px Arial, sans-serif;
font-weight: bold;
text-shadow: 1px 1px 0px rgba(255,255,255,.15);
}
.toggle:before {
content: 'ON';
color: #f66;
position: absolute;
left: 10px;
z-index: 0;
font: 12px/26px Arial, sans-serif;
font-weight: bold;
}
.toggle label {
display: block;
width: 34px;
height: 20px;
cursor: pointer;
position: absolute;
top: 3px;
left: 3px;
z-index: 1;
background: #fcfff4;
background: linear-gradient(top, #fcfff4 0%,
#dfe5d7 40%, #b3bead 100%);
border-radius: 50px;
transition: all 0.4s ease;
box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.3);
}
.toggle input[type=checkbox] {
visibility: hidden;
}
.toggle input:checked + label {
left: 43px;
}
</style>
复制代码
toggle演示:
缺点:- 只能点击白色区域才能切换状态
- 不能用键盘来控制
三、选择器的特异度(权重)
解释一下:- 特异度的算法是:
- 内联样式在千位
- id在百位
- 类和伪类在十位
- 元素和伪元素在个位
#nav .list li a:link
包含1个id标签#nav
,1个class类.list
,1个伪类:link
,2个标签a
和li
,所以它的特异度(权重)是 122.hd ul.links a
包含两个class类.hd
和.links
,两个元素ul
和a
,所以它的特异度是 22
属性覆盖
- 同一个级别的下面的样式会覆盖上面的
- 优先级高的会覆盖优先级低的相同属性
! important
- 如果我们不想让样式被其他优先级高的属性覆盖,我们可以给这个属性后面加
!important
- 如果我们想把上面带有
!important
的属性覆盖,就需要给下面的优先级高的属性也添加!important
就可以了
四、css样式的来源
- 页面开发者
- 用户 (比如开放用户对页面字体的大小,样式设置等等)
- 浏览器预设
用户样式:可以将设置后的样式存在本地css文件中,打开页面时自动加载 浏览器预设样式:
哪条css样式会起作用呢?(css优先级)
-
找出匹配到的该属性所有声明
-
根据规则来源,优先级从低到高:
- 浏览器预设
- 用户设置
- 网页样式
-
同一来源中,越特殊优先级越高
-
特异度一样时,书写顺序在后面的优先级高
有!important时的变化
- 找出匹配到的该属性所有声明
- 根据规则来源,优先级从低到高:
- 浏览器预设
- 用户设置
- 网页样式
- 含!important的网页样式
- 含!important的用户设置样式
- 同一来源中,越特殊优先级越高
- 特异度一样时,书写顺序在后面的优先级高
五、课后练习题
- 单选题:关于标签嵌套的正确说法是?
A. table标签可以直接嵌套tr
B. video中可以嵌套img作为视频的封面图片
C. button中不能包含其他任何标签
D. p标签中可以嵌套div
答案:A
解析:video里面可以放track、source等标签,封面图用poster属性,所以B是错误的
button里面可以嵌套标签,如span标签,但<input type='button'/>
是单标签不能嵌套。
p是代表段落,里面只能放段落内容,不包含div
知识点:<video>
<video>
的属性
属性 | 描述 |
---|---|
width | 视频宽度 |
height | 视频高度 |
controls | 显示控制条 |
poster | 贴图 |
autoplay | 自动播放 |
muted | 默认状态下静音 |
volume | 控制音量 |
preload | 预加载 |
loop | 循环播放 |
src | 资源路径 |
currentSrc | 当前播放路径 |
currentTime | 播放时间的控制 |
duration | 播放时长 |
volume 音量控制api
<video id="_volume" src="./test.mp4" width="200" height="200" muted preload controls autoplay></video>
<script>
// 获取video元素
var v = document.getElementById("_volume");
// 音量范围0-1,将音量设置为50%
v.volume = 0.5;
</script>
复制代码
currentTime 播放进度api
<!-- 播放时间控制 -->
<video id="_currentTime" src="./test.mp4" width="200" height="200" muted preload controls autoplay></video>
<script>
var v = document.getElementById("_currentTime");
// 播放进度设置为1分钟
// currentTime的单位:秒
v.currentTime = 60;
</script>
复制代码
src 视频资源api
<!-- 播放地址的切换 -->
<video id="_src" src="./test.mp4" width="200" height="200" muted preload controls autoplay></video>
<script>
var v = document.getElementById("_src");
setTimeout(() => {
// 两秒后视频资源切换为test2.mp4
// 场景:当用户选择高清,普清时,通过src地址来切换清晰度
v.src = './test2.mp4'
}, 2000);
</script>
复制代码
也可以在video里面嵌入source标签, 通过currentSrc
获取当前视频播放地址
<video id="_source" width="200" height="200" controls>
<source src="./video.mp4" type="video/mp4">
<!-- 备用地址 -->
<source src="./video.mp4" type="video/mp4">
</video>
<script>
var v = document.getElementById("_source");
// 场景:通过遍历source的地址,找到currentSrc地址前的地址,上传错误地址到服务器
setTimeout(() => {
console.log('当前播放的src', v.currentSrc)
v.currentSrc = './test.mp4'
}, 2000);
</script>
复制代码
<video>
的事件
事件 | 描述 |
---|---|
loadstart | 视频播放时触发 |
durationchange | 当视频的时长数据发生变化时触发 |
loadedmetadata | 视频源数据加载完成 |
loadeddata | 当前帧的数据已加载,但没有足够的数据来播放指定视频的下一帧触发。 |
progress | 当浏览器正在下载指定的视频时触发 |
canplay | 视频有帧播放时触发 |
canplaythrough | 当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的视频时触发 |
play | 视频播放时触发 |
pause | 视频暂停时触发 |
ended | 视频播放完毕 (用途:向视频添加广告) |
seeking | 用户在视频中移动/跳跃到新的位置时触发 |
seeded | 寻找资源完毕 |
waiting | 当视频无法继续播放,且需要加载时触发 |
timeupdate | 进度条进度每更新一次,触发一次timeupdate 事件 |
error | 视频出现错误 |
<video>
创建时,拿不到时长信息,因此在初始状态下,duration
为NaN
。
以chrome为例子,当视频处于加载过程中时,会依次发生以下事件:
progress
(加载视频资源)loadstart
(此时duration
为NaN)progress
(浏览器加载视频视频, 可触发多次)durationchange
(此时duration
为总时长)loadedmetadata
(视频源数据加载完毕)loadeddata
(当前帧加载完毕)canplay
(视频可以播放,但没有缓冲)progress
(浏览器加载视频视频, 可触发多次)canplaythrough
(视频缓冲完毕, 可以流畅的播放)progress
(浏览器自动缓存数据, 可触发多次)
场景1: 当用户点击按钮跳转到新的位置时,会触发下列事件
seeking
寻找资源progress
加载资源seeked
寻找完毕canplay
可以播放当前帧canplaythrough
可以连续播放
场景2: 当用户播放时,点击跳转按钮,会触发下列事件
seeking
寻找资源play
播放视频progress
加载资源waiting
等待资源加载seeked
寻找完毕canplay
可以播放当前帧playing
播放状态下,资源加载完毕,视频继续播放canplaythrough
视频有足够的缓冲可以持续播放