跳转到内容

巧用伪类

刀刀

5/2/2024

0 字

0 分钟

CSS 中提供了很多伪类,方便我们能更好的设置样式。其中,伪类也分为很多种,下面一一介绍。

链接伪类

超链接 a 标签有四个伪类可以使用,分别为:

  • :link :未访问的链接

    css
    a:link {
      color: blue
    }
  • :visited :已访问的链接

    市面上那些招聘类或新闻类的项目在点击文章详情后返回列表页样式为浅灰色,就是用到该伪类来实现。

    css
    a:visited {
      color: #ccc
    }
  • :hover :鼠标划过链接

    css
    a:hover {
      color: red
    }
  • :active :已选中的链接

    css
    a:active {
      color: green
    }

注意:

  1. 在CSS定义中,a:hover 必须被置于 a:link 和 a:visited 之后,才是有效的。
  2. 在 CSS 定义中,a:active 必须被置于 a:hover 之后,才是有效的。
  3. 伪类的名称不区分大小写。

元素匹配伪类

  • :first-child :第一个子元素

    css
    .nav :first-child {
      font-size: 12px;
    }
  • :last-child :最后一个子元素

    css
    .nav :last-child {
      font-size: 20px;
    }
  • :nth-child(n) :顺数第 n 个 子元素,不限制子元素的类型

    css
    p:nth-child(2) {
      color: red;
    }
  • :nth-of-type(n) :顺数第 n 个子元素,规定子元素的类型

    css
    p:nth-of-type(2) {
      color: blue;
    }
  • :nth-last-child(n) :倒数第 n 个 子元素,不限制子元素的类型

    css
    p:nth-last-child(2) {
      color: orange;
    }
  • :nth-last-of-type(n) :倒数第 n 个子元素,规定子元素的类型

    css
    p:nth-last-of-type(2) {
      color: green;
    }

表单伪类

基础使用

  • :checked :选择所有选中的表单元素

    css
    input:checked {
      color: red
    }
  • disabled :选择所有禁用的表单元素

    css
    input:disabled {
      color: red
    }
  • read-only :选择所有禁用的表单元素

    css
    input:read-only {
      color: red
    }
  • focus :选择所有聚焦的表单元素

    css
    input:focus {
      color: red
    }

focus-within

下面有一个场景:一个表单,用户在给表单聚焦时不仅该表单元素样式做处理,其父元素也有相应的背景颜色变化。

第一个要求很容易实现,通过 focus 伪类修改即可。但是其父 div 无法通过该伪类实现,此时可以用到 focus-within 伪类。该伪类意思是匹配孩子元素中有聚焦的父元素。

代码如下:

html
<style>
  div:focus-within {
    background-color: skyblue;
  }
</style>

<div>
  <input type="text" />
</div>

注意:这里的 div 必须是 focus-within 伪类元素的父元素,不能是 focus-within 伪类元素本身。后续样式生效的 DOM 元素是 focus-within 伪类元素的父元素 div

first-letter

一段文本首个文字或字母大写的效果依靠 first-letter 伪类设置,其效果为给盒子文本第一个文字或字母设置样式,因此代码写成如下形式:

css
div:first-letter {
    font-weight: bold;
    font-size: 4em;
    text-transform: uppercase;
    float: left;
    line-height: 1;
    margin-right: 10px;
}

修改后效果为首字加粗,字体大小为4倍,行高为1,左浮动,统一大写显示。

selection

该伪类主要用于设置用户鼠标选中文本后显示的样式。代码如下:

css
.content:selection {
    background: #333;
    color: #fff;
}

placeholder-shown

:placeholder-shown CSS伪类表示当前显示占位符文本的任何 inputtextarea 元素。用大白话来说就是当输入框标签设置了 placeholder 占位符且没输入内容(显示占位符内容)时,该伪类的样式生效。

代码如下:

html
<input name="email" type="email" placeholder="name@example.com" />

<style>
input:placeholder-shown {
  background-color: skyblue;
  border: 2px solid darkorange;
  border-radius: 5px;
}
</style>

实际业务中也可以使用在让文本输入框后面的按钮在有没有输入内容时是否显示或显示不同的文字。

大致代码如下:

html
<div>
    <input placeholder="write something" />
    <button>
        click me
    </button>
</div>

<style>
    input:placeholder-shown + button {
        display: none;
    }
</style>

函数选择伪类

where()

:where() : CSS 伪类函数接受选择器列表作为它的参数,将会选择所有能被该选择器列表中任何一条规则选中的元素。

示例代码如下所示:

html
<style>
  :where(div, p) span {
    color: yellow;
  }
</style>

<div class="test-div">
    <span>哈哈</span>
</div>
<p class="test-p">
    <span>哈哈</span>
</p>

