Customizer, Present and Future (Talk at WordCamp Helsinki

The original slides for this talk can be found here: https://danielkoskinen.com/wchel2017-slides/

Editing WordPress themes used to look like this:

An old-school theme settings panel from the Divi theme.

The screenshot above is from the Divi theme but there are loads of similar examples like this.

You have to make a change to a setting, go to the front end, find the place where the change was applied and hope it didn’t break anything in the meanwhile.

This is a Bad User Experience.

Customizer to the rescue

The Customizer in WordPress provides a much better experience for making changes to your site and previewing them before going live.

Let’s take widgets as an example. Editing widgets in the admin can be messy. Before WordPress 4.7, finding the correct widget in the Customizer wasn’t an obvious task either, especially if you had multiple widget areas (hello Genesis child themes…). However with one simple addition…

    // Add theme support for selective refresh for widgets.
    add_theme_support( 'customize-selective-refresh-widgets' );

A quick fix is to add support for visual edit shortcuts to your theme and hey presto, widgets are cool again.

Much better.

OK we know about widgets, show me more stuff

Let’s say we want to have a related posts section in our theme below every post.

The code could be something like this:

function customizer_test_display_related_posts() {
    // Get the categories for this post
    $post_categories_objects = get_the_category();
    $post_categories_ids = wp_list_pluck( $post_categories_objects, 'term_id' );

    // Get three posts with the same category
    $related_posts = new WP_Query( array(
        'posts_per_page' => 3,
        'category__in' => $post_categories_ids,
        'ignore_sticky_posts' => true,
    ) );

    // Loop over posts and display them
    if ( $related_posts->have_posts() ) {
    ?>
    <div class="related-posts-container">
        <h2><?php esc_html_e( 'Related posts', 'customizer-test' ); ?></h2>
        <ul class="related-posts-list">
    <?php
        while ( $related_posts->have_posts() ) {
            $related_posts->the_post();
    ?>
        <li>
            <a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
        </li>
    <?php
        }
    ?>
        </ul>
    </div>
    <?php
    }
    wp_reset_postdata();
}

Let’s make the number of posts editable.

The Customizer is built around objects, we have Panels, Sections, Controls, Settings and Partials:

Diagram of Customizer Object relationships
Image from the Theme Handbook at https://developer.wordpress.org/themes/customize-api/

These objects are manipulated via the customize_register hook, like this:

function customizer_test_customize_register( $wp_customize ) {

    // The magic happens here...

}
add_action( 'customize_register', 'customizer_test_customize_register' );

First, we need a section to hold our controls

// Create a custom section
$wp_customize->add_section( 'related_posts_section', array(
    'title' => __( 'Related posts' ),
    'priority' => 160,
) );

Then, we create a setting to store the number of posts.

// Add a setting
$wp_customize->add_setting( 'related_posts_number', array(
    'sanitize_callback' => 'absint',        
    'default' => 3,
) );    

Finally, a control to modify our setting.

$wp_customize->add_control( 'related_posts_number', array(
    'type' => 'number',
    'section' => 'related_posts_section',
    'label' => __( 'Number of posts to show' ),
) );                        

So we need a section (usually), a setting and a control.

Getting the data

Getting the data is straightforward. The second argument for get_theme_mod is the default value.

$number_of_posts = get_theme_mod( 'related_posts_number', 3 );

Let’s put that back in our original code

$number_of_posts = get_theme_mod( 'related_posts_number', 3 );

// Get three posts with the same category
$related_posts = new WP_Query( array(
    'posts_per_page' => absint( $number_of_posts ),
    'category__in' => $post_categories,
) );

// rest of the code...

So now we have a working setting.

Issues

  1. Full page load every time we change a setting
  2. No visible editor shortcuts
  3. Setting is visible on all pages

SOLUTION: Let’s register a partial!

This solves issues 1. and 2.

$wp_customize->selective_refresh->add_partial( 
    'related_posts_number', 
    array(
        'selector' => '.related-posts-container',
        'container_inclusive' => true,
        'render_callback' => function() {
            customizer_test_display_related_posts();
        },
    ) 
);

This already gives you a visible edit shortcut icon, but to enable selective refresh we need to go back to our setting and add a transport setting:


// Add a setting
$wp_customize->add_setting( 'related_posts_number', array(
    'sanitize_callback' => 'absint',        
    'default' => 3,
    'transport' => 'postMessage', // 'refresh' by default
) );    

Full Customizer code

function customizer_test_customize_register( $wp_customize ) {

    // Create a custom section
    $wp_customize->add_section( 'related_posts_section', array(
        'title' => __( 'Related posts' ),
        'priority' => 160,
    ) );

    // Add a setting
    $wp_customize->add_setting( 'related_posts_number', array(
        'sanitize_callback' => 'absint',        
        'default' => 3,
        'transport' => 'postMessage',
    ) );    

    $wp_customize->add_control( 'related_posts_number', array(
        'type' => 'number',
        'section' => 'related_posts_section',
        'label' => __( 'Number of posts to show' ),
    ) );

    $wp_customize->selective_refresh->add_partial( 
        'related_posts_number', 
        array(
            'selector' => '.related-posts-container',
            'container_inclusive' => true,
            'render_callback' => function() {
                customizer_test_display_related_posts();
            },
        ) 
    );

}
add_action( 'customize_register', 'customizer_test_customize_register' );

What’s next?

This post just scratches the surface. You can use one of the many custom controls available in WordPress core or build your own with PHP and/or JavaScript. To learn more, I highly recommend reading the Customize API section of the Theme Handbook.

Kirki is a nice toolkit for speeding up developing components for the Customizer but sadly hasn’t been updated in 6 months.

Visible edit shortcuts are also the first step toward exploring the potential to edit elements of a site directly within the customizer preview.

Nick Halsey on make.wordpress.org/core, 11th Nov 2016

A lot of work is going in to the Editor and the Customizer in future WordPress development, and who knows we might soon be editing posts directly in the Customizer too. You can try it today with the Customize Posts plugin by XWP.

Update: example code for workshop

I was going to do a short beginners’ workshop at WordCamp Helsinki 2017 Contributor Day on the same subject, but unfortunately had to cancel. I’ve put some of the examples I was going to cover (including the above code) in a gist on Github.