css 教程
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
11 KiB

# 伪类
*伪类(pseudo classes)允许你根据元素的状态动态的设置样式。这意味着,你的设计可以根据用户的操作发生动态的变化。*
本节内容比较多,你不需要完全记住所有的伪类,只需要知道伪类的作用和一些常用伪类即可,用到的时候,可以来这里再回忆一下。
假设需要在页面上添加一个邮箱输入框,当用户输入无效格式的邮箱字符串时,输入框会出现一个红色的边框,你要如何实现这个功能呢?CSS提供了`:invalid`伪类,恰好满足我们的需求。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_01" src="https://codepen.io/AhCola/embed/gOROjoN?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/gOROjoN">
018 Pseudo classes_01</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
当邮箱账号格式正确时,显示绿色的边框,格式不正确时,显示红色的边框。这种设计可以起到提示的作用。
例子中的`:invalid`和`:valid`就是伪类。与[伪元素](http://pengfeixc.com/tutorial/css/pseudo-elements)写法有点类似,但是伪类用单冒号表示。
## 一.交互状态
下面是一些与用户操作引发元素状态改变有关的伪类。
### `:hover`
当鼠标悬浮在某个元素上面时,元素的hover状态被激活,你可以用`:hover`更改此时元素的样式。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_02" src="https://codepen.io/AhCola/embed/JjJjBqm?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/JjJjBqm">
018 Pseudo classes_02</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### `:active`
当元素正在处于与用户交互的操作时,此时该元素处于激活状态,例如用户点击了该元素,该元素在点击的过程中处于激活状态。可以用`:active`更改这个状态下的元素样式。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_03" src="https://codepen.io/AhCola/embed/NWgWLWb?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/NWgWLWb">
018 Pseudo classes_03</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### `:focus`、`:focus-within`和`:focus-visible`
通过`:focus`可以更改focusable元素(例如button)获得焦点时的样式。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_04" src="https://codepen.io/AhCola/embed/powoOjW?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/powoOjW">
018 Pseudo classes_04</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
如果一个元素的子元素获得焦点,可以通过`:focus-within`更改该元素此时的样式。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_05" src="https://codepen.io/AhCola/embed/rNwNZxK?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/rNwNZxK">
018 Pseudo classes_05</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
关于`:focus-visible`[这里](https://www.zhangxinxu.com/wordpress/2019/03/css-focus-visible/)有详细解释。它的作用是可以让我们知道元素的聚焦行为到底是鼠标触发还是键盘触发。
例如下面的例子,我们希望去除鼠标点击时候的`outline`轮廓,而保留键盘访问时候的`outline`轮廓。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_06" src="https://codepen.io/AhCola/embed/zYzYJpe?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/zYzYJpe">
018 Pseudo classes_06</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### `:target`
当url中锚片段匹配某个元素的id时,可以用`:target`更改此时元素的样式。通常用这个标志页面跳转的区域。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_07" src="https://codepen.io/AhCola/embed/zYzYJJX?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/zYzYJJX">
018 Pseudo classes_07</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
## 二.历史状态
### `:link`
如果一个拥有`href`属性的`<a>`元素还没有访问过(被用户点击),可以使用`:link`更改它的样式。
也可以使用`:visited`更改已访问过得`<a>`元素的样式。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_08" src="https://codepen.io/AhCola/embed/NWgWLJy?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/NWgWLJy">
018 Pseudo classes_08</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
#### 顺序问题
在某些浏览器中,如果你定义了一个`:visited`样式,它可能会被后面定义的`:link`样式覆盖,所以建议按照如下顺序定义伪类样式。
```css
a:link {}
a:visited {}
a:hover {}
a:active {}
```
## 三.表单状态
### `:disabled`和`:enabled`
`:disabled`和`:enabled`用于设置表单元素(例如button)是否禁用时的样式,表单元素默认是enabled,所以我们一般很少用`:enabled`设置元素的样式。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_09" src="https://codepen.io/AhCola/embed/rNwNqBg?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/rNwNqBg">
018 Pseudo classes_09</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### `:checked` and `:indeterminate`
`:checked`用于指示某些可以被用户点击选中的表单元素,例如checkbox和radioButton。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_10" src="https://codepen.io/AhCola/embed/powoxrm?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/powoxrm">
018 Pseudo classes_10</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
checkbox元素除了拥有选中和被选中两种状态,还有一种状态为`indeterminate`,需要通过js激活该状态:
```javascript
inputCheckbox.indeterminate = true;
```
可以使用`:indeterminate`设置该状态下的样式。
### `:placeholder-shown`
如果某个表单元素设置了`placeholder`属性,那么当`placeholder`显示的时候,可以用`:placeholder-shown`设置该状态下的样式。
### 验证状态
正如文章开始的例子那样,可以使用`:valid`、`:invalid`和`in-range`根据表单元素的验证状态,动态的更改样式。
`:in-range`主要是针对,设置了`min`和`max`属性的`<input>`元素。例如`<input type=number min=1 max=5 />`,使用下面的css代码,当用户输入数字范围不在1~5范围间时,输入框背景色为红色。
```css
input {
background: red;
}
input:in-range {
background: white;
}
```
## 四.根据元素的索引、出现顺序选中元素
### `:first-child`和`:last-child`
`:first-child`和`:last-child`用于选中一组元素内同级的第一个和最后一个元素。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_11" src="https://codepen.io/AhCola/embed/PojoxoX?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/PojoxoX">
018 Pseudo classes_11</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### `only-child`
`only-child`用于选中没有兄弟元素的元素。
<iframe height="300" style="width: 100%;" scrolling="no" title="018 Pseudo classes_12" src="https://codepen.io/AhCola/embed/gOROQpZ?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true">
See the Pen <a href="https://codepen.io/AhCola/pen/gOROQpZ">
018 Pseudo classes_12</a> by Pengfei Wang (<a href="https://codepen.io/AhCola">@AhCola</a>)
on <a href="https://codepen.io">CodePen</a>.
</iframe>
### `:first-of-type`和`:last-of-type`
`:first-of-type`和`:last-of-type`与`:first-child`和`:last-child`类似,也是选中第一个和最后一个元素,但是范围不一样,它不限于元素在一个组内,不要求元素是兄弟节点。
### `nth-child`和`nth-of-type`
`nth-child`和`nth-of-type`是前面内容的扩充,用于选中第n个元素。
你还可以使用`nth-child(even)`选中所有奇数位元素。
甚至更复杂的形式,选中3n+3位置的元素。
```css
li:nth-child(3n+3) {
background: yellow;
}
```
### `only-of-type`
`only-of-type`与`only-child`元素类似,区别是`only-child`选中的是一组内唯一子元素,而`only-of-type`选中的是一组内唯一类型的子元素。
## 五.寻找空元素
### `:empty`
当某个元素没有子元素时,我们认为它是一个空元素。可以使用`:empty`设置空元素的样式。
注意空元素,标签内部没有空格。
```html
<div></div>
<div>
</div>
```
第二个`<div>`元素不是一个空元素,所以`:empty`对其无效果。
## 六.选择和过滤
### `:is() `
如果你想要指示类名为`.post`元素下`h2`、`li`子元素,可以这样写:
```css
.post :is(h2, li) {
}
```
等价的写法:
```css
.post h2,.post li {
}
```
### `:not()`
可以使用`:not()`排除某些元素。例如选中所有没有类名(`class`属性)的链接。
```css
a:not([class]) {
}
```
选中所有没有`alt`属性的图片。
```css
img:not([alt]) {
}
```
(完)