Color Picker in Theme Options Tutorial

Theme Options pages get quite sophisticated these days, providing the end user with a highly customizable WordPress experience. Our topic today is color and color pickers, which can be used to provide the theme user with an option to choose colors for different things like the footer area, the general text color, the navigation menu background color, headings color and so on. Of course all of this can easily be done by simply providing a Custom CSS field, but let’s admit that not everybody’s fluent in CSS.

Today we’ll talk about Farbtastic, a jQuery color picker script that is shipped together with WordPress. We’ll create a Theme Options page with a single text field and I’ll show you how to pop out the color wheel when the user clicks that field, as well as save and use the saved color in your theme afterwards.

Getting Started

First of all you should get familiar with the WordPress Settings API. Although you can copy/paste your way through this tutorial, I do recommend you read this great post by Chip Bennett called Incorporating the Settings API in WordPress Themes.

You should also be familiar with what actions in WordPress are and functions like get_option, wp_enqueue_script and of course add_theme_page. We’ll use those and other functions to:

  • Create a Theme Options Page
  • Register a setting, a section and a field (a color field) using the Settings API
  • Enqueue a few scripts and styles on our Theme Options page
  • Create a text input to hold our color value
  • Attach Farbtastic to the color field

Ready? Let’s roll.

Creating a Theme Options Page

First things first, a Theme Options page. We’ll use the add_theme_page function and fire it during the admin_menu WordPress action as suggested by the administration menus entry in the Codex. I’ll be using my_ as the prefix for all the functions but you’re free to use your own, and/or wrap it up in an object-oriented fashion if you’d like to. Here’s the first few lines of our functions.php file:

function my_admin_menu() {
    $page = add_theme_page( 'Theme Options', 'Theme Options', 'edit_theme_options', 'my-theme-options', 'my_theme_options' );
    add_action( 'admin_print_styles-' . $page, 'my_admin_scripts' );
}
add_action( 'admin_menu', 'my_admin_menu' );

This creates a new entry under the Appearance menu called Theme Options which is rendered by the my_theme_options functions that we have provided. Note that we’re saving the output of the add_theme_page function into a variable called $page. We then add a function called my_admin_scripts to the admin_print_styles- hook prefixed with our $page.

This may look weird at first, but it really is quite simple. The admin_print_styles-x action is called whenever it is time to print the stylesheets on the x page. We’ll use this action to enqueue our javascript files later, but basically we’re telling it to call our function only when it is time to print stylesheets on that $page we have just added to the menu.

Read more about it in this codex entry: Load scripts only on plugin pages which is of course adapted to our theme and simplified a little bit.

Let’s go ahead and create the my_admin_scripts function and leave it empty for now, we’ll get to that in a while.

function my_admin_scripts() {
    // We'll put some javascript & css here later
}

Let’s move on to the actual theme options page contents which is rendered by the function called my_theme_options. We’ll move on to the more difficult bit (the settings registration) after that.

Theme Options Page Contents

Hopefully you’ve seen such pages in the past and this is no different. You’ll be very familiar with the contents of the page if you’ve worked with the Settings API before. Here’s our my_theme_options function which has been provided as a callback to the add_theme_page call earlier.

function my_theme_options() {
    ?>
    <div class="wrap">
        <div id="icon-themes" class="icon32" ><br></div>
        <h2>My Theme Options</h2>

        <form method="post" action="options.php">
            <?php wp_nonce_field( 'update-options' ); ?>
            <?php settings_fields( 'my-theme-options' ); ?>
            <?php do_settings_sections( 'my-theme-options' ); ?>
            <p class="submit">
                <input name="Submit" type="submit" class="button-primary" value="Save Changes" />
            </p >
        </form>
    </div>
    <?php
}

The simple markup makes the page look like a WordPress native page, with an Appearance icon and the appropriate heading. The form contains calls to wp_nonce_field, settings_fields and do_settings_sections as suggested by the Settings API. Finally we render a submit button called Save Changes. We could have used a sweet submit_button function here, but that would limit compatibility to 3.1 :)

If you browse to your Theme Options page at this point, you’ll see a blank page titled My Theme Options and a Save Changes button which doesn’t really work yet. The rest is up to the Settings API to define what sections and fields will be rendered on our page. Note that I used the my-theme-options key for the function calls in the snippet above, we’ll have to use the same key when registering our options.

Theme Options Page

Settings, Sections and Fields

This part should probably go before the theme options page contents, but since it’s a little bit more difficult to understand we left it down here. We’ll basically hook to the admin_init action and register one setting, one section and one field that will go into our theme options form that we have created earlier.

Here’s the code for the my_admin_init function:

function my_admin_init() {
    register_setting( 'my-theme-options', 'my-theme-options' );
    add_settings_section( 'section_general', 'General Settings', 'my_section_general', 'my-theme-options' );
    add_settings_field( 'color', 'Color', 'my_setting_color', 'my-theme-options', 'section_general' );
}
add_action( 'admin_init', 'my_admin_init' );

As simple as that. One setting, one section and one field using register_setting, add_settings_section and add_settings_field respectively. You might also have noticed that I’ve got two more functions which I used as callbacks for the section and the field.