咋一看使用场景并不多,但是我们看下面一段代码:

css
div a:hover,
li a:hover,
.cla a:hover,
.aa .bb a:hover,
[class^='bold'] a:hover{
  color: yellow;
}

我们可以使用 :where()来简化这个写法,使用它找出 divli.cla 类名等这三种选择器,选择器可以是标签,也可以是类名,也可以是选择器表达式

css
:where(div, li, .cla, .ab .bb, [class^='bold']) a:hover {
    color: yellow;
}

再来看看使用 :where() 的组合,完成一些功能,我们看以下的代码

css
.dark-theme button,
.dark-theme a,
.light-theme button,
.light-theme a{
  color: pink;
}

我们完全可以使用 :where() 简化这个写法

css
:where(.dark-theme, .light-theme) :where(button, a) {
    color: pink;
}

:where()的优先级是 0,我们可以看下面代码

css
.box {
    color: yellow;
}
:where(.box) {
    color: pink
}

最后字体颜色是 yellow

is()

:is():where()可以说一模一样,区别就是 :is()的优先级不是0,而是由传入的选择器来决定的,拿刚刚的代码来举个例子

css
div {
    color: yellow;
}
:where(.test) {
    color: pink
}

<div class="test">哈哈</div>

这要是 :where(),那么字体颜色会是 yellow,因为它的优先级是 0

但是如果是 :is()的话,字体颜色会是 pink,因为 类选择器 优先级比 标签选择器 优先级高

css
:is(.test) {
    color: pink
}
div {
    color: yellow;
}

<div class="test">哈哈</div>

has()

举一个场景例子,我们看以下代码,一个容器中,图片是可以显隐的,我想要实现:

  • 图片显示时,字体大小为 12px
  • 图片隐藏时,字体大小为 20px
html
<div class="container">
    哈哈哈哈哈
    <img class="test-img" v-if="showImg"></img>
</div>

如果按照以前的做法,就是使用 动态class 的方式去玩完成这个功能,但是现在有 :has()可以通过 css 的方式去完成这件事~

css
.container {
    font-size: 20px;
}
.container:has(img) {
    font-size: 12px;
}

或者
.container:has(.test-img) {
    font-size: 12px;
}

现在又有两个场景

  • 判断容器有没有子img,有的话字体设置为 12px(上面的例子是后代选择器,不是子选择器)
  • 判断容器有没有一个小相邻的img,有的话设置字体颜色为 red

我们可以这么去实现:

css
.container:has(>img) {
    font-size: 12px;
}

.container:has(+img) {
    color: red;
}

再来一个场景

  1. 当我 hover 到 子img 上时,我想要让 container 的字体变粗,可以这么去使用

    css
    .container:has(>img:hover) {
        color: red;
    }
  2. 所有状态为必填 required 的表单项后面添加星号,可以这么做

    css
    input:has(+input[required])::after {
        content: '*';
    }

not()

用来匹配不符合一组选择器的元素。由于它的作用是防止特定的元素被选中,它也被称为反选伪类

使用 :not() 时,有几种不寻常的效果和结果需要注意:

  • 可以使用此伪类编写无用的选择器。例如,:not(*) 匹配任何不是元素的元素,这显然是荒谬的,所以这个附加的规则将永远不被应用。
  • 可以利用这个伪类提高规则的优先级。例如,#foo:not(#bar)#foo 都将匹配相同的元素,但是具有两个 id 的选择器具有更高的优先级。
  • :not() 伪类的优先级将由其逗号分割的参数中优先级最高的选择器指定;提供与 :not(:is(argument)) 相同的优先级。
  • :not(.foo) 将匹配任何非 .foo 的元素,包括 ](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/html) 和 [
  • 这个选择器将匹配任意“不是一个 X”的元素。当与后代选择器一起使用,这可能令人惊讶,因为有多种路径可以选择一个目标元素。例如,body :not(table) a 仍将应用 `` 中的链接,因为 、、](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/th)、 (en-US)](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td)、](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/caption) 等都可以匹配选择器 :not(table)` 部分。
  • 你可以同时否定多个选择器。例如::not(.foo, .bar) 等同于 :not(.foo):not(.bar)
  • 如果传递给 :not() 伪类的选择器无效或者浏览器不支持,则整个规则都将是无效的。克服这种行为的有效方式是使用::is 伪类,它接受一个可容错选择器列表。例如 :not(.foo, :invalid-pseudo-class) 将使整个规则无效,但是 :not(:is(.foo, :invalid-pseudo-class)) 将匹配任何(包括 ](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/html) 和 [)不是 .foo 的元素。
css
/* 选择所有没有 .foo 类或者 .bar 类的 <div> 元素 */
div:not(.foo, .bar) {
  color: red;
  font-style: italic;
}

总体效果