CSS `Pseudo-Class` (`:not()`, `:first-child`) 与 `Pseudo-Element` (`::before`, `::after`) 高级应用

各位观众老爷,大家好!我是你们的老朋友,今天咱们来聊聊CSS里那些看似简单,实则威力无穷的Pseudo-Class (:not(), :first-child) 和 Pseudo-Element (::before, ::after)。保证让你们听完之后,感觉自己写的CSS代码都升华了!

开场白:CSS世界的伪装大师

CSS的世界里,选择器就是我们的眼睛,而Pseudo-Class和Pseudo-Element就像是给这些选择器加了特效滤镜,让它们能选中一些“特殊”的元素,或者给元素“变个魔术”。它们就像CSS世界的伪装大师,能让你的样式更加灵活、强大。

第一幕:Pseudo-Class——元素的“性格”侦探

Pseudo-Class,顾名思义,就是“伪类”。它用来选取处于特定状态的元素。这就像一个侦探,专门找出具有某些“性格”的元素。

1. :first-child:家庭地位的象征

:first-child 选取的是作为其父元素的第一个子元素的元素。 就像一个家庭里的大哥大姐,备受关注。

/* 选取所有作为其父元素第一个子元素的 <p> 元素 */
p:first-child {
  color: red;
}

/* 选取所有作为其父元素第一个子元素的 <li> 元素 */
ul > li:first-child {
  font-weight: bold;
}

示例1:列表里的“头牌”

假设我们有一个列表:

<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

使用 :first-child,我们可以给第一个 <li> 加点特别的样式:

li:first-child {
  background-color: lightblue;
}

效果就是,只有 "Item 1" 会有浅蓝色的背景。

示例2:表格里的“第一排”

表格也类似,我们可以让第一行的单元格更突出:

<table>
  <tr>
    <th>Header 1</th>
    <th>Header 2</th>
  </tr>
  <tr>
    <td>Data 1</td>
    <td>Data 2</td>
  </tr>
</table>

CSS:

th:first-child {
  font-weight: bold;
}
td:first-child {
  text-decoration: underline;
}

这样,每个 <tr> 里的第一个 <th><td> 都会应用相应的样式。

2. :not():叛逆者的选择

:not() 选择器选取不匹配选择器的元素。它就像一个叛逆者,专门挑选那些“不符合”规则的元素。

/* 选取所有不是 <p> 元素的元素 */
:not(p) {
  border: 1px solid black;
}

/* 选取所有没有 class="highlight" 的元素 */
:not(.highlight) {
  opacity: 0.5;
}

示例1:排除高亮

假设我们想要给所有段落添加边框,但是不想给带有 highlight 类的段落加边框:

<p>This is a normal paragraph.</p>
<p class="highlight">This is a highlighted paragraph.</p>
<p>This is another normal paragraph.</p>

CSS:

p:not(.highlight) {
  border: 1px solid blue;
}

只有没有 highlight 类的段落会显示蓝色边框。

示例2:禁用链接

我们可以用 :not() 结合其他选择器来实现更复杂的逻辑。 例如,禁用所有不是活动状态的链接:

<a href="#">Link 1</a>
<a href="#" class="active">Link 2</a>

CSS:

a:not(.active) {
  pointer-events: none; /* 禁用点击 */
  opacity: 0.5; /* 降低透明度 */
}

这样,只有带有 active 类的链接才能被点击。

:not() 的注意事项

  • :not() 选择器内部不能再嵌套 :not()
  • :not() 选择器内部可以使用复杂的选择器,例如 p:not(.highlight > span)
  • :not(selector) 会匹配文档根元素,除非 selector 明确包含根元素,例如 :root

:first-child:not() 的结合

这两个伪类可以组合使用,实现更精细的控制。 比如,选取不是第一个子元素的段落:

p:not(:first-child) {
  margin-top: 1em; /* 给除了第一个段落之外的所有段落添加上边距 */
}

第二幕:Pseudo-Element——元素的“分身术”

Pseudo-Element,也就是“伪元素”。 它允许你创建一个不存在于文档树中的元素,并为其添加样式。 就像给元素施展了一个分身术,凭空创造出一些“影子”。

1. ::before:元素的前置小弟

::before 在选定元素的内容之前插入内容。 它就像一个忠实的小弟,永远站在元素的前面。

/* 在每个 <h1> 元素之前插入一个文本 */
h1::before {
  content: "Chapter: ";
  color: green;
}

示例1:添加图标

我们可以用 ::before 给链接添加图标:

<a href="#">Download</a>

CSS:

a::before {
  content: "f019"; /* Font Awesome 下载图标 */
  font-family: FontAwesome;
  padding-right: 0.5em;
}

示例2:装饰性边框

::before 也可以用来创建装饰性的边框:

.box {
  position: relative;
  padding: 1em;
  border: 1px solid black;
}

.box::before {
  content: "";
  position: absolute;
  top: -5px;
  left: -5px;
  width: 10px;
  height: 10px;
  background-color: red;
}

这段代码会在 .box 元素的左上角创建一个红色的正方形。

2. ::after:元素的后置小弟

::after 在选定元素的内容之后插入内容。 它就像一个贴心的助手,永远跟在元素的后面。

/* 在每个 <h2> 元素之后插入一个文本 */
h2::after {
  content: " - End of Section";
  font-style: italic;
}

