CSS 选择器深度解析:从基础到高级应用

一、选择器基础概念

CSS 选择器是用于"选择"需要添加样式的 HTML 元素的模式。它们构成了 CSS 的基础,允许开发者精确控制页面元素的样式表现。

选择器的工作机制可以理解为:

  1. 浏览器解析 HTML 构建 DOM 树
  2. 解析 CSS 规则并提取选择器
  3. 将选择器与 DOM 节点匹配
  4. 应用匹配的样式规则

二、基础选择器详解

1. 元素选择器

/* 选择所有<p>元素 */
p {
  color: blue;
}

2. 类选择器

/* 选择所有class="highlight"的元素 */
.highlight {
  background-color: yellow;
}

3. ID 选择器

/* 选择id="header"的元素 */
#header {
  font-size: 24px;
}

4. 通配符选择器

/* 选择所有元素 */
* {
  margin: 0;
  padding: 0;
}

三、组合选择器实战

1. 后代选择器

/* 选择<div>内所有的<p>元素 */
div p {
  line-height: 1.5;
}

2. 子元素选择器

/* 只选择<ul>的直接子<li>元素 */
ul > li {
  list-style-type: none;
}

3. 相邻兄弟选择器

/* 选择紧接在<h2>后的<p>元素 */
h2 + p {
  margin-top: 0;
}

4. 通用兄弟选择器

/* 选择<h2>之后的所有<p>兄弟元素 */
h2 ~ p {
  color: #666;
}

四、属性选择器进阶

/* 存在title属性的<a>元素 */
a[title] {
  color: purple;
}

/* href属性值以"https"开头的<a>元素 */
a[href^="https"] {
  border-left: 2px solid green;
}

/* href属性值包含"example"的<a>元素 */
a[href*="example"] {
  font-weight: bold;
}

/* href属性值以".pdf"结尾的<a>元素 */
a[href$=".pdf"] {
  background: url(pdf-icon.png) no-repeat right center;
}

五、伪类与伪元素深度应用

1. 常用伪类

/* 未访问的链接 */
a:link {
  color: blue;
}

/* 鼠标悬停状态 */
button:hover {
  background-color: #eee;
}

/* 获得焦点的输入框 */
input:focus {
  border-color: #4CAF50;
}

/* 第一个子元素 */
li:first-child {
  font-weight: bold;
}

/* 每第3个元素 */
li:nth-child(3n) {
  background-color: #f5f5f5;
}

2. 伪元素实践

/* 在元素前插入内容 */
blockquote::before {
  content: "“";
  font-size: 2em;
  color: #999;
}

/* 选择第一行文本 */
p::first-line {
  font-weight: bold;
}

/* 选择用户选中的文本 */
::selection {
  background: #ffb7b7;
}

六、选择器优先级机制

CSS 优先级通过权重系统计算,具体规则如下:

图1

权重计算示例

  • #nav .item:hover = 1(ID) + 1(类) + 1(伪类) = 110
  • ul#nav li.active = 1(ID) + 1(元素) + 1(类) = 111
  • style="color:red" = 1000(内联样式)

七、性能优化建议

  1. 避免过度嵌套

    /* 不推荐 */
    body div#container ul li a {}
    
    /* 推荐 */
    #container a {}
  2. 优先使用类选择器

    /* 不推荐 */
    ul#navigation {}
    
    /* 推荐 */
    .navigation {}
  3. 限制属性选择器使用

    /* 性能较差 */
    [type="text"] {}
    
    /* 改进方案 */
    input[type="text"] {}
  4. 利用继承特性

    /* 父元素设置字体,子元素自动继承 */
    body {
      font-family: Arial, sans-serif;
    }

八、现代 CSS 选择器新特性

1. :is():where()

/* 传统写法 */
header p, 
main p, 
footer p {
  line-height: 1.6;
}

/* 使用:is()简化 */
:is(header, main, footer) p {
  line-height: 1.6;
}

/* :where()优先级总是0 */
:where(header, footer) p {
  color: gray;
}

2. :has() 父选择器

/* 选择包含<img>的<figure> */
figure:has(img) {
  border: 1px solid #ccc;
}

/* 选择后面跟着<p>的<h2> */
h2:has(+ p) {
  margin-bottom: 0;
}

3. :focus-visible

/* 只在键盘聚焦时显示焦点样式 */
button:focus-visible {
  outline: 2px solid blue;
}

九、实践案例:构建导航菜单

<nav class="main-nav">
  <ul>
    <li><a href="/">首页</a></li>
    <li class="active"><a href="/products">产品</a></li>
    <li><a href="/about">关于我们</a></li>
    <li><a href="/contact" data-highlight>联系我们</a></li>
  </ul>
</nav>
.main-nav ul {
  display: flex;
  gap: 1rem;
  list-style: none;
  padding: 0;
}

.main-nav a {
  padding: 0.5rem 1rem;
  text-decoration: none;
  color: #333;
  border-radius: 4px;
  transition: background-color 0.3s;
}

.main-nav a:hover {
  background-color: #f0f0f0;
}

.main-nav .active a {
  background-color: #007bff;
  color: white;
}

.main-nav a[data-highlight] {
  font-weight: bold;
  color: #ff5722;
}

十、常见问题解答

Q: 为什么我的样式没有生效?
A: 检查以下可能原因:

  1. 选择器拼写错误
  2. 优先级被更高权重规则覆盖
  3. 属性被标记为!important的规则覆盖
  4. 样式表加载顺序问题

Q: 如何覆盖第三方库的样式?
A: 推荐方案:

  1. 增加选择器特异性(如添加父类)
  2. 使用相同的选择器但放在第三方样式后加载
  3. 万不得已时使用!important(尽量避免)

Q: 伪元素必须要有content属性吗?
A: 是的,即使设置为空:

.element::after {
  content: "";
  /* 其他样式 */
}

掌握 CSS 选择器是成为前端高手的关键一步。建议通过实际项目不断练习,理解各种选择器的适用场景和性能影响,从而写出更高效、更易维护的样式代码。

评论已关闭