WordPress子主题创建:写对 Template 一行,父主题更新不丢改动

倪叶明

作者

更新于 ·发布于

子主题创建这件事,最反直觉的地方在于:整个子主题只需要一个style.css就能成立,可这个文件里真正决定成败的,是Template那一行。Template的值必须与父主题文件夹名100%一致,差一个字符,WordPress就匹配不上父主题,子主题等于白建。官方把style.css定为子主题唯一绝对必需的文件,父主题更新时,子主题里的改动不会丢。

做英文独立站,主题这层能不动父主题就不动。主题这块最省事的管法,就是从第一天用子主题,改动全放在子主题里,父主题怎么更新都不心疼。

  • 是什么:子主题是父主题的扩展,不直接改父主题代码就能改现有主题。
  • 官方唯一必需文件:style.css。没有它,子主题不成立。
  • Template必须与父主题文件夹名逐字一致,否则WordPress匹配不上。
  • 样式不生效,多半是父主题没加载子主题样式表,要自己在functions.php里入队。

这篇从建文件夹、写头部、上传启用讲到两个最容易踩的坑,把创建这件事一次做对,第一次摸WordPress后台的可以先看WordPress建站教程。

子主题和父主题到底差在哪,为什么改主题要先建子主题

先把关系说清楚。父主题是一个完整的主题,能单独安装、单独启用,管着整个站的外观和功能。子主题是挂在父主题下面的另一套文件,它自己不是一个完整主题,离开父主题跑不起来。

WordPress官方手册Child Themes页面,说明子主题是父主题的扩展
官网说明截图:子主题是父主题的扩展,不直接改父主题代码就能改现有主题。

子主题的定义很直接:它是父主题的扩展,用来在不直接编辑父主题代码的前提下修改现有主题。父主题负责原来那套东西,你只在子主题里写要改的那部分。

子主题默认继承父主题的一切,你只写要改的那部分

子主题默认包含父主题的全部内容,包括设计和功能。父主题有的模板、样式、函数,子主题不用复制一遍就能用。你打开子主题,前台看起来跟父主题一模一样,这是正常的,因为你还没写任何定制。

真正要你动手的,只有想改的那几处。改颜色就写CSS,改页脚就放一个同名的页脚模板,加功能就在functions.php里加一个函数。这叫只写需要的代码,省的是开发时间。

父主题更新不丢改动,这是子主题存在的理由

直接改父主题的文件,比如把一段代码写进父主题的functions.php,当时能用。下次主题更新,整包文件被覆盖,你写的那段就没了。这不是好做法,下次更新你的函数就会消失。

子主题把你的改动放在另一套文件里,跟父主题隔开。父主题更新只覆盖它自己的文件,子主题的文件不动,改动还在。子主题的好处里有一条是让改动可迁移、可复制,说的也是这个隔离。

只有两级:父主题和子主题,没有孙主题

WordPress的标准主题层级只有两级,父主题和子主题。目前不支持在子主题下面再挂一个子主题。你在子主题上再建子主题,WordPress认不出来。

还有一点容易绕进去:所有主题,除非它明确声明自己是子主题,技术上都是父主题。一个主题能不能当父主题,不看它名字里有没有parent,看它是不是一个能独立安装启用的完整主题。

选主题这层,免费和付费的差别可以另看,免费主题与付费主题讲的是怎么挑,跟子主题创建是两件事。

WordPress子主题怎么创建:建文件夹、写style.css、上传启用,再补一步入队

整个创建过程在WordPress后台和文件管理器里完成,不用装插件。下面按动作拆开,每一步都给出错了往哪看。

第一步:在wp-content/themes下建一个kebab-case文件夹

给子主题起个名,然后在wp-content/themes目录下新建文件夹。文件夹名用主题名的小写连字符版本,官方示例是grand-sunrise。这个名字是你自己定的,但后面写Template时要跟父主题的文件夹名对上,两个名字别搞混。

WordPress找主题的方式是遍历wp-content/themes下的每个文件夹,看里面有没有style.css。找到就读取文件开头那一小段,判断有没有标准的文件头部。所以文件夹建对位置只是第一步,style.css必须放在这个文件夹的根目录,不能塞进子目录。

后台外观的主题列表里看不到你刚建的子主题,先回查这一条:style.css是不是在主题根目录。放错一层,WordPress就当这个文件夹不存在。

第二步:写style.css头部,Template一行是关键

在子主题文件夹里新建style.css。这是子主题存在的唯一绝对必需文件,别的都可以没有,这个不能没有。

文件开头写头部注释,至少两行:

/*
Theme Name: Grand Sunrise
Template: twentytwentyfour
*/

Theme Name写子主题的名字,随便起。Template写父主题的文件夹名,不是父主题在后台显示的名字。这个值必须与父主题文件夹名100%匹配,相对wp-content/themes这个目录。父主题后台显示「Twenty Twenty-Four」,文件夹名是twentytwentyfour,Template里要写twentytwentyfour。

