搜索全站
主题 16 分钟阅读

用 Underscores(_s)从零做 WordPress 主题:生成、精简与补齐模板

Underscores(_s)是官方团队维护的主题起手式,自带完整模板结构却没有任何视觉样式。本文走一遍从生成、精简到补齐模板的完整流程,含目录说明、改造代码与打包前的检查点。

U
UFO_PF 2021-06-10 · 阅读 16 分钟
用 主题
阅读提示
本文约 6,336 字,预计阅读 16 分钟。文中命令与配置均经过实测,可直接参考执行。

引言:从空白页到能用的主题,中间隔着二十个文件

新建一个 WordPress 主题,理论上只需要 style.css 和 index.php 两个文件。但真要交付,你得处理:header、footer、侧边栏、单篇文章、页面、归档、搜索结果、404、评论、分页、菜单、特色图、国际化……挨个从零写,光是搞清楚模板层级就要花几天。

Underscores(GitHub 上的 Automattic/_s)就是为了省掉这段重复劳动:它是一个「什么都齐了但什么都没设计」的主题骨架,模板层级完整、代码符合官方编码规范、带 Sass 源码和构建脚本、可访问性基础(跳转链接、screen-reader-text)也已就位。它的定位很明确——起点,不是成品。你要做的是三件事:精简掉用不上的部分、按设计稿补齐模板、把占位函数名换成自己的前缀。

原理分析:_s 的目录结构与设计取舍

生成后的典型结构:

路径 作用 是否必留
functions.php 主题初始化、注册菜单/侧边栏/脚本 必留
header.php / footer.php 头尾结构 必留
index.php 兜底模板 必留(WordPress 强制)
single.php / page.php / archive.php / search.php / 404.php 各场景模板 按需
sidebar.php 侧边栏 无侧边栏可删
comments.php 评论模板 按需
template-parts/ 可复用的内容片段(content.php 等) 建议留
inc/template-tags.php 自定义模板标签(posted_on 等) 建议留
inc/template-functions.php 钩子类辅助函数 建议留
inc/customizer.php Customizer 示例 按需
inc/jetpack.php Jetpack 支持声明 不用 Jetpack 可删
sass/ SCSS 源码,分模块 必留(或换构建方式)
js/navigation.js、js/skip-link-focus-fix.js 菜单与跳转链接脚本 建议留

_s 的哲学是「少即是多」:它故意不提供任何视觉设计(连 .container 都没有),逼你从零写样式;同时把所有 WordPress 规范动作都做对(wp_body_open、body_class、post_class、the_posts_navigation、escaping 全覆盖),保证你能直接提交官方目录审核。

一个关键细节:所有函数名都以 _s_ 开头,生成时若指定了 slug 会自动替换为你的前缀(如 mimangfei_)。如果手动下载 zip,记得全局替换,否则插件/子主题冲突时很难排查。

保姆级实操

第一步:生成主题骨架

两种方式。官网生成(underscores.me)填主题名与作者即可下载;命令行更可控:

cd wp-content/themes
wp scaffold _s mimangfei \
  --theme_name="迷忙飞主题" \
  --author="迷忙飞" \
  --author_uri="https://mimangfei.com" \
  --activate

生成后先确认前缀替换是否成功:

grep -rn "_s_" mimangfei/ | head -20

第二步:精简

cd mimangfei
# 不用 Jetpack
rm inc/jetpack.php
# 站点无侧边栏(企业站常见)
rm sidebar.php
# 不需要自定义 Customizer 示例
rm inc/customizer.php

同时把 functions.php 里对应的 require 删掉:

require get_template_directory() . '/inc/template-tags.php';
require get_template_directory() . '/inc/template-functions.php';
// 已删除:inc/customizer.php、inc/jetpack.php

删 sidebar.php 后,还要去掉 register_sidebar() 的调用和 functions.php 里的 mimangfei_widgets_init,否则后台小工具页面会有空区域。

第三步:补齐主题支持与菜单

if ( ! function_exists( 'mimangfei_setup' ) ) :
    function mimangfei_setup() {
        load_theme_textdomain( 'mimangfei', get_template_directory() . '/languages' );

        add_theme_support( 'automatic-feed-links' );
        add_theme_support( 'title-tag' );
        add_theme_support( 'post-thumbnails' );
        add_theme_support( 'responsive-embeds' );
        add_theme_support( 'editor-styles' );
        add_theme_support( 'html5', array(
            'search-form',
            'comment-form',
            'comment-list',
            'gallery',
            'caption',
            'style',
            'script',
        ) );

        register_nav_menus( array(
            'primary' => esc_html__( '主导航', 'mimangfei' ),
            'footer'  => esc_html__( '页脚导航', 'mimangfei' ),
        ) );
    }
