本文约 5,464 字,预计阅读 14 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:为什么别人的主题有特色图,我的没有
上传文章时右侧「特色图片」模块怎么都找不到,翻遍后台设置也没有开关。搜索一圈才知道是主题没声明支持:add_theme_support( 'post-thumbnails' )。类似的情况还有:<title> 标签被 SEO 插件重复输出两遍、搜索框的 HTML5 占位属性不生效、古腾堡编辑器里的”宽幅对齐”按钮是灰的。
这些”功能开关”都由同一个函数控制。它不产生任何可见输出,只往全局变量 $_wp_theme_features 里登记一条记录,然后由核心各处通过 current_theme_supports() 查询。理解这一点,就知道它不是”锦上添花的声明”,而是主题对核心的”能力契约”。
原理分析:一个登记函数,三种使用形态
add_theme_support( string $feature, mixed ...$args )
内部实现极其简单:
// wp-includes/theme.php(简化)
function add_theme_support( $feature, ...$args ) {
global $_wp_theme_features;
if ( ! $args ) {
$_wp_theme_features[ $feature ] = true; // 形态一:布尔开关
} else {
$_wp_theme_features[ $feature ] = $args; // 形态二:带参数
}
}
三种形态对应不同类型的能力:
| 形态 | 示例 | 核心如何使用 |
|---|---|---|
| 布尔开关 | add_theme_support( 'title-tag' ) |
决定是否接管 <title> 输出 |
| 数组参数 | add_theme_support( 'html5', array( 'comment-form', 'gallery' ) ) |
逐个判断是否输出 HTML5 标记 |
| 复杂配置 | add_theme_support( 'post-thumbnails', array( 'post', 'page' ) ) |
限定作用范围 |
查询侧统一走 current_theme_supports( $feature, ...$args ),比如 current_theme_supports( 'html5', 'gallery' ) 会检查 gallery 是否在数组里。移除用 remove_theme_support( $feature ),一般只在子主题里用来”反悔”父主题的声明。
注意调用时机:必须在 after_setup_theme 钩子里调用(或直接在 functions.php 顶层,此时 after_setup_theme 尚未触发)。挂在 init 上太晚,很多功能已经初始化完毕。
保姆级实操
第 1 步:基础必备项
add_action( 'after_setup_theme', function () {
// 由主题接管 <title>,避免与 SEO 插件重复输出(WP 4.1+)
add_theme_support( 'title-tag' );
// 开启特色图片,数组参数限定作用的文章类型(WP 2.9+)
add_theme_support( 'post-thumbnails' );
// 自动输出 RSS feed 链接到 <head>(WP 3.0+)
add_theme_support( 'automatic-feed-links' );
} );
title-tag 开启后,<head> 里不要再手写 <title>,也不要在 header.php 里调 wp_title()(已废弃)。SEO 插件(Yoast、Rank Math)检测到 title-tag 后会接管输出,不会重复。
第 2 步:HTML5 标记支持
add_theme_support( 'html5', array(
'search-form', // 搜索表单用 <input type="search"> 与 HTML5 占位符
'comment-form', // 评论表单
'comment-list', // 评论列表用 <ol class="comment-list">
'gallery', // 图库用 <figure>/<figcaption>
'caption', // 图片说明用 <figure>/<figcaption>
'style', // 去掉 <style> 标签上的 type="text/css"
'script', // 去掉 <script> 标签上的 type="text/javascript"
) );
'style' 与 'script' 是 WP 5.3 加入的,用于移除 HTML5 已默认的类型属性,对通过校验工具有帮助。少声明一项,对应的输出就会退回 XHTML 风格标记。
第 3 步:块编辑器(古腾堡)相关
add_theme_support( 'wp-block-styles' ); // 加载核心块默认样式(WP 5.0+)
add_theme_support( 'align-wide' ); // 启用"宽幅/全宽"对齐按钮(WP 5.0+)
add_theme_support( 'responsive-embeds' ); // 嵌入内容自适应(WP 4.9+)
add_theme_support( 'editor-styles' ); // 编辑器加载 editor-style.css(WP 3.0+)
add_theme_support( 'custom-logo', array( // 站点 Logo(WP 4.5+)
'height' => 60,
'width' => 200,
'flex-height' => true,
'flex-width' => true,
) );
add_theme_support( 'customize-selective-refresh-widgets' ); // 小组件局部刷新(WP 4.5+)
add_theme_support( 'post-formats', array( 'aside', 'gallery', 'video' ) ); // 文章形式(WP 3.1+)
editor-styles 要在 after_setup_theme 里再补一句资源加载,否则不生效:
add_action( 'after_setup_theme', function () {
add_editor_style( 'assets/css/editor-style.css' );
} );
第 4 步:自定义 Logo 的前台输出
// header.php 里
if ( has_custom_logo() ) {
the_custom_logo();
} else {
printf(
'<a href="%1$s" class="site-title">%2$s</a><p class="site-desc">%3$s</p>',
esc_url( home_url( '/' ) ),
esc_html( get_bloginfo( 'name' ) ),
esc_html( get_bloginfo( 'description' ) )
);
}
the_custom_logo() 会输出带 custom-logo 类的 <a><img></a>,并自动带 srcset,主题只需给它写宽度样式。
第 5 步:加自定义能力,并让插件能查询
主题也可以自己登记一项能力,供插件侧判断:
// 主题声明:支持深色模式
add_theme_support( 'mmf-dark-mode' );
// 插件里查询
if ( current_theme_supports( 'mmf-dark-mode' ) ) {
add_action( 'wp_footer', 'myplugin_inject_dark_toggle' );
}
这是主题与插件解耦协作的标准方式,比”检测主题名是不是 Astra”可靠得多。
第 6 步:验证声明是否生效
wp eval 'var_dump( current_theme_supports( "post-thumbnails" ) );'
wp eval 'print_r( get_theme_support( "html5" ) );'
后台也能肉眼验证:文章编辑页右侧出现「特色图片」模块 → post-thumbnails 生效;「外观 → 自定义」里出现「站点身份 → Logo」→ custom-logo 生效;编辑器段落工具栏出现”宽幅对齐” → align-wide 生效。调用 the_custom_logo() 之外的自定义输出,记得按输出转义规范 esc_html esc_attr esc_url处理。
常见踩坑
- 挂在
init上。 太晚,title-tag等需要在模板渲染前完成登记。统一挂after_setup_theme。 header.php里既手写<title>又开title-tag。 页面源码里出现两个<title>,搜索引擎抓取结果不稳定。- 开了
post-thumbnails但前台不显示。 声明只是让后台能上传,前台还必须调用the_post_thumbnail(),且需要图片尺寸,见add_image_size 自定义缩略图尺寸。 html5传了字符串。add_theme_support( 'html5', 'gallery' )会把整个参数存成字符串,判断时匹配失败。必须传数组。- 子主题想去掉父主题的能力却改了父主题文件。 应在子主题里
remove_theme_support(),注意钩子优先级要更晚:
add_action( 'after_setup_theme', function () {
remove_theme_support( 'post-formats' );
}, 11 ); // 父主题默认 10,子主题用 11 才能覆盖
- 案例: 某站升级主题后,Google Search Console 里大量页面报”标题重复/标题过短”。排查发现新主题没声明
title-tag,header.php里手写了一个<title><?php wp_title(); ?></title>,而wp_title()在 WP 4.4 之后已废弃且输出为空,导致部分页面<title>只剩站点名。补上add_theme_support( 'title-tag' )、删除手写标签后两周内恢复正常。 - 把
add_theme_support写在条件判断里。 比如if ( is_home() )内部——此时after_setup_theme早已过去,is_home()也还没确定,声明会静默失效。
总结
配置 add_theme_support 的标准动作是:在 after_setup_theme 里一次性声明,不做条件判断;基础三项(title-tag、post-thumbnails、automatic-feed-links)任何主题都该有;块编辑器时代再加 wp-block-styles、align-wide、responsive-embeds、editor-styles、custom-logo。验证别靠感觉,用 wp eval 'var_dump( current_theme_supports( "xxx" ) );' 一条命令确认。它是主题与核心之间最基础的一份契约,写得越完整,插件与编辑器的行为越可预期。
