WordPress 主题的 CSS 加载顺序:为什么你的样式被覆盖了
「我明明写了 !important,还是没生效。」——这句我听了太多遍。 CSS 加载顺序在 WordPress 里不是按文件在模板里出现的先后,而是按 enqueue 的顺序,还有依赖关系。 wp_enqueue_style 的三个参
「我明明写了 !important,还是没生效。」——这句我听了太多遍。
CSS 加载顺序在 WordPress 里不是按文件在模板里出现的先后,而是按 enqueue 的顺序,还有依赖关系。
wp_enqueue_style 的三个参数
wp_enqueue_style($handle, $src, $deps, $ver);
$handle:唯一标识,重复注册会被忽略$src:文件地址$deps:依赖的 handle 数组,被依赖的先加载$ver:版本号,拼在 URL 后面
关键在第三个。它决定的正是加载顺序。
三个典型场景
场景一:子主题想覆盖父主题样式
wp_enqueue_style('parent-style', get_template_directory_uri() . '/style.css');
wp_enqueue_style('child-style', get_stylesheet_uri(), array('parent-style'));
依赖写 parent-style,子主题样式一定排在后面,覆盖得住。不写依赖,加载顺序不保证。
场景二:主题想覆盖插件的样式
插件加载时机不一定。主题的 enqueue 一般挂在 wp_enqueue_scripts 上,默认优先级 10;插件可能挂的是 5 或 20。
要稳定覆盖插件样式,把主题的 enqueue 优先级调到后面:
add_action('wp_enqueue_scripts', function() {
// ...
}, 99);
99 表示最后。这样主题的样式一定在插件之后。
但这招有副作用:如果另一个插件挂了优先级 100,还是压你。实在不行,告诉用户去清缓存,或者用更具体的 CSS 选择器,别只依赖顺序。
场景三:样式表还没加载就用了
有时候会因为某个插件把主题的样式 deregister 了,整个页面变成裸 HTML。这种情况下查一下 wp_head 输出的源码,看主题的 handle 在不在。
不在的话,可能被插件的 wp_dequeue_style() 摘掉了。多半是那个插件要自己接管主题样式。
同一个 handle 只能有一个
我碰到过两次:主题和插件都用了 my-style 这个 handle,结果后注册的覆盖了先注册的地址,样式加载成了对方的文件。
handle 空间是全站共享的,命名必须带自己的前缀。
主题用 mytheme-main,插件用 myplugin-front。别用通用名。
内联样式怎么在样式表之后
有些样式是动态生成的,比如主题选项里用户填的主色调。这种一般用 wp_add_inline_style() 挂到某个样式表上:
wp_enqueue_style('mytheme-main', ...);
wp_add_inline_style('mytheme-main', ':root { --primary: #3a7; }');
这样内联样式会紧跟在 mytheme-main 之后输出,顺序是稳的。
直接往 wp_head 里 echo <style> 也行,但那样就在所有样式表之后了,反而可能压掉别人的样式。具体看你要覆盖什么。
顺带说一下所有 CSS 都会遇到的一件事
加载顺序对的前提是选择器权重差不多。
父主题用 .site-header .logo { color: red },子主题写 .logo { color: blue },就算子主题排后面也不会生效——父主题那两条类名权重高。
正确做法是权重对齐:
.site-header .logo { color: blue; }
同权重、后加载,赢。
我最早以为是加载顺序出了问题,调试了两小时,最后发现是自己选择器写太短。