endif;
add_action( 'after_setup_theme', 'mimangfei_setup' );

set_post_thumbnail_size( 1200, 675, true ) 这类按需补,title-tag 一定不能漏(否则 <title> 不输出,SEO 直接扣分)。

第四步:补齐内容模板

template-parts/content.php 是列表与详情页共用的片段:

<article id="post-<?php the_ID(); ?>" <?php post_class( 'entry' ); ?>>
    <header class="entry-header">
        <?php the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' ); ?>
        <div class="entry-meta">
            <?php mimangfei_posted_on(); ?>
        </div>
    </header>

    <?php if ( has_post_thumbnail() ) : ?>
        <a class="entry-thumb" href="<?php the_permalink(); ?>">
            <?php the_post_thumbnail( 'medium_large', array( 'loading' => 'lazy' ) ); ?>
        </a>
    <?php endif; ?>

    <div class="entry-summary">
        <?php the_excerpt(); ?>
    </div>
</article>

再根据设计稿补 template-parts/content-single.php(正文页)、template-parts/content-page.php(页面),用 get_template_part( 'template-parts/content', 'single' ) 按需引入。

第五步:接上构建与样式

npm install
npx sass sass/style.scss style.css --watch

sass/ 目录下按模块拆分,建议的改造是加一个 _variables.scss 统一颜色与间距:

// sass/variables-site/_variables-site.scss
$mf-accent:   #2563eb;
$mf-text:     #1a1a1a;
$mf-muted:    #6b7280;
$mf-container: 1200px;
$mf-gap:      1.5rem;

按需求可换成 Tailwind 之类的方案,思路见 Tailwind 与 WordPress 主题结合。

第六步:脚本与样式的加载检查

add_action( 'wp_enqueue_scripts', 'mimangfei_scripts' );

function mimangfei_scripts() {
    wp_enqueue_style( 'mimangfei-style', get_stylesheet_uri(), array(), wp_get_theme()->get( 'Version' ) );

    wp_enqueue_script(
        'mimangfei-navigation',
        get_template_directory_uri() . '/js/navigation.js',
        array(),
        wp_get_theme()->get( 'Version' ),
        true
    );

    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }
}

第七步:补齐 style.css 头部与截图

/*
Theme Name: 迷忙飞主题
Theme URI: https://mimangfei.com/themes/mimangfei
Author: 迷忙飞
Author URI: https://mimangfei.com
Description: 轻量、语义化、面向内容站点的 WordPress 主题。
Requires at least: 6.0
Tested up to: 6.8
Requires PHP: 7.4
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: mimangfei
Tags: blog, custom-logo, custom-menu, translation-ready
*/

再加一张 1200×900 的 screenshot.png,后台就能看到主题预览图。

常见踩坑

  1. 忘了全局替换 _s_ 前缀:与父主题或插件函数重名,出现「Cannot redeclare」致命错误。
  2. 删了 sidebar.php 却没删 get_sidebar():前台报模板文件缺失的致命错误。
  3. load_theme_textdomain 写错 text domain:所有 __() 翻译都不生效,且 Theme Check 会报错。
  4. Sass 编译出来的 style.css 覆盖了头部注释:sass/style.scss 编译时不会自动保留注释,头部注释应写在编译产物的 style.css 顶部或用 /*! */ 保留注释语法。
  5. wp_body_open() 缺失:插件注入内容(如统计代码、AMP 组件)位置错乱。
  6. 案例:某开发者用 underscores.me 生成主题后直接开始写样式,交付时客户在后台「外观 → 菜单」里找不到菜单位置——因为 mimangfei_setup() 里只注册了默认的 menu-1,而他改了模板里的 theme_location 却没同步注册。排查方式是比对 register_nav_menus 与 wp_nav_menu( array( 'theme_location' => ... ) ) 两个字符串是否完全一致。
  7. 把 index.php 删掉:WordPress 要求主题必须有 index.php 作为兜底,缺失会导致主题无法启用。
  8. npm install 后忘了编译:style.css 只有头部注释没有任何样式,前台一片空白。

总结

_s 的正确用法是「当成规范参考,而不是最终产品」。交付前的检查点:所有函数名已换成自己的前缀、未使用的 inc/ 文件已删且 require 已同步、title-tag 与 post-thumbnails 已声明、Sass 编译产物里保留了头部注释、screenshot.png 就位、用 Theme Check 跑一遍无 REQUIRED 项(见 Theme Check 自检)。这套流程走完,你的主题在结构上已经和官方目录里的优质主题没有本质差别;若想进一步做视觉统一,可继续参考 theme.json 全局样式 的做法迁移到区块主题。

U
UFO_PF作者

专注 WordPress 生态的实战作者,内容以「可复制、可验证」为第一原则。

留下你的想法

邮箱地址不会被公开。带 * 的为必填项。