本文是《WordPress主题开发从入门到精通》系列教程的第十二篇。我们将学习如何使用WordPress自定义器(Customizer)API,为主题添加可视化的设置选项。
你是否羡慕过Twenty系列主题那种在后台实时预览主题设置的效果?这就是WordPress自定义器(Customizer)的强大之处。它允许用户在修改主题设置时实时看到变化,大大提升了用户体验。
今天我们就来学习如何为我们的主题添加自定义器支持,实现专业级的主题设置界面。
什么是WordPress自定义器?为什么需要它?
WordPress自定义器是一个可视化主题设置界面,它允许用户:
- 实时预览:修改设置时立即看到效果,无需保存刷新
- 直观操作:所见即所得的设置体验
- 安全测试:可以预览更改而不影响前台网站
- 发布控制:满意后再发布更改
相比传统的主题选项页面,自定义器的优势:
- 更好的用户体验
- 更直观的设置方式
- WordPress官方推荐的标准
- 与核心功能无缝集成
第一步:基础设置 - 添加站点标识自定义
让我们从最基本的站点标识设置开始。在functions.php中添加:
/**
* 注册主题自定义器设置
*/
function mft_theme_customizer($wp_customize) {
// == 第一部分:站点标识 ==
// 1.1 网站Logo
$wp_customize->add_setting('mft_site_logo', array(
'default' => '',
'transport' => 'refresh', // 或 'postMessage' 用于实时更新
'sanitize_callback' => 'esc_url_raw'
));
$wp_customize->add_control(new WP_Customize_Image_Control($wp_customize, 'mft_site_logo', array(
'label' => __('网站Logo', 'my-first-theme'),
'section' => 'title_tagline', // 使用现有的"站点标识"区域
'settings' => 'mft_site_logo',
'priority' => 10
)));
// 1.2 移动端Logo(不同尺寸)
$wp_customize->add_setting('mft_mobile_logo', array(
'default' => '',
'transport' => 'refresh',
'sanitize_callback' => 'esc_url_raw'
));
$wp_customize->add_control(new WP_Customize_Image_Control($wp_customize, 'mft_mobile_logo', array(
'label' => __('移动端Logo(可选)', 'my-first-theme'),
'section' => 'title_tagline',
'settings' => 'mft_mobile_logo',
'priority' => 15
)));
// 1.3 网站副标题
$wp_customize->add_setting('mft_site_description', array(
'default' => '',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_text_field'
));
$wp_customize->add_control('mft_site_description', array(
'label' => __('网站副标题', 'my-first-theme'),
'section' => 'title_tagline',
'type' => 'text',
'priority' => 20
));
}
add_action('customize_register', 'mft_theme_customizer');
第二步:创建自定义区域和面板
现在让我们创建专属的自定义区域,更好地组织设置选项。
/**
* 创建自定义区域和面板
*/
function mft_theme_customizer_sections($wp_customize) {
// == 创建面板:主题设置 ==
$wp_customize->add_panel('mft_theme_settings', array(
'title' => __('主题设置', 'my-first-theme'),
'description' => __('自定义主题外观和功能', 'my-first-theme'),
'priority' => 30,
));
// == 区域1:头部设置 ==
$wp_customize->add_section('mft_header_settings', array(
'title' => __('头部设置', 'my-first-theme'),
'description' => __('自定义网站头部样式', 'my-first-theme'),
'panel' => 'mft_theme_settings',
'priority' => 10,
));
// 头部背景颜色
$wp_customize->add_setting('mft_header_bg_color', array(
'default' => '#ffffff',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color'
));
$wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'mft_header_bg_color', array(
'label' => __('头部背景颜色', 'my-first-theme'),
'section' => 'mft_header_settings',
'settings' => 'mft_header_bg_color',
'priority' => 10
)));
// 头部文字颜色
$wp_customize->add_setting('mft_header_text_color', array(
'default' => '#333333',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color'
));
$wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'mft_header_text_color', array(
'label' => __('头部文字颜色', 'my-first-theme'),
'section' => 'mft_header_settings',
'settings' => 'mft_header_text_color',
'priority' => 20
)));
// 头部高度
$wp_customize->add_setting('mft_header_height', array(
'default' => '80',
'transport' => 'postMessage',
'sanitize_callback' => 'absint'
));
$wp_customize->add_control('mft_header_height', array(
'label' => __('头部高度 (px)', 'my-first-theme'),
'section' => 'mft_header_settings',
'type' => 'number',
'input_attrs' => array(
'min' => 50,
'max' => 200,
'step' => 5
),
'priority' => 30
));
// == 区域2:颜色设置 ==
$wp_customize->add_section('mft_color_settings', array(
'title' => __('颜色设置', 'my-first-theme'),
'description' => __('自定义网站主题颜色', 'my-first-theme'),
'panel' => 'mft_theme_settings',
'priority' => 20,
));
// 主色调
$wp_customize->add_setting('mft_primary_color', array(
'default' => '#3498db',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color'
));
$wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'mft_primary_color', array(
'label' => __('主色调', 'my-first-theme'),
'section' => 'mft_color_settings',
'settings' => 'mft_primary_color',
'priority' => 10
)));
// 次要颜色
$wp_customize->add_setting('mft_secondary_color', array(
'default' => '#2c3e50',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color'
));
$wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'mft_secondary_color', array(
'label' => __('次要颜色', 'my-first-theme'),
'section' => 'mft_color_settings',
'settings' => 'mft_secondary_color',
'priority' => 20
)));
// 背景颜色
$wp_customize->add_setting('mft_background_color', array(
'default' => '#f8f9fa',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_hex_color'
));
$wp_customize->add_control(new WP_Customize_Color_Control($wp_customize, 'mft_background_color', array(
'label' => __('背景颜色', 'my-first-theme'),
'section' => 'mft_color_settings',
'settings' => 'mft_background_color',
'priority' => 30
)));
}
add_action('customize_register', 'mft_theme_customizer_sections');
第三步:创建版式设置区域
添加字体、布局等版式设置选项。
/**
* 版式设置
*/
function mft_typography_customizer($wp_customize) {
// == 区域3:版式设置 ==
$wp_customize->add_section('mft_typography_settings', array(
'title' => __('版式设置', 'my-first-theme'),
'description' => __('自定义网站字体和排版', 'my-first-theme'),
'panel' => 'mft_theme_settings',
'priority' => 30,
));
// 正文字体
$wp_customize->add_setting('mft_body_font', array(
'default' => 'system-ui, -apple-system, sans-serif',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_text_field'
));
$wp_customize->add_control('mft_body_font', array(
'label' => __('正文字体', 'my-first-theme'),
'section' => 'mft_typography_settings',
'type' => 'text',
'priority' => 10
));
// 标题字体
$wp_customize->add_setting('mft_heading_font', array(
'default' => 'system-ui, -apple-system, sans-serif',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_text_field'
));
$wp_customize->add_control('mft_heading_font', array(
'label' => __('标题字体', 'my-first-theme'),
'section' => 'mft_typography_settings',
'type' => 'text',
'priority' => 20
));
// 字体大小 - 选择性刷新
$wp_customize->add_setting('mft_base_font_size', array(
'default' => '16',
'transport' => 'refresh', // 需要刷新页面
'sanitize_callback' => 'absint'
));
$wp_customize->add_control('mft_base_font_size', array(
'label' => __('基础字体大小 (px)', 'my-first-theme'),
'section' => 'mft_typography_settings',
'type' => 'number',
'input_attrs' => array(
'min' => 12,
'max' => 24,
'step' => 1
),
'priority' => 30
));
// 行高
$wp_customize->add_setting('mft_line_height', array(
'default' => '1.6',
'transport' => 'postMessage',
'sanitize_callback' => 'sanitize_text_field'
));
$wp_customize->add_control('mft_line_height', array(
'label' => __('行高', 'my-first-theme'),
'section' => 'mft_typography_settings',
'type' => 'text',
'priority' => 40
));
// == 区域4:布局设置 ==
$wp_customize->add_section('mft_layout_settings', array(
'title' => __('布局设置', 'my-first-theme'),
'description' => __('自定义网站布局', 'my-first-theme'),
'panel' => 'mft_theme_settings',
'priority' => 40,
));
// 布局宽度
$wp_customize->add_setting('mft_layout_width', array(
'default' => '1200',
'transport' => 'postMessage',
'sanitize_callback' => 'absint'
));
$wp_customize->add_control('mft_layout_width', array(
'label' => __('布局最大宽度 (px)', 'my-first-theme'),
'section' => 'mft_layout_settings',
'type' => 'number',
'input_attrs' => array(
'min' => 800,
'max' => 1600,
'step' => 50
),
'priority' => 10
));
// 侧边栏位置
$wp_customize->add_setting('mft_sidebar_position', array(
'default' => 'right',
'transport' => 'refresh',
'sanitize_callback' => 'mft_sanitize_sidebar_position'
));
$wp_customize->add_control('mft_sidebar_position', array(
'label' => __('侧边栏位置', 'my-first-theme'),
'section' => 'mft_layout_settings',
'type' => 'select',
'choices' => array(
'left' => __('左侧', 'my-first-theme'),
'right' => __('右侧', 'my-first-theme'),
'none' => __('无侧边栏', 'my-first-theme')
),
'priority' => 20
));
// 内容区域宽度
$wp_customize->add_setting('mft_content_width', array(
'default' => '70',
'transport' => 'postMessage',
'sanitize_callback' => 'absint'
));
$wp_customize->add_control('mft_content_width', array(
'label' => __('内容区域宽度 (%)', 'my-first-theme'),
'section' => 'mft_layout_settings',
'type' => 'number',
'input_attrs' => array(
'min' => 50,
'max' => 100,
'step' => 5
),
'priority' => 30
));
}
// 侧边栏位置验证函数
function mft_sanitize_sidebar_position($input) {
$valid = array('left', 'right', 'none');
if (in_array($input, $valid)) {
return $input;
}
return 'right';
}
add_action('customize_register', 'mft_typography_customizer');
第四步:创建高级设置区域
添加更高级的功能设置选项。
/**
* 高级功能设置
*/
function mft_advanced_customizer($wp_customize) {
// == 区域5:高级设置 ==
$wp_customize->add_section('mft_advanced_settings', array(
'title' => __('高级设置', 'my-first-theme'),
'description' => __('主题高级功能配置', 'my-first-theme'),
'panel' => 'mft_theme_settings',
'priority' => 50,
));
// 自定义CSS
$wp_customize->add_setting('mft_custom_css', array(
'default' => '',
'transport' => 'postMessage',
'sanitize_callback' => 'wp_strip_all_tags' // 移除HTML标签,保留CSS
));
$wp_customize->add_control('mft_custom_css', array(
'label' => __('自定义CSS', 'my-first-theme'),
'section' => 'mft_advanced_settings',
'type' => 'textarea',
'priority' => 10
));
// 页脚版权信息
$wp_customize->add_setting('mft_footer_copyright', array(
'default' => '© {year} {sitename}. All rights reserved.',
'transport' => 'postMessage',
'sanitize_callback' => 'wp_kses_post' // 允许有限的HTML
));
$wp_customize->add_control('mft_footer_copyright', array(
'label' => __('页脚版权信息', 'my-first-theme'),
'description' => __('可用变量: {year} - 当前年份, {sitename} - 网站名称', 'my-first-theme'),
'section' => 'mft_advanced_settings',
'type' => 'textarea',
'priority' => 20
));
// 回到顶部按钮
$wp_customize->add_setting('mft_back_to_top', array(
'default' => true,
'transport' => 'refresh',
'sanitize_callback' => 'wp_validate_boolean'
));
$wp_customize->add_control('mft_back_to_top', array(
'label' => __('显示"回到顶部"按钮', 'my-first-theme'),
'section' => 'mft_advanced_settings',
'type' => 'checkbox',
'priority' => 30
));
// 懒加载图片
$wp_customize->add_setting('mft_lazy_load', array(
'default' => true,
'transport' => 'refresh',
'sanitize_callback' => 'wp_validate_boolean'
));
$wp_customize->add_control('mft_lazy_load', array(
'label' => __('启用图片懒加载', 'my-first-theme'),
'section' => 'mft_advanced_settings',
'type' => 'checkbox',
'priority' => 40
));
// == 区域6:首页设置 ==
$wp_customize->add_section('mft_homepage_settings', array(
'title' => __('首页设置', 'my-first-theme'),
'description' => __('首页特殊设置', 'my-first-theme'),
'panel' => 'mft_theme_settings',
'priority' => 60,
));
// 首页显示文章数量
$wp_customize->add_setting('mft_home_posts_per_page', array(
'default' => '10',
'transport' => 'refresh',
'sanitize_callback' => 'absint'
));
$wp_customize->add_control('mft_home_posts_per_page', array(
'label' => __('首页显示文章数量', 'my-first-theme'),
'section' => 'mft_homepage_settings',
'type' => 'number',
'input_attrs' => array(
'min' => 1,
'max' => 50,
'step' => 1
),
'priority' => 10
));
// 首页特色内容
$wp_customize->add_setting('mft_show_featured_content', array(
'default' => true,
'transport' => 'refresh',
'sanitize_callback' => 'wp_validate_boolean'
));
$wp_customize->add_control('mft_show_featured_content', array(
'label' => __('显示首页特色内容', 'my-first-theme'),
'section' => 'mft_homepage_settings',
'type' => 'checkbox',
'priority' => 20
));
}
add_action('customize_register', 'mft_advanced_customizer');
第五步:实现实时预览的JavaScript
创建assets/js/customizer-preview.js文件来处理实时预览:
(function($) {
'use strict';
// 实时预览功能
wp.customize('mft_header_bg_color', function(value) {
value.bind(function(newval) {
$('.site-header').css('background-color', newval);
});
});
wp.customize('mft_header_text_color', function(value) {
value.bind(function(newval) {
$('.site-header, .site-header a').css('color', newval);
});
});
wp.customize('mft_primary_color', function(value) {
value.bind(function(newval) {
$('a, .primary-color').css('color', newval);
$('.button, .primary-bg').css('background-color', newval);
});
});
wp.customize('mft_secondary_color', function(value) {
value.bind(function(newval) {
$('h1, h2, h3, .secondary-color').css('color', newval);
});
});
wp.customize('mft_background_color', function(value) {
value.bind(function(newval) {
$('body').css('background-color', newval);
});
});
wp.customize('mft_body_font', function(value) {
value.bind(function(newval) {
$('body').css('font-family', newval);
});
});
wp.customize('mft_heading_font', function(value) {
value.bind(function(newval) {
$('h1, h2, h3, h4, h5, h6').css('font-family', newval);
});
});
wp.customize('mft_line_height', function(value) {
value.bind(function(newval) {
$('body').css('line-height', newval);
});
});
wp.customize('mft_layout_width', function(value) {
value.bind(function(newval) {
$('.content-wrapper').css('max-width', newval + 'px');
});
});
wp.customize('mft_content_width', function(value) {
value.bind(function(newval) {
$('.main-content').css('flex', newval + '%');
$('.sidebar-area').css('flex', (100 - newval) + '%');
});
});
wp.customize('mft_site_description', function(value) {
value.bind(function(newval) {
$('.site-description').text(newval);
});
});
wp.customize('mft_footer_copyright', function(value) {
value.bind(function(newval) {
var currentYear = new Date().getFullYear();
var siteName = wp.customize('blogname').get();
var processedText = newval
.replace(/{year}/g, currentYear)
.replace(/{sitename}/g, siteName);
$('.footer-copyright').html(processedText);
});
});
wp.customize('mft_custom_css', function(value) {
value.bind(function(newval) {
$('#mft-custom-css').remove();
if (newval) {
$('head').append('<style id="mft-custom-css">' + newval + '</style>');
}
});
});
})(jQuery);
在functions.php中注册预览脚本:
/**
* 注册自定义器预览脚本
*/
function mft_customizer_preview_js() {
wp_enqueue_script(
'mft-customizer-preview',
get_template_directory_uri() . '/assets/js/customizer-preview.js',
array('customize-preview', 'jquery'),
'1.0.0',
true
);
}
add_action('customize_preview_init', 'mft_customizer_preview_js');
第六步:在前台应用自定义器设置
创建inc/customizer-styles.php文件来处理自定义器设置的CSS输出:
<?php
/**
* 生成自定义器CSS
*/
function mft_generate_customizer_css() {
$css = '';
// 头部样式
$header_bg_color = get_theme_mod('mft_header_bg_color', '#ffffff');
$header_text_color = get_theme_mod('mft_header_text_color', '#333333');
$header_height = get_theme_mod('mft_header_height', '80');
$css .= "
.site-header {
background-color: {$header_bg_color};
color: {$header_text_color};
min-height: {$header_height}px;
}
.site-header a {
color: {$header_text_color};
}
";
// 颜色样式
$primary_color = get_theme_mod('mft_primary_color', '#3498db');
$secondary_color = get_theme_mod('mft_secondary_color', '#2c3e50');
$background_color = get_theme_mod('mft_background_color', '#f8f9fa');
$css .= "
body {
background-color: {$background_color};
}
a, .primary-color {
color: {$primary_color};
}
.button, .primary-bg {
background-color: {$primary_color};
}
h1, h2, h3, .secondary-color {
color: {$secondary_color};
}
";
// 版式样式
$body_font = get_theme_mod('mft_body_font', 'system-ui, -apple-system, sans-serif');
$heading_font = get_theme_mod('mft_heading_font', 'system-ui, -apple-system, sans-serif');
$base_font_size = get_theme_mod('mft_base_font_size', '16');
$line_height = get_theme_mod('mft_line_height', '1.6');
$css .= "
body {
font-family: {$body_font};
font-size: {$base_font_size}px;
line-height: {$line_height};
}
h1, h2, h3, h4, h5, h6 {
font-family: {$heading_font};
}
";
// 布局样式
$layout_width = get_theme_mod('mft_layout_width', '1200');
$content_width = get_theme_mod('mft_content_width', '70');
$sidebar_width = 100 - $content_width;
$css .= "
.content-wrapper {
max-width: {$layout_width}px;
}
.main-content {
flex: {$content_width}%;
}
.sidebar-area {
flex: {$sidebar_width}%;
}
";
// 侧边栏位置
$sidebar_position = get_theme_mod('mft_sidebar_position', 'right');
if ($sidebar_position === 'left') {
$css .= "
.content-wrapper {
flex-direction: row-reverse;
}
";
} elseif ($sidebar_position === 'none') {
$css .= "
.sidebar-area {
display: none;
}
.main-content {
flex: 100%;
}
";
}
return $css;
}
/**
* 输出自定义器CSS
*/
function mft_output_customizer_css() {
$css = mft_generate_customizer_css();
if (!empty($css)) {
echo '<style id="mft-theme-custom-css">' . $css . '</style>';
}
// 输出自定义CSS
$custom_css = get_theme_mod('mft_custom_css', '');
if (!empty($custom_css)) {
echo '<style id="mft-additional-custom-css">' . $custom_css . '</style>';
}
}
add_action('wp_head', 'mft_output_customizer_css');
第七步:更新模板文件应用设置
更新header.php应用Logo设置:
<header class="site-header">
<div class="header-inner">
<!-- Logo显示 -->
<div class="site-branding">
<?php
$logo = get_theme_mod('mft_site_logo');
$mobile_logo = get_theme_mod('mft_mobile_logo', $logo);
if ($logo) : ?>
<a href="<?php echo esc_url(home_url('/')); ?>" class="site-logo">
<img src="<?php echo esc_url($logo); ?>" alt="<?php bloginfo('name'); ?>" class="desktop-logo" />
<?php if ($mobile_logo && $mobile_logo !== $logo) : ?>
<img src="<?php echo esc_url($mobile_logo); ?>" alt="<?php bloginfo('name'); ?>" class="mobile-logo" />
<?php endif; ?>
</a>
<?php else : ?>
<h1 class="site-title">
<a href="<?php echo esc_url(home_url('/')); ?>"><?php bloginfo('name'); ?></a>
</h1>
<?php endif; ?>
<?php
$description = get_theme_mod('mft_site_description', get_bloginfo('description'));
if ($description) : ?>
<p class="site-description"><?php echo esc_html($description); ?></p>
<?php endif; ?>
</div>
<!-- 导航菜单 -->
<nav class="main-navigation">
<?php
wp_nav_menu(array(
'theme_location' => 'primary',
'menu_class' => 'primary-menu',
'container' => false,
));
?>
</nav>
</div>
</header>
更新footer.php应用版权信息:
<footer class="site-footer">
<?php if (is_active_sidebar('footer-1')) : ?>
<div class="footer-widgets">
<?php dynamic_sidebar('footer-1'); ?>
</div>
<?php endif; ?>
<div class="site-info">
<?php
$copyright = get_theme_mod('mft_footer_copyright', '© {year} {sitename}. All rights reserved.');
$current_year = date('Y');
$site_name = get_bloginfo('name');
$processed_copyright = str_replace(
array('{year}', '{sitename}'),
array($current_year, $site_name),
$copyright
);
?>
<div class="footer-copyright">
<?php echo wp_kses_post($processed_copyright); ?>
</div>
<?php if (get_theme_mod('mft_back_to_top', true)) : ?>
<button id="back-to-top" class="back-to-top-button" aria-label="回到顶部">
↑
</button>
<?php endif; ?>
</div>
</footer>
第八步:添加回到顶部功能
在functions.php中添加回到顶部功能:
/**
* 回到顶部功能
*/
function mft_back_to_top_script() {
if (get_theme_mod('mft_back_to_top', true)) {
?>
<script>
jQuery(document).ready(function($) {
$('#back-to-top').on('click', function() {
$('html, body').animate({scrollTop: 0}, 500);
});
$(window).on('scroll', function() {
if ($(this).scrollTop() > 300) {
$('#back-to-top').addClass('visible');
} else {
$('#back-to-top').removeClass('visible');
}
});
});
</script>
<?php
}
}
add_action('wp_footer', 'mft_back_to_top_script');
总结:自定义器开发的完整流程
通过今天的学习,你已经掌握了创建专业级主题自定义器的完整技能:
- 基础设置注册:使用
customize_register钩子添加设置 - 组织架构设计:使用面板和区域合理组织设置选项
- 多种控件类型:文本、颜色、图片、选择框、复选框等
- 实时预览实现:使用
postMessage传输和JavaScript预览 - 数据验证安全:使用适当的清理回调函数
- 前台应用设置:通过
get_theme_mod()获取设置值
现在你的主题已经具备了专业主题的所有设置功能!在下一篇文章中,我们将学习WordPress主题国际化(i18n),让主题支持多语言。

评论框