好的,让我们开始设计一个可扩展的WordPress主题框架,从父主题到子主题的最佳实践。
主题框架设计:父主题的构建
一个好的主题框架应该具备以下几个关键特性:
- 模块化: 将主题功能分解为独立、可重用的模块。
- 可扩展性: 允许通过子主题覆盖和增强父主题的功能。
- 可维护性: 代码结构清晰、易于理解和修改。
- 性能优化: 加载速度快、资源利用率高。
1. 目录结构
一个清晰的目录结构是模块化的基础。建议采用以下结构:
parent-theme/
├── assets/ # 存放静态资源 (CSS, JS, 图片)
│ ├── css/
│ │ ├── style.css # 主样式表
│ │ ├── custom.css # 自定义样式
│ │ └── ...
│ ├── js/
│ │ ├── script.js # 主脚本
│ │ ├── custom.js # 自定义脚本
│ │ └── ...
│ ├── images/
│ │ └── ...
│ └── fonts/
│ └── ...
├── inc/ # 存放 PHP include 文件 (主题核心功能)
│ ├── functions-theme.php # 主题核心功能函数
│ ├── functions-admin.php # 后台管理相关函数
│ ├── functions-widgets.php # 自定义小工具相关函数
│ ├── functions-hooks.php # 自定义钩子相关函数
│ ├── functions-filters.php # 自定义过滤器相关函数
│ ├── customizer/ # 自定义主题设置 (Theme Customizer)
│ │ ├── customizer.php # 自定义主题设置主文件
│ │ ├── sections/ # 自定义设置面板
│ │ │ ├── section-header.php
│ │ │ ├── section-footer.php
│ │ │ └── ...
│ │ ├── controls/ # 自定义设置控件
│ │ │ ├── control-color.php
│ │ │ ├── control-image.php
│ │ │ └── ...
│ └── template-tags.php # 模板标签
├── languages/ # 存放翻译文件 (.po, .mo)
│ └── ...
├── templates/ # 存放通用模板
│ ├── template-parts/ # 存放模板片段
│ │ ├── content.php # 文章内容模板
│ │ ├── content-page.php # 页面内容模板
│ │ ├── content-single.php # 单篇文章内容模板
│ │ ├── header.php # 页眉模板
│ │ ├── footer.php # 页脚模板
│ │ └── ...
│ ├── page-templates/ # 存放页面模板
│ │ ├── template-home.php
│ │ ├── template-contact.php
│ │ └── ...
│ ├── 404.php # 404 页面模板
│ ├── archive.php # 归档页面模板
│ ├── index.php # 主页模板
│ ├── page.php # 页面模板
│ ├── single.php # 单篇文章模板
│ └── search.php # 搜索结果页面模板
├── README.md # 主题说明文档
├── style.css # 主题样式表 (必须)
└── functions.php # 主题核心文件 (必须)
2. 核心文件:functions.php
functions.php
是主题的核心文件,负责加载主题的其他模块,并定义主题的基本功能。
<?php
/**
* 主题核心文件
*/
// 定义主题常量
define( 'THEME_VERSION', '1.0.0' );
define( 'THEME_DIR', get_template_directory() );
define( 'THEME_URI', get_template_directory_uri() );
// 加载主题文本域 (用于翻译)
load_theme_textdomain( 'parent-theme', THEME_DIR . '/languages' );
// 引入主题支持
require_once THEME_DIR . '/inc/functions-theme.php';
// 引入后台管理功能
require_once THEME_DIR . '/inc/functions-admin.php';
// 引入自定义小工具
require_once THEME_DIR . '/inc/functions-widgets.php';
// 引入自定义钩子
require_once THEME_DIR . '/inc/functions-hooks.php';
// 引入自定义过滤器
require_once THEME_DIR . '/inc/functions-filters.php';
// 引入自定义主题设置
require_once THEME_DIR . '/inc/customizer/customizer.php';
// 注册导航菜单
register_nav_menus(
array(
'primary' => __( '主导航菜单', 'parent-theme' ),
'footer' => __( '页脚导航菜单', 'parent-theme' ),
)
);
// 添加主题支持
add_theme_support( 'title-tag' );
add_theme_support( 'post-thumbnails' );
add_theme_support( 'automatic-feed-links' );
add_theme_support( 'html5', array( 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption' ) );
add_theme_support( 'customize-selective-refresh-widgets' );
add_theme_support( 'responsive-embeds' );
// 设置内容宽度
if ( ! isset( $content_width ) ) {
$content_width = 900;
}
// 注册和加载主题脚本和样式
function parent_theme_scripts() {
// 注册样式
wp_register_style( 'parent-theme-style', get_stylesheet_uri(), array(), THEME_VERSION );
wp_register_style( 'parent-theme-custom', THEME_URI . '/assets/css/custom.css', array(), THEME_VERSION );
// 注册脚本
wp_register_script( 'parent-theme-script', THEME_URI . '/assets/js/script.js', array( 'jquery' ), THEME_VERSION, true );
wp_register_script( 'parent-theme-custom', THEME_URI . '/assets/js/custom.js', array( 'jquery' ), THEME_VERSION, true );
// 加载样式
wp_enqueue_style( 'parent-theme-style' );
wp_enqueue_style( 'parent-theme-custom' );
// 加载脚本
wp_enqueue_script( 'parent-theme-script' );
wp_enqueue_script( 'parent-theme-custom' );
// 传递 PHP 数据到 JavaScript
wp_localize_script( 'parent-theme-script', 'theme_data', array(
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'ajax_nonce' ),
) );
}
add_action( 'wp_enqueue_scripts', 'parent_theme_scripts' );
// 自定义 excerpt length
function parent_theme_excerpt_length( $length ) {
return 40; // 返回自定义的 excerpt 长度
}
add_filter( 'excerpt_length', 'parent_theme_excerpt_length', 999 );
// 自定义 excerpt more
function parent_theme_excerpt_more( $more ) {
return '...'; // 返回自定义的 excerpt more
}
add_filter( 'excerpt_more', 'parent_theme_excerpt_more' );
// 添加自定义 body class
function parent_theme_body_class( $classes ) {
if ( is_front_page() ) {
$classes[] = 'front-page';
}
if ( is_singular() ) {
$classes[] = 'singular';
}
return $classes;
}
add_filter( 'body_class', 'parent_theme_body_class' );
3. 主题支持:inc/functions-theme.php
这个文件用于定义主题的基本支持功能,例如特色图像、HTML5 支持等。将其独立出来,方便管理和修改。
<?php
/**
* 主题支持功能
*/
// 添加主题支持
function parent_theme_setup() {
// 让主题支持特色图像
add_theme_support( 'post-thumbnails' );
// 添加自定义图像尺寸
add_image_size( 'featured-image', 900, 600, true ); // 固定尺寸
add_image_size( 'thumbnail-image', 150, 150, true );
// 启用 HTML5 支持
add_theme_support( 'html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
) );
// 启用自动 feed 链接
add_theme_support( 'automatic-feed-links' );
// 启用主题自定义 logo
add_theme_support( 'custom-logo', array(
'height' => 100,
'width' => 400,
'flex-height' => true,
'flex-width' => true,
'header-text' => array( 'site-title', 'site-description' ),
) );
// 启用主题自定义背景
add_theme_support( 'custom-background', apply_filters( 'parent_theme_custom_background_args', array(
'default-color' => 'ffffff',
'default-image' => '',
) ) );
// 启用主题自定义头部
add_theme_support( 'custom-header', apply_filters( 'parent_theme_custom_header_args', array(
'default-image' => '',
'default-text-color' => '000000',
'header-text' => true,
'width' => 1000,
'height' => 250,
'flex-width' => true,
'flex-height' => true,
) ) );
// 启用主题选择性刷新小工具
add_theme_support( 'customize-selective-refresh-widgets' );
// 启用主题响应式嵌入
add_theme_support( 'responsive-embeds' );
}
add_action( 'after_setup_theme', 'parent_theme_setup' );
4. 后台管理:inc/functions-admin.php
这个文件用于定义主题的后台管理功能,例如添加自定义菜单、设置页面等。
<?php
/**
* 后台管理功能
*/
// 添加自定义管理菜单
function parent_theme_admin_menu() {
add_menu_page(
__( '主题设置', 'parent-theme' ),
__( '主题设置', 'parent-theme' ),
'manage_options',
'parent-theme-settings',
'parent_theme_settings_page',
'dashicons-admin-generic',
20
);
}
add_action( 'admin_menu', 'parent_theme_admin_menu' );
// 创建设置页面
function parent_theme_settings_page() {
?>
<div class="wrap">
<h1><?php esc_html_e( '主题设置', 'parent-theme' ); ?></h1>
<form method="post" action="options.php">
<?php
settings_fields( 'parent_theme_options' );
do_settings_sections( 'parent-theme-settings' );
submit_button();
?>
</form>
</div>
<?php
}
// 注册设置
function parent_theme_register_settings() {
register_setting(
'parent_theme_options',
'parent_theme_options',
'parent_theme_sanitize_options'
);
add_settings_section(
'parent_theme_general_section',
__( '常规设置', 'parent-theme' ),
'parent_theme_general_section_callback',
'parent-theme-settings'
);
add_settings_field(
'parent_theme_option_example',
__( '示例选项', 'parent-theme' ),
'parent_theme_option_example_callback',
'parent-theme-settings',
'parent_theme_general_section'
);
}
add_action( 'admin_init', 'parent_theme_register_settings' );
// 常规设置回调
function parent_theme_general_section_callback() {
echo '<p>' . esc_html__( '在这里设置常规选项', 'parent-theme' ) . '</p>';
}
// 示例选项回调
function parent_theme_option_example_callback() {
$options = get_option( 'parent_theme_options' );
$example = isset( $options['example'] ) ? esc_attr( $options['example'] ) : '';
?>
<input type="text" name="parent_theme_options[example]" value="<?php echo $example; ?>" />
<?php
}
// 清理设置
function parent_theme_sanitize_options( $input ) {
$sanitized = array();
if ( isset( $input['example'] ) ) {
$sanitized['example'] = sanitize_text_field( $input['example'] );
}
return $sanitized;
}
5. 自定义小工具:inc/functions-widgets.php
这个文件用于注册和定义自定义小工具。
<?php
/**
* 自定义小工具
*/
// 定义自定义小工具类
class Parent_Theme_Widget extends WP_Widget {
/**
* 构造函数
*/
function __construct() {
parent::__construct(
'parent_theme_widget', // Base ID
__( 'Parent Theme Widget', 'parent-theme' ), // Name
array( 'description' => __( 'A Parent Theme Widget', 'parent-theme' ), ) // Args
);
}
/**
* 小工具前端显示
*
* @param array $args 显示小工具的参数
* @param array $instance 保存设置的值
*/
public function widget( $args, $instance ) {
$title = apply_filters( 'widget_title', $instance['title'] );
echo $args['before_widget'];
if ( ! empty( $title ) ) {
echo $args['before_title'] . $title . $args['after_title'];
}
echo __( 'Hello, World!', 'parent-theme' );
echo $args['after_widget'];
}
/**
* 小工具设置表单
*
* @param array $instance 先前保存设置的值
*/
public function form( $instance ) {
$title = isset( $instance['title'] ) ? $instance['title'] : __( 'New title', 'parent-theme' );
?>
<p>
<label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
<input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
</p>
<?php
}
/**
* 更新小工具设置
*
* @param array $new_instance 新设置的值
* @param array $old_instance 先前设置的值
*
* @return array 更新后的设置值
*/
public function update( $new_instance, $old_instance ) {
$instance = array();
$instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
return $instance;
}
} // class Parent_Theme_Widget
// 注册小工具
function parent_theme_register_widgets() {
register_widget( 'Parent_Theme_Widget' );
}
add_action( 'widgets_init', 'parent_theme_register_widgets' );
6. 自定义钩子和过滤器:inc/functions-hooks.php
和 inc/functions-filters.php
这两个文件用于定义自定义的 WordPress 钩子和过滤器,允许子主题在不修改父主题代码的情况下,修改主题的行为和输出。
inc/functions-hooks.php
:
<?php
/**
* 自定义钩子
*/
// 定义一个自定义动作钩子
function parent_theme_custom_action() {
// 执行一些操作
}
add_action( 'parent_theme_custom_hook', 'parent_theme_custom_action' );
// 使用自定义钩子
function parent_theme_example_function() {
// 在这里触发自定义钩子
do_action( 'parent_theme_custom_hook' );
}
add_action( 'wp_footer', 'parent_theme_example_function' );
inc/functions-filters.php
:
<?php
/**
* 自定义过滤器
*/
// 定义一个自定义过滤器
function parent_theme_custom_filter( $text ) {
return 'Modified: ' . $text;
}
add_filter( 'parent_theme_custom_text', 'parent_theme_custom_filter' );
// 使用自定义过滤器
function parent_theme_example_function() {
$original_text = 'Original Text';
$modified_text = apply_filters( 'parent_theme_custom_text', $original_text );
echo $modified_text;
}
add_action( 'wp_footer', 'parent_theme_example_function' );
7. 自定义主题设置:inc/customizer/
这个目录包含自定义主题设置相关的 PHP 文件,允许用户通过 WordPress 主题自定义工具修改主题的外观和行为。
inc/customizer/customizer.php
:
<?php
/**
* Theme Customizer functionality
*
* @package WordPress
* @subpackage Parent Theme
* @since Parent Theme 1.0
*/
/**
* Sets up the WordPress core customizer and enqueues customizer styles.
*
* Note that this function is hooked into the after_setup_theme hook, which
* runs before the init hook. Because of this, any styles enqueued inside
* determined conditional logic must use late_static_binding (via static::).
*/
function parent_theme_customize_register( $wp_customize ) {
// Add postMessage support for site title and description.
$wp_customize->get_setting( 'blogname' )->transport = 'postMessage';
$wp_customize->get_setting( 'blogdescription' )->transport = 'postMessage';
$wp_customize->get_setting( 'header_textcolor' )->transport = 'postMessage';
if ( isset( $wp_customize->selective_refresh ) ) {
$wp_customize->selective_refresh->add_partial( 'blogname', array(
'selector' => '.site-title a',
'render_callback' => 'parent_theme_customize_partial_blogname',
) );
$wp_customize->selective_refresh->add_partial( 'blogdescription', array(
'selector' => '.site-description',
'render_callback' => 'parent_theme_customize_partial_blogdescription',
) );
}
// Include custom controls.
require_once trailingslashit( get_template_directory() ) . '/inc/customizer/controls/control-color.php'; // Example
// Include custom sections.
require_once trailingslashit( get_template_directory() ) . '/inc/customizer/sections/section-header.php'; // Example
// Register custom sections.
Parent_Theme_Customize_Header_Section::register( $wp_customize ); // Example
// Register custom controls.
$wp_customize->register_control_type( 'Parent_Theme_Customize_Color_Control' ); // Example
// Add Header Settings section.
$wp_customize->add_section( 'header_settings', array(
'title' => __( 'Header Settings', 'parent-theme' ),
'priority' => 30,
) );
// Add Header Background Color setting and control.
$wp_customize->add_setting( 'header_background_color', array(
'default' => '#ffffff',
'sanitize_callback' => 'sanitize_hex_color',
'transport' => 'postMessage',
) );
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'header_background_color', array(
'label' => __( 'Header Background Color', 'parent-theme' ),
'section' => 'header_settings',
'settings' => 'header_background_color',
) ) );
// Example usage of custom control
$wp_customize->add_setting(
'custom_color_setting',
array(
'default' => '#000000',
'sanitize_callback' => 'sanitize_hex_color',
)
);
$wp_customize->add_control(
new Parent_Theme_Customize_Color_Control(
$wp_customize,
'custom_color_setting',
array(
'label' => __( 'Custom Color', 'parent-theme' ),
'section' => 'header_settings',
'settings' => 'custom_color_setting',
)
)
);
}
add_action( 'customize_register', 'parent_theme_customize_register' );
/**
* Render the site title for the selective refresh partial.
*
* @return void
*/
function parent_theme_customize_partial_blogname() {
bloginfo( 'name' );
}
/**
* Render the site tagline for the selective refresh partial.
*
* @return void
*/
function parent_theme_customize_partial_blogdescription() {
bloginfo( 'description' );
}
/**
* Bind JS handlers to make Theme Customizer preview reload changes asynchronously.
*/
function parent_theme_customize_preview_js() {
wp_enqueue_script( 'parent-theme-customizer', get_theme_file_uri( '/assets/js/customizer.js' ), array( 'customize-preview' ), THEME_VERSION, true );
}
add_action( 'customize_preview_init', 'parent_theme_customize_preview_js' );
/**
* Enqueue customizer styles.
*/
function parent_theme_customize_css() {
wp_enqueue_style( 'parent-theme-customizer', get_theme_file_uri( '/assets/css/customizer.css' ), array(), THEME_VERSION );
}
add_action( 'customize_controls_print_styles', 'parent_theme_customize_css' );
inc/customizer/sections/section-header.php
:
<?php
/**
* Customizer Header Section
*
* @package WordPress
* @subpackage Parent Theme
* @since Parent Theme 1.0
*/
if ( class_exists( 'WP_Customize_Section' ) ) {
/**
* Header Section
*/
class Parent_Theme_Customize_Header_Section extends WP_Customize_Section {
/**
* The type of customize section being rendered.
*
* @since 1.0.0
* @access public
* @var string
*/
public $type = 'header';
/**
* Custom section json.
*
* @since 1.0.0
* @access public
* @return void
*/
public function json() {
$json = parent::json();
$json['options'] = array( 'hide_title' => $this->hide_title );
return $json;
}
/**
* Init the section.
*
* @param WP_Customize_Manager $manager The WordPress Customize Manager.
* @param string $id A Specific ID of the section.
* @param array $args Section arguments.
* @see WP_Customize_Section::__construct()
*/
public function __construct( $manager, $id, $args = array() ) {
parent::__construct( $manager, $id, $args );
}
/**
* An Underscore (JS) template for rendering this section.
*
* Class variables for this section class are available in the `data`
* object; export custom variables by overriding
* {@see WP_Customize_Section::json()}.
*
* @see WP_Customize_Section::print_template()
*
* @access protected
* @since 4.3.0
*/
protected function render_template() {
?>
<li id="accordion-section-{{ data.id }}" class="accordion-section control-section control-section-{{ data.type }}">
<h3 class="accordion-section-title" tabindex="0">
{{ data.title }}
<# if ( data.description ) { #>
<button class="button-secondary section-description-button" type="button" aria-describedby="{{ data.id }}-description">{{ data.title }}</button>
<# } #>
</h3>
<# if ( data.description ) { #>
<div class="accordion-section-content description" id="{{ data.id }}-description">
{{{ data.description }}}
</div>
<# } #>
<ul class="accordion-section-content control-section-content">
<# data.controls.forEach( function( control ) { #>
<li>{{{ control }}}</li>
<# } ) #>
</ul>
</li>
<?php
}
/**
* Register custom section.
*
* @param WP_Customize_Manager $wp_customize Customize manager instance.
* @since 1.0.0
* @access public
* @static
*/
public static function register( $wp_customize ) {
$wp_customize->register_section_type( 'Parent_Theme_Customize_Header_Section' );
}
}
}
inc/customizer/controls/control-color.php
:
<?php
/**
* Customizer Color Control
*
* @package WordPress
* @subpackage Parent Theme
* @since Parent Theme 1.0
*/
if ( class_exists( 'WP_Customize_Control' ) ) {
/**
* Custom Color Control Class
*/
class Parent_Theme_Customize_Color_Control extends WP_Customize_Control {
/**
* The type of customize control being rendered.
*
* @since 1.0.0
* @access public
* @var string
*/
public $type = 'parent_theme_color';
/**
* Enqueue control related scripts/styles.
*
* @access public
* @since 1.0.0
* @return void
*/
public function enqueue() {
wp_enqueue_script( 'parent-theme-custom-controls-js', get_template_directory_uri() . '/assets/js/custom-controls.js', array( 'jquery', 'customize-controls', 'iris', 'underscore', 'wp-color-picker' ), THEME_VERSION, true );
wp_enqueue_style( 'parent-theme-custom-controls-css', get_template_directory_uri() . '/assets/css/custom-controls.css', array( 'customize-controls', 'wp-color-picker' ), THEME_VERSION );
}
/**
* Refresh the parameters passed to the JavaScript via JSON.
*
* @access public
* @since 1.0.0
* @uses WP_Customize_Control::json()
* @return void
*/
public function json() {
$json = parent::json();
return $json;
}
/**
* An Underscore (JS) template for rendering this control in the customizer.
*
* Class variables for this control class are available in the `data`
* object; export custom variables by overriding
* {@see WP_Customize_Control::json()}.
*
* @see WP_Customize_Control::print_template()
*
* @access protected
* @since 4.3.0
*/
protected function render_template() {
?>
<label>
<# if ( data.label ) { #>
<span class="customize-control-title">{{{ data.label }}}</span>
<# } #>
<# if ( data.description ) { #>
<span class="description customize-control-description">{{{ data.description }}}</span>
<# } #>
<input class="color-picker-hex" type="text" data-palette="{{ data.palette }}" data-default-color="{{ data.default }}" value="{{ data.value }}" data-alpha="{{ data.alpha }}" />
</label>
<?php
}
}
}
8. 模板文件:templates/
这个目录包含主题的模板文件,例如 index.php
、single.php
、page.php
等。使用 get_template_part()
函数加载模板片段,提高代码的可维护性。
index.php
:
<?php
/**
* 主页模板
*/
get_header();
?>
<div id="primary" class="content-area">
<main id="main" class="site-main">
<?php
if ( have_posts() ) :
// 加载文章循环模板
while ( have_posts() ) : the_post();
get_template_part( 'templates/template-parts/content', get_post_format() );
endwhile;
// 分页
the_posts_navigation();
else :
// 加载没有文章时的模板
get_template_part( 'templates/template-parts/content', 'none' );
endif;
?>
</main><!-- #main -->
</div><!-- #primary -->
<?php
get_sidebar();
get_footer();
?>
templates/template-parts/content.php
:
<?php
/**
* 文章内容模板
*/
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php
if ( is_singular() ) :
the_title( '<h1 class="entry-title">', '</h1>' );
else :
the_title( '<h2 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h2>' );
endif;
if ( 'post' === get_post_type() ) : ?>
<div class="entry-meta">
<?php parent_theme_posted_on(); ?>
</div><!-- .entry-meta -->
<?php
endif; ?>
</header><!-- .entry-header -->
<div class="entry-content">
<?php
the_content( sprintf(
__( 'Continue reading<span class="screen-reader-text"> "%s"</span>', 'parent-theme' ),
get_the_title()
) );
wp_link_pages( array(
'before' => '<div class="page-links">' . __( 'Pages:', 'parent-theme' ),
'after' => '</div>',
) );
?>
</div><!-- .entry-content -->
<footer class="entry-footer">
<?php parent_theme_entry_footer(); ?>
</footer><!-- .entry-footer -->
</article><!-- #post-<?php the_ID(); ?> -->
9. 样式表:style.css
style.css
是主题的样式表,用于定义主题的样式。在父主题中,应该定义主题的基本样式,例如排版、颜色、布局等。
/*
Theme Name: Parent Theme
Theme URI: https://example.com/parent-theme/
Description: Parent Theme Description
Author: Author Name
Author URI: https://example.com/
Template:
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: parent-theme
*/
/* ------------------------------------------------------------
主题基本样式
------------------------------------------------------------ */
body {
font-family: sans-serif;
line-height: 1.6;
color: #333;
}
h1, h2, h3, h4, h5, h6 {
font-weight: bold;
margin-bottom: 1rem;
}
a {
color: #007bff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
主题框架设计:子主题的构建
子主题允许在不修改父主题代码的情况下,修改主题的外观和行为。
1. 创建子主题
创建一个新的目录,作为子主题的根目录。例如,child-theme/
。
2. 创建 style.css
文件
在子主题的根目录下,创建一个 style.css
文件,并添加以下内容:
/*
Theme Name: Child Theme
Theme URI: https://example.com/child-theme/
Description: Child Theme Description
Author: Author Name
Author URI: https://example.com/
Template: parent-theme
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: child-theme
*/
/* ------------------------------------------------------------
子主题样式
------------------------------------------------------------ */
/* 覆盖父主题的样式 */
body {
font-family: serif;
color: #666;
}
/* 添加新的样式 */
.custom-class {
color: red;