伪元素是子元素,有点像。

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200 美元的免费积分!

这里有一个包含一些子元素的容器

<div class="container">
  <div>item</div>
  <div>item</div>
  <div>item</div>
</div>

如果我这样做

.container::before {
  content: "x"
}

我本质上是在做

<div class="container">
  [[[ ::before psuedo-element here ]]]
  <div>item</div>
  <div>item</div>
  <div>item</div>
</div>

这将像子元素一样工作,大多数时候。 一个棘手的事情是,除了用于创建它的那个选择器(或类似的选择器,实际上是::before::after,最终出现在同一个位置),没有其他选择器可以选择它。

为了说明,假设我将该容器设置为 2×3 网格,并将每个项目设置为某种药盒设计

.container {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-gap: 0.5rem;
}

.container > * {
  background: darkgray;
  border-radius: 4px;
  padding: 0.5rem;
}

没有伪元素,它将是这样的

Six items in a clean two-by-two grid

如果我像上面那样添加那个伪元素选择器,我将得到这个

Six items in a two-by-two grid, but with a seventh item at the beginning, pushing elements over by one

这很有道理,但它也可能让人感到意外。 伪元素通常是装饰性的(它们几乎应该只用于装饰),因此让它参与内容网格感觉很奇怪。

请注意,.container > *选择器没有选择它并将其设为darkgray,因为你无法以这种方式选择伪元素。 这是另一个小问题。

在我的日常工作中,我发现伪元素通常是绝对定位的,用于做一些装饰性的工作 - 所以,如果你有

.container::before {
  content: "";
  position: absolute;
  /* Do something decorative */
}

…你可能根本不会注意到。 从技术上讲,伪元素仍然是子元素,所以它仍然在那里发挥作用,但没有参与网格。 这也不仅仅是 CSS 网格独有的。 例如,你会发现通过使用 flexbox,你的伪元素会成为一个 flex 项目。 你也可以自由地浮动你的伪元素或用它做任何其他类型的布局。

DevTools 很清楚地表明它在 DOM 中就像子元素一样

DevTools with a ::before element selected

还有几个需要注意的地方!

一个是:nth-child()。 你会认为如果伪元素实际上是子元素,它们会影响:nth-child()计算,但事实并非如此。 这意味着像这样

.container > :nth-child(2) {
  background: red;
}

…无论是否存在::before伪元素,它都会选择同一个元素。 ::after:nth-last-child及其朋友也是如此。 这就是我在标题中加上“有点像”的原因。 如果伪元素完全像子元素一样,它们会影响这些选择器。

另一个需要注意的地方是,你不能像选择普通子元素一样在 JavaScript 中选择伪元素。 document.querySelector(".container::before");将返回null。 如果你在 JavaScript 中尝试获取伪元素的原因是为了查看它的样式,你可以使用一些CSSOM魔法来实现这一点。

const styles = window.getComputedStyle(
  document.querySelector('.container'),
  '::before'
);
console.log(styles.content); // "x"
console.log(styles.color); // rgb(255, 0, 0)
console.log(styles.getPropertyValue('color'); // rgb(255, 0, 0)

你遇到过伪元素的任何问题吗?