本文约 3,605 字,预计阅读 10 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:三个月后,没人敢动那段 CSS
项目初期,为了赶进度,样式都堆在”外观 → 自定义 → 额外 CSS”里。三个月后那段 CSS 变成几百行:选择器写得很随意,.content p span 这种依赖层级的写法到处都是,为了盖住主题样式加了十几个 !important。换主题时全盘失效,改一处会牵连三个页面,最后谁都不敢动。
CSS 的问题从来不是”写得对不对”,而是”半年后还能不能改”。规范的意义就在这里:位置明确、命名可预测、作用域可控。
原理分析:为什么会失控
三个技术性原因:
其一,特异性(specificity)竞赛。主题样式选择器写得越具体,你的覆盖就必须更具体,最后只能用 !important 兜底。而 !important 一旦出现,后续所有覆盖都得跟着加,形成恶性循环。
其二,作用域不可控。在额外 CSS 里写的规则作用于全站,你只想改首页列表,结果文章页的列表也变了。
其三,没有版本记录。额外 CSS 存在数据库里(custom_css 文章类型,对应 wp_posts),主题切换时它会跟着”当前主题”走,且没有 diff 能力,改错了只能靠记忆恢复。
对应的三个手段是:优先用子主题文件(可进 Git、可 diff)、用类名而非层级选择器(降低特异性)、用 CSS 变量集中管理可配置项。
| 做法 | 特异性 | 可版本管理 | 适合场景 |
|---|---|---|---|
!important |
最高 | 否 | 临时止血,不应长期存在 |
| 增加选择器层级 | 高 | 否 | 不推荐,会滚雪球 |
| 加一个语义类名 | 低(可控) | 是 | 首选 |
| 用 CSS 变量 | 低 | 是 | 颜色、间距等全局配置 |
保姆级实操
- 确定存放位置:少量临时调整放”额外 CSS”;超过十几行、需要长期维护的,一律放子主题
style.css或assets/css/下独立文件。 - 用浏览器定位选择器:DevTools 里找到目标元素,看命中规则来自哪个文件、特异性多少,再决定覆盖策略,不要凭感觉写。
- 给元素加语义类名:改不动主题模板时,用
body_class或post_class过滤器给容器加一个自己的类名,把作用域限定住。 - 采用 BEM 命名:
block__element--modifier,避免层级嵌套,特异性稳定在单个类。 - 用 CSS 变量集中配置:颜色、间距、圆角、最大宽度统一放
:root,改一次全站生效。 - 按区块分文件并注释:每个文件顶部写明”用途 / 添加日期 / 关联页面”,半年后还能看懂。
- 定期清理:升级主题后检查哪些覆盖已经不再需要,及时删掉。
/* ============================================================
文件:assets/css/_cards.css
用途:首页与归档页的文章卡片样式
添加日期:2026-03
依赖:无
说明:使用 BEM 命名,不使用 !important
============================================================ */
:root {
--mf-card-radius: 10px;
--mf-card-gap: 24px;
--mf-card-bg: #fff;
--mf-card-border: rgba(0, 0, 0, .08);
}
.mf-card {
display: flex;
flex-direction: column;
background: var(--mf-card-bg);
border: 1px solid var(--mf-card-border);
border-radius: var(--mf-card-radius);
overflow: hidden;
}
.mf-card__thumb {
aspect-ratio: 4 / 3;
object-fit: cover;
}
.mf-card__body {
padding: 16px;
gap: 8px;
}
/* 修饰类:只改差异,不重复基础样式 */
.mf-card--horizontal {
flex-direction: row;
}
.mf-card--horizontal .mf-card__thumb {
width: 40%;
aspect-ratio: auto;
}
@media ( max-width: 600px ) {
:root {
--mf-card-gap: 16px;
}
.mf-card--horizontal {
flex-direction: column;
}
}
<?php
// 用过滤器给容器加语义类名,把作用域限定在归档页
add_filter( 'post_class', 'mimangfei_card_class' );
function mimangfei_card_class( $classes ) {
if ( is_archive() || is_home() ) {
$classes[] = 'mf-card';
}
return $classes;
}
// 只在首页加载卡片样式,减少其他页面的体积
add_action( 'wp_enqueue_scripts', 'mimangfei_card_css' );
function mimangfei_card_css() {
if ( ! is_home() && ! is_archive() ) {
return;
}
$file = get_stylesheet_directory() . '/assets/css/_cards.css';
wp_enqueue_style(
'mf-cards',
get_stylesheet_directory_uri() . '/assets/css/_cards.css',
array(),
file_exists( $file ) ? filemtime( $file ) : null
);
}
// 把"额外 CSS"里的内容迁移到文件时,可先取出原文备份
// $css = wp_get_custom_css();
-- 查看当前主题绑定的额外 CSS 记录(迁移前确认内容)
SELECT ID, post_title, post_status, LENGTH(post_content_filtered) AS len
FROM wp_posts
WHERE post_type = 'custom_css';
常见踩坑
- 习惯性加
!important,最后所有覆盖都必须加,无法收敛。 - 把只该作用于首页的规则写进额外 CSS,结果全站受影响。
- 用
.entry-content > div > p这类深层级选择器,主题一升级结构变化就失效。 - 额外 CSS 里累积了几百行,换主题后全部失效且无法找回历史版本。
- 案例:某站改版后列表卡片样式全乱。排查发现旧主题用
.post-list .item,新主题改成了.posts-grid .card,而额外 CSS 里 200 多行全部基于旧类名。此后该站把样式迁到子主题assets/css/并用 BEM 命名,改版时只需替换少量基础类名。 - 用
filemtime()做版本号却忘了在改 CSS 后清 CDN 缓存,用户看到旧样式。 - 同一份 CSS 在额外 CSS 和子主题文件里各存一份,改了一边忘了另一边。
总结
自定义 CSS 的三条规范:位置优先子主题文件(便于版本管理)、命名用 BEM 单类(稳定特异性)、配置走 CSS 变量(集中可控)。判断标准是”任何一条规则都能说清它作用于哪个页面、为什么需要”。行动清单:① 十几行以上就放进子主题文件;② 覆盖靠语义类名而非提高特异性;③ 颜色间距统一到 :root;④ 每个文件写明用途与日期;⑤ 主题升级后清理失效规则。延伸阅读 主题自定义 CSS 放置位置、WordPress 子主题制作 与 lumen-mimangfei 主题性能优化。
