讲解

一条 CSS 规则由「选择器 + 声明块」组成:selector { property: value; }。花括号里可以写多条声明,每条以分号结尾。注释用 /* ... */(没有单行注释)。选择器决定规则命中哪些元素,是整个 CSS 的入口。

常用选择器按类别记:基本选择器有元素选择器 p、类选择器 .card(最常用的主力)、ID 选择器 #header、通配符 ;组合器有后代(空格,.card p 命中 .card 里任意深度的 p)、子代(>,只命中直接子元素)、相邻兄弟(+,命中紧跟其后的一个)、通用兄弟(~,命中之后所有同级);属性选择器如 [type="text"]、[href^="https"](开头匹配)、[class="btn"](包含匹配);伪类描述元素状态,如 :hover、:focus、:first-child、:nth-child(2n+1)(奇数行)、:not(.active);伪元素选中元素的某个「部分」,用双冒号书写,如 ::before、::after、::first-line、::placeholder。多个选择器用逗号分组,共享一份声明。

当多条规则命中同一元素的同一属性时,浏览器按「优先级」裁决:行内样式 > ID 选择器 > 类/属性/伪类 > 元素/伪元素,同级别则后写的覆盖先写的(这就是「层叠」)。另外约一半属性(字体、颜色、text-align 等)会从父元素继承,盒模型相关的(宽高、边距、边框)不继承——记住这条能解释大量「为什么没生效」。

示例

/* 元素选择器:所有段落 */
p {
  line-height: 1.8;
}

/* 类选择器(推荐的主力):可复用 */
.highlight {
  background: #fff3bf;
}

/* 组合器:article 内「直接子级」的 p,以及 h2 后面紧跟的 p */
article > p {
  margin-bottom: 16px;
}
h2 + p {
  color: #666;
}

/* 属性选择器:外链加标记 */
a[href^="https://"] {
  color: #0b7285;
}

/* 伪类与伪元素 */
li:nth-child(odd) {
  background: #f8f9fa; /* 奇数行斑马纹 */
}
.quote::before {
  content: '「';
}
.quote::after {
  content: '」';
}

/* 逗号分组:多个选择器共享声明 */
h1,
h2,
h3 {
  font-weight: 600;
}

常见坑

  • 类与 ID 不分:类用 . 可复用、优先级适中;ID 用 # 一页只能一个、优先级极高,会压住后续所有类样式。写样式优先用类,ID 留给锚点和 JS 钩子。
  • .a.b 与 .a .b 混淆:.a.b(无空格)命中「同时带 a 和 b 两个类」的同一个元素;.a .b(有空格)命中「a 的后代 b」。一个空格天差地别。
  • 伪类伪元素冒号写错::hover 是伪类(状态,单冒号),::before 是伪元素(虚拟节点,规范双冒号)。老代码里 :before 单冒号也能跑,是历史兼容。
  • 优先级计算走极端:写成 #page .article .list li a.active 这种长链,优先级高到谁也覆盖不了。日常保持 1~2 层类选择器足够。
  • 以为所有属性都继承:给父元素设 border 不会传给子元素;想让某个不继承的属性跟随父元素,可以显式写 color: inherit;。

小结

规则 = 选择器 + 声明块;类选择器是主力,组合器和伪类覆盖绝大多数命中场景;冲突时按优先级裁决,同级后写胜出。下一节看 CSS 以哪几种方式进入页面。