The section callback simply renders some info text about the General Settings section, here’s what my says:

function my_section_general() {
    _e( 'The general section description goes here.' );
}

While the field is a little bit more complicated.

The Color Field

Let’s start with a simple text input that would contain our color value and be able to save it. Note that I’m not doing any options validation for brevity but you probably should. Here’s how the simple version of my_setting_color will look like:

function my_setting_color() {
    $options = get_option( 'my-theme-options' );
    ?>
    <input type="text" name="my-theme-options[color]" value="<?php echo esc_attr( $options['color'] ); ?>" />
    <?php
}

At this stage you’ll notice that your new text input appears in your theme options page and actually works. Go ahead and type in anything in the input field and hit Save Changes, you’ll see that your new value is being saved.

Theme Options Page Color WordPress

Now you can start using that color value in your template files already, with a simple call to get_option and the output of the color key inside the returned array. Right, but our tutorial is about the slick color wheel, remember? Let’s move on to Farbtastic.

Attaching Farbtastic

As mentioned earlier, Farbtastic is a jQuery plugin that is shipped together with WordPress. We’ll use it to render a color wheel when the user clicks our color field input. We’ll stick to the basic Farbtastic usage, but if you explore the docs you’ll see that there’s quite some cool stuff you can do with that.

In order to use Farbtastic we’ll also need a javascript file of our own. Let’s call it theme-options.js and put it in a directory called js inside our theme folder. We’ll get to the contents of that file very soon, but now let’s get WordPress to load it (and Farbtastic too).

Remember the function called my_admin_scripts where we said we’ll squeeze in a few javascript and stylesheets inside? Well now is the time, here’s the new contents for the function:

function my_admin_scripts() {
    wp_enqueue_style( 'farbtastic' );
    wp_enqueue_script( 'farbtastic' );
    wp_enqueue_script( 'my-theme-options', get_template_directory_uri() . '/js/theme-options.js', array( 'farbtastic', 'jquery' ) );
}

Quite easy to follow along, right? Include the Farbtastic stylesheet and javascript and then load our own (still empty) javascript file. I have also provided farbtastic and jquery as dependancies for our script to make sure that it gets loaded after those two have.

Let’s now revisit our my_setting_color function and change the markup a little bit to make it suitable with Farbtastic. What we need is an extra div that will hold our color picker as well as id attributes on both elements. I have also wrapped the whole thing up into a div and gave the elements some basic styling. This should probably be done with an external CSS file but if it’s that minor we’re okay :)

Here’s the contents of the new my_setting_color function:

function my_setting_color() {
    $options = get_option( 'my-theme-options' );
    ?>
    <div class="color-picker" style="position: relative;">
        <input type="text" name="my-theme-options[color]" id="color" />
        <div style="position: absolute;" id="colorpicker"></div>
    </div>
    <?php
}

The position relative/absolute hack is to make sure that the color wheel pops up on top of any elements existing on the page. This will prevent our Save Changes button from jumping up and down whenever the color picker is shown or hidden.

If you save changes at this point you won’t notice any difference. Right, because we have only prepared to use Farbtastic, but haven’t actually used it yet. That’s up to our javascript file.

Behold! The Color Picker!

Okay, you can simply copy/paste the code into your javascript file, see how that works and then return back here to read what it actually does ;)

jQuery(document).ready(function($) {
    $('#colorpicker').hide();
    $('#colorpicker').farbtastic('#color');

    $('#color').click(function() {
        $('#colorpicker').fadeIn();
    });

    $(document).mousedown(function() {
        $('#colorpicker').each(function() {
            var display = $(this).css('display');
            if ( display == 'block' )
                $(this).fadeOut();
        });
    });
});

So, first thing we’ll do is hide the color picker element and then initialize Farbtastic on that. Then we register a click event handler for our color field and make the color picker fade in. The last part of the code makes sure that the color picker is hidden whenever we click anywhere else on the page.

Color Picker Farbtastic WordPress

And that’s about it!

Conclusion

You’ve now got your very own color field inside your Theme Options page. With a little help from the Farbtastic docs you’ll be able to use it with multiple fields, style the color picker however you like and with some javascript magic you can add a Restore button that would restore the color to a default one. Just like the Background color feature provided by WordPress.

As mentioned earlier you can use the color value anywhere in your template files (or better yet in your wp_head section) with a call to get_option, like this:

function my_wp_head() {
    $options = get_option( 'my-theme-options' );
    $color = $options['color'];
    echo "<style> h1 { color: $color; } </style>";
}
add_action( 'wp_head', 'my_wp_head' );

Which would colorize your first level headings. Of course the whole code is far from perfect, you should validate all incoming options, escape all options output, etc. Imagine if $color has been set to red; display: none; and the code snippet above. That would actually hide all your heading tags. You can’t make it absolutely hack-proof I know, but you should at least try to.

That’s all for today, hope you learned something new and enjoyed our tutorial. Ask questions, provide feedback and tell us if this helped you fine tune your WordPress theme. Use the comments section below to leave your thoughts and thank you for subscribing to our RSS feed.