对不上的后果是WordPress匹配不上父主题,子主题启用不了,或者启用了但什么都不继承。回查的办法很笨但有效:打开wp-content/themes,把父主题那个目录名复制出来,贴到Template后面,逐字比对一遍,注意大小写和连字符。

第三步:打包ZIP上传,后台Appearance > Themes点Activate

把子主题文件夹打成ZIP。进WordPress后台,走Appearance > Themes > Add New,上传这个ZIP,装完在主题列表里找到它,点Activate启用。

启用后前台看起来跟父主题一模一样,这是对的。现在看起来没区别,是因为你还没做定制,但子主题已经建成了。别因为前台没变化就以为没成功。

如果启用后前台真的出问题,先确认一件事:你启用的是子主题,不是父主题。主题列表里两个主题名字可能很像,点Activate之前看清名字。

第四步:按父主题的情况,决定要不要在functions.php里入队样式

这一步是子主题创建里最容易漏的。子主题的style.css写好了,不等于它会自动加载。加不加载,取决于父主题怎么处理样式表。

打开父主题的functions.php,看它入队了哪些样式表。这件事每个主题都不一样,没有硬性规则,必须看代码。

看下来是三种情况:

  1. 父主题同时加载自己的style.css和子主题的style.css。这种情况下子主题什么都不用做,样式表会自动加载。
  2. 父主题只加载自己的style.css。这时子主题要自己入队自己的样式,用get_stylesheet_uri()拿子主题样式表的地址。
  3. 父主题只加载当前活动主题的样式表,比如用get_stylesheet_uri()。这种写法会自动加载子主题的样式表,但父主题的样式表反而可能没加载,这时子主题还要用get_parent_theme_file_uri('style.css')把父主题的样式补上。

入队代码挂在wp_enqueue_scripts这个动作上,官方示例的函数名是grand_sunrise_enqueue_styles:

add_action( 'wp_enqueue_scripts', 'grand_sunrise_enqueue_styles' );

函数名加自己的主题前缀,样式表的$handle也要唯一,别跟父主题或者插件重名。

写完发现样式还是不生效,回查顺序是:先看父主题在入队哪些样式表,再看子主题要不要自己入队,最后看两边的函数名有没有撞。主题这层改动对搜索的影响,可以另看主题对SEO的影响。

子主题里改模板文件:放同名文件覆盖,别动父主题

子主题不只能改样式,还能改模板。办法是在子主题里放一个跟父主题同名的文件,WordPress加载时会优先用子主题的这个,父主题原来那个不动。

覆盖范围很宽:模板、部件、图案都能覆盖。模板是page.php、single.php这类,部件是header、footer这类,图案是区块主题里的pattern。覆盖图案时除了文件名一样,还要有相同的注册Slug字段,不然WordPress认不出这是同一个图案。

覆盖文件里如果还要引用别的文件,分两种写法。包含PHP文件用get_theme_file_path(),官方示例是require_once get_theme_file_path( 'inc/functions-helpers.php' );。按URL引用文件,比如图片或样式表,用get_theme_file_uri()。两个函数别用混,一个走服务器路径,一个走网址。

覆盖文件有个限度。在子主题里做大量定制,文件越放越多,最后会变成管理负担:父主题更新了模板结构,你的同名文件还是旧结构,两边对不上。这种大型项目更适合fork原主题,做一个自己的完整主题,具体哪个项目走哪条路要逐案决定。

子主题创建要用的数字和限制

创建过程本身不复杂,但有几个数字和规则是硬的,写代码和排查时都会碰到。

项目 数值/规则
WordPress读取style.css判断头部的数据量 前8kb
主题层级 只有父、子两级,不支持孙主题
wp_enqueue_style的$media默认值 all,可传print、screen或媒体查询
wp_enqueue_style引入版本 2.6.0
子主题章节最后更新 2024年1月26日

8kb这条决定了style.css的头部必须写在文件最前面。你可以在头部后面接几百行CSS,但Theme Name和Template这两行要出现在文件开头那一小段里,写在后面WordPress读不到。

两级这条是硬限制,别想着在子主题上再套一层。样式表那两条是写代码时会碰到的:$media不传就是all,版本号别乱塞。

子主题创建不生效、报错,按这个顺序排查

子主题建完,出了问题基本落在三个地方。

wp_enqueue_style函数参考页$media默认值all的说明
官网说明截图:$media不传默认all,可传print、screen或媒体查询。

坑一:把父主题functions.php的代码直接复制进子主题

结论是不要复制。子主题的functions.php不覆盖父主题的functions.php,两个文件都会加载,而且子主题的先加载。你把父主题的函数原样搬过来,同一个函数名出现两次,WordPress直接报致命错误。

正确做法是只写父主题里没有的新函数,函数名加主题前缀。官方要求主题开发者给函数、类、变量起唯一名,用主题名或缩写做前缀,就是为了减少这种冲突。命名冲突在WordPress里会让站点报错或者行为异常,不是小事。

坑二:Template与父主题文件夹名不完全一致

