乐趣区

关于css:如何使用CSS伪类选择器

总览

CSS 选择器容许你通过类型、属性、位于 HTML 文档中的地位来抉择元素。本教程论述了三个新选项 :is():where():has()

选择器通常在样式表中应用。上面的示例会找到所有 <p> 段落元素并将字重更改为粗体:

p {font-weight: bold;}

你也能够在 JavaScript 中应用选择器来找到 DOM 节点:

  • document.querySelector()返回首个匹配的 HTML 元素。
  • document.querySelectorAll()返回所有匹配的 HTML 元素,这些元素位于类数组 NodeList 中。

伪类选择器依据 HTML 元素的以后状态来定位它们。兴许最广为人知的是 :hover,它在光标移到一个元素上时利用款式,所以它被用来高亮可点击的链接和按钮。

其余受欢迎的选项包含:

  • :visited:匹配拜访过的链接
  • :target:匹配文档 URL 所指向的元素
  • :first-child:指向第一个子元素
  • :nth-child:抉择指定子元素
  • :empty:匹配没有内容或子元素的元素
  • :checked:匹配已勾选的复选框或单选按钮
  • :blank:抉择用户输出为空的输入框
  • :enabled:匹配一个被启用的输入框。如果一个元素可能被激活(如抉择、点击或承受文本输出),或者可能获取焦点,则该元素是启用的
  • :disabled:匹配一个被禁用的输入框。在被禁用时,元素不能被激活或获取焦点
  • :required:指向必填的输入框。所谓必填,就是在提交所属表单之前,用户必须为输入框指定一个值
  • :valid:匹配一个内容验证正确的输入框
  • :invalid:匹配一个内容未通过验证的输入框
  • :playing:指向一个正在播放的 audiovideo元素

浏览器最近又收到了三个伪类选择器…

:is 伪类选择器

留神:这最后被指定为 :matches():any(),但 :is() 曾经成为 CSS 规范。

MDN 解释::is()CSS 伪类函数将选择器列表作为参数,并抉择该列表中任意一个选择器能够抉择的元素。这对于以更紧凑的模式编写大型选择器十分有用。

你常常须要在不止一个元素下面利用雷同的款式。比如说,<p>段落文本色彩默认为彩色,然而当它位于<article><section><aside> 外面时,文本色彩为灰色:

/* default black */
p {color: #000;}

/* gray in <article>, <section>, or <aside> */
article p,
section p,
aside p {color: #444;}

这是一个简略的例子,但更简单的页面将导致更简单和更简短的选择器字符串。任何选择器的语法错误都会毁坏所有元素的款式。

像 Sass 这样的 CSS 预处理器容许嵌套(这也将呈现在原生 CSS 中)。

article, section, aside {

  p {color: #444;}

}

这能够创立雷同的 CSS 代码,缩小打字的工作量,并能够避免谬误。然而:

  • 在原生嵌套到来之前,你仍须要一个 CSS 构建工具。你可能想应用像 Sass 这样的计划,但这可能给一些开发团队引入复杂性。
  • 嵌套可能会导致其余问题。构建深度嵌套的选择器是很容易的,但它会变得越来越难以浏览以及输入简短的 CSS。

:is() 提供了一个原生 CSS 解决方案。该个性已被所有古代浏览器反对(IE 除外)。

:is(article, section, aside) p {color: #444;}

单个选择器能够蕴含任意数量的 :is() 伪类。比如说,上面的简单选择器将绿色文本色彩利用于所有 <h1><h2><p>元素,这些元素是 <section> 的子元素,其蕴含类 .primary.secondary,并且不是 <article> 的第一个子元素。

article section:not(:first-child):is(.primary, .secondary) :is(h1, h2, p) {color: green;}

没有 :is() 的等同代码须要六个 CSS 选择器。

article section.primary:not(:first-child) h1,
article section.primary:not(:first-child) h2,
article section.primary:not(:first-child) p,
article section.secondary:not(:first-child) h1,
article section.secondary:not(:first-child) h2,
article section.secondary:not(:first-child) p {color: green;}

留神,:is()无奈匹配 ::before::after伪元素,因而上面示例代码会不起作用:

/* NOT VALID - selector will not work */
div:is(::before, ::after) {
  display: block;
  content: '';
  width: 1em;
  height: 1em;
  color: blue;
}

:where 伪类选择器

:where()选择器语法与 :is() 雷同,也被所有古代浏览器反对(IE 除外)。这往往会导致雷同的款式。比方:

:where(article, section, aside) p {color: #444;}

不同点在于优先级。优先级是用来决定哪个 CSS 选择器应该笼罩所有其余选择器的算法。在上面的例子中,article p比独自的 p 更加具体,因而所有位于 <article> 内的 p 元素的字体色彩将会是灰色:

article p {color: #444;}
p {color: #000;}

:is() 的状况下,优先级是在其参数中找到的最具体的选择器。在 :where() 的状况下,优先级为零。

思考上面的 CSS:

article p {color: black;}

:is(article, section, aside) p {color: red;}

:where(article, section, aside) p {color: blue;}

让咱们将这个 CSS 利用到上面的 HTML 中:

<article>
  <p>paragraph text</p>
</article>

段落文本将被渲染为红色,点击链接查看 CodePen 示例。

:is()选择器与 article p 具备雷同的优先级,但它在样式表的前面,所以文本变成了红色。如有必要能够同时删除 article p:is()选择器来利用蓝色,因为 :where() 选择器的优先级比两者都低。

更多的代码库会应用 :is() 而不是 :where()。然而,:where() 的零优先级对 CSS 重置来说是很实用的,它在没有特定款式的状况下利用规范款式的基线。通常状况下,重置会利用一个默认的字体、色彩、内边距和外边距。

这个 CSS 重置代码对 <h2> 题目利用了 1em 的上外边距,除非它们是 <article> 元素的首个子元素。

/* CSS reset */
h2 {margin-block-start: 1em;}

article :first-child {margin-block-start: 0;}

试图在样式表的前面设置一个自定义的 <h2> 上外边距是没有成果的,因为 article :first-child 有更高的优先级:

/* never applied - CSS reset has higher specificity */
h2 {margin-block-start: 2em;}

你能够用一个更高优先级的选择器来解决这个问题,但这须要更多的代码,而且对其余开发者来说不并不显著。你最终会遗记你为什么须要它。

/* styles now applied */
article h2:first-child {margin-block-start: 2em;}

你也能够通过对每个款式利用 !important 来解决这个问题,但请防止这样做!它使进一步的款式定义和开发变得更具挑战性。

/* works but avoid this option! */
h2 {margin-block-start: 2em !important;}

一个更好的抉择是在你的 CSS 重置中采纳 :where() 的零优先级。

/* reset */
:where(h2) {margin-block-start: 1em;}

:where(article :first-child) {margin-block-start: 0;}

当初,你能够笼罩任何 CSS 重置款式,无论其优先级如何;不须要进一步的选择器或!important

/* now works! */
h2 {margin-block-start: 2em;}

:has()伪类选择器

:has()选择器应用了相似于 :is():where()的语法,但它的指标是一个蕴含其余元素的元素。比如说,这里是为任何蕴含一个或多个 <img><section>标签的 <a> 链接增加蓝色、两像素宽的边框的 CSS:

/* style the <a> element */
a:has(img, section) {border: 2px solid blue;}

这是几十年来最激动人心的 CSS 停顿!开发者们终于有了一种针对父元素的办法。

难以捉摸的 ” 父选择器 ” 始终是人们申请最多的 CSS 个性之一,但它给浏览器供应商带来了性能上的麻烦。因而,它曾经行将到来了很长时间。简而言之:

  • 浏览器在页面上绘制元素时将 CSS 款式利用于该元素。因而,在进一步增加子元素时,整个父元素必须从新绘制。
  • 在 JavaScript 中增加、删除或批改元素可能会影响整个页面的款式,直到闭合的<body> 标签为止。

假如供应商曾经解决了性能问题,:has()的引入容许过来没有 JavaScript 就不可能实现的成为可能。例如,当任何必填的外部字段没有校验通过时,你能够设置内部表单 <fieldset> 和上面的提交按钮的款式。

/* red border when any required inner field is invalid */
fieldset:has(:required:invalid) {border: 3px solid red;}

/* change submit button style when invalid */
fieldset:has(:required:invalid) + button[type='submit'] {
  opacity: 0.2;
  cursor: not-allowed;
}

这个例子增加了一个导航链接子菜单指示器,其中蕴含一个子菜单项的列表:

/* display sub-menu indicator */
nav li:has(ol, ul) a::after {
  display: inlne-block;
  content: ">";
}

或者,你能够增加调试款式,比方高亮显示所有没有外部 img<figure>元素。

/* where's my image?! */
figure:not(:has(img)) {border: 3px solid red;}

在关上你的编辑器和重构你的 CSS 代码库之前,请留神 :has() 是很新的,反对比 :is():where()更无限。它在 Safari 15.4+ 和 Chrome 105+ 可用,然而到 2023 年应该能够宽泛应用。

总结

:is():where() 伪类选择器简化了 CSS 语法。你对嵌套和 CSS 预处理器的需要会缩小。

:has()更具革命性和令人激动。父级抉择将迅速流行起来,咱们将遗记黑暗时代。

以上就是本文的所有内容,如果对你有所帮忙,欢送点赞珍藏转发~

退出移动版