Is it possible to create multiple "custom background" administration pages? A site I'm doing now needs 2 different background in 2 different areas, I would really love giving my client the same experience for both backgrounds in terms of colour/image/select-repeat etc. Any Ideas?


Hi @Amit:

The answer is "Yes, it is possible." The follow up question is "Do you really want to?"

I thought it would be fun to see if I could build a plugin to do what you are asking for so I decided to see if it was possible. Of course I was able to make it work but I fear that the plugin code I wrote needs to be so tightly coupled with the existing code in WordPress that it might easily break on a core update.

This code handles all the admin console side of things by creating a new menu item in the Appearance section called "Special Background." What it does not do is provide any way to actually use the background; that's phase two of the plugin and will require hooking many of the functions in /wp-includes/themes.php and frankly I don't know if I'll get a chance to write that code.

The reason I stopped without doing it is I didn't know the requirements for where the special background should show and where the regular one would show. I assume maybe for selected pages and/or URL paths?

Nonetheless, here if the code for the plugin (which you can also download from gist):

Plugin Name: Special Background
Plugin URI: http://wordpress.stackexchange.com/questions/972/
Description: Example to show how to add a special background using exiting background admin page in core.
Version: 0.1
Author: Mike Schinkel
Author URI: http://mikeschinkel.com/custom-wordpress-plugins/
function add_special_background_menu_item() {
    add_theme_page(__('Special Background'), __('Special Background'),'edit_theme_options','special-background','special_background_admin_page');
function add_js_for_special_background() {
    global $custom_background;
    if (is_special_background_page()) {
    $hook = 'load-appearance_page_special-background';
    add_action($hook, array(&$custom_background, 'admin_load'));
    add_action($hook, array(&$custom_background, 'take_action'), 49);
    add_action($hook, array(&$custom_background, 'handle_upload'), 49);    
add_filter('theme_mod_background_image',      'theme_mod_special_background_image');
add_filter('theme_mod_background_repeat',     'theme_mod_special_background_repeat');
add_filter('theme_mod_background_position_x', 'theme_mod_special_background_position_x');
add_filter('theme_mod_background_attachment', 'theme_mod_special_background_attachment');
add_filter('theme_mod_background_color',      'theme_mod_special_background_color');
function theme_mod_special_background_image($defaults) {
    return theme_mod_special_background_image_attrs('image',$defaults);
function theme_mod_special_background_image_thumb($defaults) {
    return theme_mod_special_background_image_attrs('image_thumb',$defaults);
function theme_mod_special_background_repeat($defaults) {
    return theme_mod_special_background_image_attrs('repeat',$defaults);
function theme_mod_special_background_position_x($defaults) {
    return theme_mod_special_background_image_attrs('position_x',$defaults);
function theme_mod_special_background_attachment($defaults) {
    return theme_mod_special_background_image_attrs('attachment',$defaults);
function theme_mod_special_background_color($defaults) {
    return theme_mod_special_background_image_attrs('color',$defaults);
function theme_mod_special_background_image_attrs($attr,$defaults) {
    if (is_special_background_page()) {
        $mods = get_option( 'mods_' . get_current_theme() );
        $defaults = (!empty($mods["special_background_{$attr}"]) ? $mods["special_background_{$attr}"] : '');
    return $defaults;
add_filter('pre_update_option_mods_' . get_current_theme(),'pre_update_option_special_background_image',10,2);
function pre_update_option_special_background_image($newvalue, $oldvalue) {
    static $times_called = 0;
    if (!empty($_POST) && is_special_background_page()) {
        if ((isset($_POST['action']) && $_POST['action']=='save') || isset($_POST['reset-background']) || isset($_POST['remove-background'])) {
            switch ($times_called) {
                case 0:
                    $newvalue = special_background_image_value_swap('image',$newvalue,$oldvalue);
                case 1:
                    $newvalue = special_background_image_value_swap('image_thumb',$newvalue,$oldvalue);
        } else {
            if ($times_called==0 && isset($_POST['background-repeat'])) {
                $newvalue = special_background_image_value_swap('repeat',$newvalue,$oldvalue);
            if ($times_called==1 && isset($_POST['background-position-x'])) {
                $newvalue = special_background_image_value_swap('position_x',$newvalue,$oldvalue);
            if ($times_called==2 && isset($_POST['background-attachment'])) {
                $newvalue = special_background_image_value_swap('attachment',$newvalue,$oldvalue);
            if ($times_called==3 && isset($_POST['background-color'])) {
            $newvalue = special_background_image_value_swap('color',$newvalue,$oldvalue);
  return $newvalue;
function special_background_image_value_swap($swap_what,$newvalue,$oldvalue) {
  $newvalue["special_background_{$swap_what}"] = $newvalue["background_{$swap_what}"];
  $newvalue["background_{$swap_what}"] = $oldvalue["background_{$swap_what}"];
  return $newvalue;
function special_background_admin_page() {
  global $custom_background;
  if (is_special_background_page()) {
    global $parent_file,$submenu_file,$title;
    $parent_file = 'themes.php';
    $submenu_file = 'themes.php?page=special-background';
    $title = 'Special Background';
    require_once(ABSPATH . 'wp-admin/admin-header.php');
    $html = ob_get_clean();
    $html = preg_replace('#<h2>([^<]+)</h2>#','<h2>Special Background</h2>',$html);
    echo $html;
    include(ABSPATH . 'wp-admin/admin-footer.php');
function is_special_background_page() {
  global $pagenow;
  return ($pagenow=='themes.php' &&
         isset($_GET['page']) && $_GET['page']== 'special-background');

Frankly it is too much code to explain proactively but I'll be happy to answer specific questions.

  • Tip: list($var1, $var2) = array($var2, $var1); // swaps the values of $var1 and $var2
    – hakre
    Aug 28 '10 at 9:18
  • 1
    That's a plugin I would definitely wrap up in a class.
    – hakre
    Aug 28 '10 at 9:20
  • @MikeSchinkel: Can you add a little description on your swap/save concept? Are normally those theme_mod_background_image theme modification values used by wp core to offer the standard header? What do you do if there is no header in theme? I'm thinking about creating some hook/option facade object in my fork... updated: codex.wordpress.org/Theme_Modification_API .
    – hakre
    Aug 28 '10 at 12:06
  • 1
    I forked you. gist.github.com/554944
    – hakre
    Aug 28 '10 at 16:11
  • @hakre; thanks for the tip on the swap. I am familiar with it though. You must understand that when I first wrote the function it was much more complicated and I refactored it down to what it is so I wasn't originally thinking it would be as simplistic. I also don't tend to wrap things up in a class for here on StackExchange because it make it harder for people to understand when all the class plumbing is in place (yet, it is not optimal; if I use a class more people will be scared off it; if I don't use a class I'm teaching them less good practice.) Aug 28 '10 at 17:27

Technically it's possible (so to extend the wordpress source), but not by default. So I would give the answer to no. The build-in background theme feature is for a single graphics only be default.

But if you describe a little bit more about the "2 different areas" you're writing about, there might be something nice to suggest next to this.

Edit: Highlight for MikeSchinkel. Plugins are extending the wordpress source.

  • Well.. There's the main site (20 sections or so) and then there's like a sub-site under one those sections which changes for this special event and need its own style colours and background image. Theoretically I could tell the client to upload an image to the "master page" of each section and call it "some-how" but I like the custom background functionality and semantic position in the CMS.
    – Amit
    Aug 27 '10 at 21:17
  • are you using a template per section? that might be something to hook in. Or to override with a subtheme for a certain area (that would scale to two background images then in total because you would have two themes, parent and child theme).
    – hakre
    Aug 27 '10 at 21:32
  • Ye of little faith! You should know not to say something is not possible with WordPress! ;-) Aug 28 '10 at 8:10
  • I didn't. I mean it's a pile of PHP you only need to re-arrange a little to get things done :)
    – hakre
    Aug 28 '10 at 9:14
  • True. But you shouldn't discourage people; where there is a will there is a way! Aug 30 '10 at 0:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.