结论是差一个字符都不行。Template的值必须是父主题文件夹名,相对wp-content/themes,大小写、连字符、单复数都要对上。写成父主题在后台显示的名字,WordPress匹配不上,子主题等于没挂上父主题。

回查办法在前面第二步写过,打开wp-content/themes把目录名复制出来比对。

坑三:用time()做版本号

结论是别用。有人为了让自己改的样式立刻生效,在样式表地址后面拼一个time(),每次刷新版本号都变。这样做几乎在所有情况下都会破坏缓存,浏览器每次都重新下载样式表,站点变慢,缓存插件也失效。

版本号用主题的版本号或者一个固定的字符串就行。wp_enqueue_style的$ver参数设成false会自动带上当前WordPress版本号,设成null就不加版本号。

排查顺序:先看样式表,再看函数

子主题样式不生效,第一步看父主题在入队哪些样式表,第二步看子主题要不要自己入队,第三步看两边函数有没有重名。这个顺序能解决大部分问题,因为样式不生效最常见的原因就是父主题只加载了自己的样式表,子主题的style.css根本没被加载。

如果换主题或子主题之后整个站打不开,先分清是主题不兼容还是服务器报错。主题这层的问题看WordPress主题不兼容,页面直接报500的看WordPress 500错误。

不想折腾子主题,有没有替代思路

如果只是改颜色、字体、间距这类样式,先翻一遍父主题的后台设置页,看有没有现成的自定义入口。有的话直接填,不用建子主题,也不用写代码。这是成本最低的一条路。

如果定制量大到要改很多模板,子主题就不是最省事的路了,更适合fork原主题,做一个自己的完整主题,后面自己维护。走哪条路要按项目定,没有统一答案。

如果问题不在改动,而在速度,那方向就不一样了。子主题不解决加载慢的问题,提速可以看WordPress速度优化。

用AI写子主题代码,哪几步能省、哪几步必须自己核

子主题创建里,纯写代码的部分可以让AI起草,判断和验收还得自己做。

AI能帮的四步:

  1. 根据父主题文件夹名,生成style.css的头部注释草稿,把Theme Name和Template两行先写出来。
  2. 根据父主题加载样式表的情况,生成对应的functions.php入队代码草稿,get_stylesheet_uri()和get_parent_theme_file_uri('style.css')两种写法都能让它写。
  3. 检查子主题functions.php里有没有跟父主题重名的函数,列出来并提示加主题名前缀。
  4. 把父主题的模板文件改写成子主题同名覆盖文件的草稿。

下面三条提示词是本文给的示例,不是官方模板,可以直接复制改一下填空:

  • 「我的父主题文件夹名是____,请生成子主题style.css的头部注释,包含Theme Name和Template字段,Template值必须与父主题文件夹名完全一致。」
  • 「我的父主题只加载自己的style.css,请给出在子主题functions.php里用wp_enqueue_scripts钩子和get_stylesheet_uri()入队子主题样式的代码,函数名加我的主题前缀。」
  • 「这是我的子主题functions.php和父主题functions.php,请列出两者重名的函数,并给出加前缀后的改写建议。」

必须人做的有三个动作。在wp-content/themes下亲手建子主题文件夹,建完确认文件夹名跟style.css里Template的值逐字一致。打开父主题的functions.php,看它到底入队了哪些样式表,据此决定子主题要不要自己写入队代码。在后台Appearance > Themes点Activate启用子主题,看前台样式跟预期是否一致,不一致就回头补入队父主题样式表。

这三步没有工具能替你点。猎者出海的AI Agent做建站这块,是把从空服务器到上线分成十个阶段,每段设一道闸门,每段都要人验收,不是丢进去就自动出站。

常见问题

子主题能不能再做孙主题?

不能。WordPress的标准主题层级只有父、子两级,不支持孙主题。你在子主题上再建一个子主题,WordPress不会把它当第三层处理。

子主题的functions.php会覆盖父主题的吗?

不会。两个文件都会加载,子主题的先加载,父主题的后加载。所以子主题里只写新增函数,函数名加前缀,别把父主题的代码搬过来。

父主题同时加载两个样式表,子主题还要写代码吗?

不用。父主题同时加载自己的style.css和子主题的style.css时,子主题的样式表会自动加载,子主题什么都不用做。判断办法是打开父主题的functions.php看它入队了哪些样式表。

区块主题必须加载style.css吗?

通常不需要。区块主题的样式一般由theme.json处理,加载style.css是可选步骤。只有确定要让style.css里的CSS生效时才做这一步。

子主题创建要花钱吗、要多久?

子主题不用买插件,也不用买主题,就是你自己建的一个文件夹加一个style.css。要多久看你对后台和文件管理器熟不熟,步骤就那几步,走完就算建好。

子主题这件事,卡人的地方不在写CSS,在Template那一行跟父主题文件夹名对不上。对上之后,父主题怎么更新,你改的东西都还在。站从空服务器到上线要过的关不止主题这一道,猎者出海的AI Agent把建站分成十个阶段,每段设一道闸门,一段过完再走下一段。

发表评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注