🪐前言
你有没有遇到过这种情况:辛辛苦苦改了主题的页脚版权信息、调整了文章页的布局、在 functions.php 里加了几个自定义函数——然后某天看到主题有安全更新,手一滑点了升级,所有修改全没了。
这不是你的问题,是 WordPress 主题更新机制就是这样设计的:更新 = 用新版本文件覆盖旧版本文件。 你直接改过的东西,一更新就归零。
解决这个问题的唯一正确方式叫做"子主题"(Child Theme)。这篇文章带你从原理到实操,一步步创建自己的子主题,从此安心定制、放心升级。
一、子主题是什么,为什么你需要它
子主题的工作机制其实不复杂:它"骑在"父主题之上运行。WordPress 加载时先检查子主题里有没有某个文件,有就用子主题的,没有就去父主题里找。这就叫继承与覆盖。
访问者 → WordPress → 先查子主题有没有对应文件
├── 有 → 用子主题的版本
└── 没有 → 去父主题找
举个例子:你的父主题 Astra 里有一个 single.php 控制文章页的布局。你在子主题里也放一个 single.php,WordPress 就会用你的版本而不是 Astra 的版本。Astra 升级时,覆盖的是它自己目录里的 single.php,你的子主题目录完全不受影响。
子主题需要的最小文件只有两个:style.css 和 functions.php。 哪怕你暂时只改一行 CSS,也建议花 10 分钟建好子主题——现在不用,将来升级时你会感谢现在的自己。

二、创建子主题的完整步骤
下面的操作全部在你的 WordPress 主题目录里完成。路径是 /wp-content/themes/。先通过 FTP、主机文件管理器或宝塔面板进入这个目录。
🗂️ 第一步:创建子主题文件夹
在 /wp-content/themes/ 下新建一个文件夹。命名规则是 父主题文件夹名 + -child:
/wp-content/themes/
├── astra/ ← 父主题
├── astra-child/ ← 这就是你的子主题目录
├── generatepress/
├── generatepress-child/
├── blocksy-child/ ← 如果你用 Blocksy
└── ...
📄 第二步:编写 style.css
在子主题文件夹里新建 style.css,这是 WordPress 识别子主题的唯一必要文件。文件头部的注释块必须有,缺任何一个字段子主题都无法被识别:
/*
Theme Name: Astra Child
Theme URI: https://你的网站.com/
Description: Astra 子主题 - 用于存放自定义修改
Author: 你自己
Author URI: https://你的网站.com/
Template: astra
Version: 1.0.0
Text Domain: astra-child
*/
关键字段说明:
Theme Name:在后台"外观 → 主题"中显示的名字,随便起Template:最重要,必须和父主题的文件夹名完全一致。父主题文件夹叫astra就写astra,大小写也要一样Text Domain:用于多语言翻译,建议用xxx-child格式
如果没有其他 CSS 需要覆写,可以再加一行导入父主题样式的代码:
/* 导入父主题的样式表 */
/* 注意:部分现代主题(如 Blocksy、GeneratePress)不需要手动导入,父主题会自动加载 */
⚠️ 现在很多主题(GeneratePress、Blocksy、Astra 新版)会通过 PHP 自动加载子主题样式。如果加了上面这行 CSS,发现样式加载了两次,说明你的主题不需要手动导入,删掉即可。
⚙️ 第三步:编写 functions.php
新建 functions.php。这个文件的作用是在 WordPress 初始化时执行你的自定义代码。最小版本只需要一个加载样式的函数:
<?php
/**
* Astra 子主题 - functions.php
* 所有自定义功能写在这里
*/
// 1. 加载父主题和子主题的样式
function astra_child_enqueue_styles() {
// 加载父主题样式
wp_enqueue_style(
'astra-parent-style',
get_template_directory_uri() . '/style.css'
);
// 加载子主题样式
wp_enqueue_style(
'astra-child-style',
get_stylesheet_directory_uri() . '/style.css',
array('astra-parent-style'),
wp_get_theme()->get('Version')
);
}
add_action('wp_enqueue_scripts', 'astra_child_enqueue_styles');
这里有一个很多人搞混的概念:get_template_directory_uri() 获取的是父主题目录,get_stylesheet_directory_uri() 获取的是当前(子)主题目录。在你没有子主题时,两者返回同一路径;启用子主题后,它们就分开了。
三个函数记牢:
| 函数 | 指谁 | 获取路径 | 获取 URI |
|---|---|---|---|
get_template_directory() / get_template_directory_uri() |
父主题 | 路径 | URI |
get_stylesheet_directory() / get_stylesheet_directory_uri() |
子主题 | 路径 | URI |
✅ 第四步:在后台启用子主题
保存后去 WordPress 后端的 外观 → 主题,你应该能看到刚才创建的子主题。点击"启用"。如果子主题的 Template: 写错了,这里会显示"父主题未安装",马上检查 style.css 里的 Template 字段。
启用后,你的网站前端应该和之前完全一样——毕竟子主题目前什么都没改,只是把父主题的样式重新加载了一遍。如果前端乱了(样式丢失、布局崩了),说明第二步的 wp_enqueue_style 写得不正确。一个快速排查思路:注释掉子主题 functions.php 中所有代码,只保留 <?php,看前端是否恢复正常。