示例1:添加版权信息

我们可以用 ::after 给文章结尾添加版权信息:

<article>
  <p>This is the content of the article.</p>
</article>

CSS:

article::after {
  content: "© 2023 My Company";
  display: block; /* 使其占据一行 */
  text-align: center;
  margin-top: 1em;
}

示例2:清除浮动

::after 还可以用来清除浮动,解决高度塌陷的问题:

.clearfix::after {
  content: "";
  display: table;
  clear: both;
}

使用方法:

<div class="clearfix">
  <div style="float: left;">Left Content</div>
  <div style="float: right;">Right Content</div>
</div>

::before::after 的注意事项

  • content 属性是必须的,即使你不想插入任何文本,也要设置 content: "";
  • 伪元素默认是行内元素,可以使用 display 属性修改其显示方式。
  • 伪元素的位置受 position 属性的影响。
  • 伪元素可以继承父元素的样式,例如字体、颜色等。

第三幕:高级应用——伪装大师的进阶之路

现在我们来探讨一下这些伪类和伪元素的高级应用,让你的CSS技能更上一层楼。

1. 使用 :not():first-child 实现复杂的列表样式

假设我们需要给列表添加一些特殊的样式,例如:

  • 第一个列表项有不同的背景颜色。
  • 每个列表项之间有分隔线,但最后一个列表项没有。
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>

CSS:

ul > li:first-child {
  background-color: lightgreen;
}

ul > li:not(:last-child) {
  border-bottom: 1px solid #ccc;
  padding-bottom: 0.5em;
  margin-bottom: 0.5em;
}

这段代码会给第一个列表项添加浅绿色背景,并在每个列表项(除了最后一个)的底部添加分隔线。

2. 使用 ::before::after 创建工具提示

我们可以用伪元素创建一个简单的工具提示效果:

<span class="tooltip">
  Hover me
  <span class="tooltiptext">This is the tooltip text.</span>
</span>

CSS:

.tooltip {
  position: relative;
  display: inline-block;
}

.tooltip .tooltiptext {
  visibility: hidden;
  width: 120px;
  background-color: black;
  color: #fff;
  text-align: center;
  border-radius: 6px;
  padding: 5px 0;
  position: absolute;
  z-index: 1;
  bottom: 125%;
  left: 50%;
  margin-left: -60px;
  opacity: 0;
  transition: opacity 0.3s;
}

.tooltip .tooltiptext::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 50%;
  margin-left: -5px;
  border-width: 5px;
  border-style: solid;
  border-color: black transparent transparent transparent;
}

.tooltip:hover .tooltiptext {
  visibility: visible;
  opacity: 1;
}

这段代码会在鼠标悬停在 tooltip 元素上时,显示一个工具提示框。

3. 使用 ::before::after 创建加载动画

伪元素也可以用来创建简单的加载动画:

<div class="loader"></div>

CSS:

.loader {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  position: relative;
  animation: rotate 1s linear infinite;
}

.loader::before,
.loader::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}

.loader::before {
  background-color: #4CAF50;
  animation: pulse 1s linear infinite;
}

.loader::after {
  background-color: #f44336;
  animation: pulse 1s linear infinite alternate;
}

@keyframes rotate {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

@keyframes pulse {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1);
  }
  100% {
    transform: scale(0);
  }
}

这段代码会创建一个旋转的圆形加载动画。

总结:掌握伪装术,玩转CSS

通过今天的学习,相信大家已经对Pseudo-Class (:not(), :first-child) 和 Pseudo-Element (::before, ::after)有了更深入的了解。 它们就像CSS世界的伪装大师,能让你的样式更加灵活、强大。 掌握它们,你就能写出更优雅、更高效的CSS代码,成为真正的CSS高手!

表格总结

特性 类型 作用 示例
:first-child Pseudo-Class 选取作为其父元素的第一个子元素的元素 p:first-child { color: red; } 选取所有作为其父元素第一个子元素的 <p> 元素,并将其颜色设置为红色。
:not() Pseudo-Class 选取不匹配选择器的元素 :not(p) { border: 1px solid black; } 选取所有不是 <p> 元素的元素,并添加黑色边框。
::before Pseudo-Element 在选定元素的内容之前插入内容 h1::before { content: "Chapter: "; color: green; } 在每个 <h1> 元素之前插入文本 "Chapter: ",并将其颜色设置为绿色。
::after Pseudo-Element 在选定元素的内容之后插入内容 h2::after { content: " - End of Section"; font-style: italic; } 在每个 <h2> 元素之后插入文本 " – End of Section",并将其样式设置为斜体。
结合使用 Pseudo-Class & Pseudo-Element 通过灵活组合,实现更精细的样式控制和更复杂的效果。 ul > li:not(:last-child) { border-bottom: 1px solid #ccc; } 给除了最后一个列表项之外的所有列表项添加下边框。
注意事项 需要关注 content 属性、display 属性、position 属性以及继承性。 content 属性是伪元素必须的,即使不插入任何文本,也要设置 content: "";position: relativeposition: absolute 结合使用可以实现精确定位。

结束语:下课!

希望今天的讲座能对大家有所帮助。记住,CSS的世界充满乐趣,只要你敢于探索,就能创造出无限可能! 下课! 咱们下次再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注