三、常用模板覆盖实战
子主题最常用的场景不是写 PHP,而是覆盖父主题的模板文件。下面三种是外贸站最常需要修改的。
🏠 覆盖 header.php(修改页头)
假设你的 Astra 主题导航栏上方有一个你不需要的"顶部信息栏"。Astra 的 header.php 包含了它。操作步骤:
- 在父主题目录里找到
header.php - 复制到子主题目录,保持同级路径
- 在子主题的
header.php里注释或删除你不想要的部分
父主题文件:astra/header.php
子主题文件:astra-child/header.php ← 复制过来后修改
规则很简单:子主题里的文件路径必须和父主题里的一样。astra/inc/custom-header.php → astra-child/inc/custom-header.php。
📝 覆盖 single.php(修改文章页)
外贸站最常见的需求:在每篇文章底部加一个公司简介或联系方式区域。你不需要写插件,直接在子主题的 single.php 里插入一段 HTML 就行。
<?php
// astra-child/single.php
// 先完整复制父主题的 single.php,再在文章内容后插入自定义区域
while ( have_posts() ) :
the_post();
the_content();
// 自定义:文章底部添加公司简介
?>
<div class="company-bio">
<h3>关于 XX 工贸</h3>
<p>专注五金加工 15 年,服务全球 30+ 国家客户。</p>
<a href="/contact">立即询盘 →</a>
</div>
<?php
endwhile;
🦶 覆盖 footer.php(修改页脚版权)
外贸站被要求最多的修改之一:把主题自带的页脚品牌标识换成自己公司的。同样,复制父主题的 footer.php 到子主题,搜索 powered by 或主题名称,替换成你的 HTML:
// astra-child/footer.php
// 找到类似下面的代码并替换
// 原代码:
// <div class="site-info">Powered by Astra</div>
// 改为:
?>
<div class="site-info">
© <?php echo date('Y'); ?> 你的公司名. All Rights Reserved.
</div>

四、子主题 functions.php 的实战用法
除了覆盖模板,functions.php 还能做很多事。下面三个是外贸站高频需求。
🔧 禁用不需要的主题功能
<?php
// 禁用 Astra 的 Google Fonts 加载(国内访问加速)
add_filter('astra_google_fonts_enable', '__return_false');
// 禁用主题自带的 Emoji 脚本(WordPress 4.2+ 默认加载)
remove_action('wp_head', 'print_emoji_detection_script', 7);
remove_action('wp_print_styles', 'print_emoji_styles');
🌐 注册自定义小工具区域
<?php
// 在文章页侧边栏上方加一个"询盘 CTA"小工具区域
function astra_child_register_sidebar() {
register_sidebar(array(
'name' => '文章页询盘 CTA',
'id' => 'single-cta',
'before_widget' => '<div class="cta-widget">',
'after_widget' => '</div>',
'before_title' => '<h4>',
'after_title' => '</h4>',
));
}
add_action('widgets_init', 'astra_child_register_sidebar');
📜 修改 WordPress 默认行为
<?php
// 修改文章摘要长度(外贸博客摘要太长影响列表页浏览效率)
function astra_child_custom_excerpt_length($length) {
return 30; // 默认 55,改为 30 词
}
add_filter('excerpt_length', 'astra_child_custom_excerpt_length');
⚠️ 所有自定义代码都写在一个
functions.php文件里就行,不要创建多个 functions 文件。代码量大的话用注释分区。
五、子主题升级不丢修改的机制解析
理解了原理,你就能彻底放心。这一节用最短的话把机制讲透。
WordPress 更新主题时,操作对象是父主题目录。子主题目录(astra-child/)里的文件一个字都不会被碰。所以:
- 你在
astra-child/style.css里写的 CSS → 安全 - 你在
astra-child/functions.php里的 PHP 代码 → 安全 - 你在
astra-child/footer.php里改的页脚 → 安全 - 你在
astra/style.css里直接改的东西 → 升级时会丢失
换句话说,你写的代码放在子主题文件夹里,升级时就等于不存在于 WordPress 的更新路径中。
唯一需要注意的是:父主题大版本升级时,模板文件的结构可能会变。比如 Astra 4.0 重构了 header.php,你子主题里的旧版 header.php 还在用旧结构,可能出现兼容问题。解决思路是:
- 父主题升级前,在本地或测试站跑一次,对比新旧模板差异
- 如果你只覆盖了小部分模板文件(而不是十来个),大概率没影响
- 如果出问题,去子主题里删掉那个模板文件,让 WordPress 回退到父主题的版本,然后重新按新结构修改

🔧 创建子主题过程中遇到白屏(White Screen of Death),先检查
functions.php是否有 PHP 语法错误。最稳妥的办法:用 FTP 把子主题文件夹重命名(让 WordPress 自动回退到父主题),然后逐段排查代码。如果排查不清楚,去 WordPress Stack Exchange(wordpress.stackexchange.com)搜索 "child theme white screen" + 你的主题名称,大概率已有现成答案。
相关文章:#28 五大主题性能横评 · #30 页面构建器深度对比 · #22 Elementor完全指南



搞这么复杂,WordPress啥时候能内置一键建子主题啊?
纯路人,原来还有子主题这种操作,以前都是硬改。
说真的,子主题也不是万能,父主题大版本一更,你子主题里复制的旧模板照样可能冲突,还得手动删。
这教程比官方文档接地气,官方那个绕来绕去根本看不懂。
如果已经直接在父主题里改过一堆文件,现在建子主题,之前改的还能不能保留下来?
有点意思,回头把我那个站也搞一下子主题。