Add a custom logo uploader to the WordPress theme customizer

The WordPress theme customizer is famous for being able to change your theme colors in real time, but did you know it can handle almost any type of theme option?

You can add layout options, image uploaders, text fields, and lots more. The possibilities are endless!

There is almost no need for theme options pages anymore. I personally like the idea of having no theme options page, and limiting everything to the theme customizer.

I’m going to show you how to add a custom logo uploader to your theme customizer, then display it in place of the site title and tagline.

Create the logo uploader setting

This may be review for some of you, but I’ll go over my basic setup for using the theme customizer. In my custom theme folder most of the code is going into /inc/customizer.php, and then we will include that file via functions.php. You could put all the code into functions.php and it will work, but it’s nice to keep functions.php uncluttered.

First, we create our function to register the new settings. I’ve prefixed my function name with m1, but you can use whatever you want:

function m1_customize_register( $wp_customize ) {
// All the code in this tutorial goes here
add_action( ‘customize_register’, ‘m1_customize_register’ );

Inside our function we need to register a setting. This saves the logo url in the database so we can use it in our theme.

function m1_customize_register( $wp_customize ) {
$wp_customize->add_setting( ‘m1_logo’ ); // Add setting for logo uploader
add_action( ‘customize_register’, ‘m1_customize_register’ );

Next, we add the uploader and assign it to a section. You could create a new section, but I think it goes nicely with the title and tagline. If you are using a different name for your setting, make sure you change all instances of m1_logo to something else.

function m1_customize_register( $wp_customize ) {
$wp_customize->add_setting( ‘m1_logo’ ); // Add setting for logo uploader

// Add control for logo uploader (actual uploader)
$wp_customize->add_control( new WP_Customize_Image_Control( $wp_customize, ‘m1_logo’, array(
‘label’ => __( ‘Upload Logo (replaces text)’, ‘m1’ ),
‘section’ => ‘title_tagline’,
‘settings’ => ‘m1_logo’,
) ) );
add_action( ‘customize_register’, ‘m1_customize_register’ );

That’s it for the code in customizer.php. To make sure our theme uses this file, simply add this one line of code in functions.php:

require get_template_directory() . ‘/inc/customizer.php’;

That’s it! We kept our functions.php file clean as a whistle.

Next we need to display our logo.

Displaying the logo

We are going to work in our theme’s header.php file to display the logo. If there is no logo, we’ll just display the site title and description.

To get the logo url from our theme customizer, you use this code:

get_theme_mod( ‘m1_logo’ )

You can store that in a variable if you want, or echo it out as is. Since we are only using this value once in our theme, we don’t need to store it in a variable.

Wherever your site title is displayed in header.php, you’ll want to replace it with this code:

” alt=”“>

So let’s talk through that chunk of code. First, we create an if statement that says, “if a theme logo has been uploaded, display this logo code. Otherwise, display the site title and site description.”

The logo is linked to the homepage, it has some alt text, blah blah blah. The important part is this:


That calls the file url for the uploaded logo, and sets it as the image source.

Make sure to tell the user a recommended logo size, otherwise they can upload a huge file that doesn’t fit quite right. You might also want to give the container around the logo a constrained width, so it will fit no matter what.

That about does it, have fun!

How to remove the customizer CSS option

Now that WordPress 4.7 has been released, most people will notice an “Additional CSS” section in the customizer when they update. This is an awesome feature and a perfect use of the customizer. It’ll be great for the vast numbers of users who just need to add some basic CSS to customize their theme.

However, for many of us, it’s an unwanted feature on our own sites for one reason or another. This tutorial is going to walk you through disabling this feature based on your situation.

Remove directly from customizer

If you just want to get rid of the custom CSS option altogether, the easiest route is to simply remove the control from the customizer. Dropping the following code in your theme’s functions.php or a plugin will handle that fine.

add_action( 'customize_register', 'jt_customize_register' );

function jt_customize_register( $wp_customize ) {

	$wp_customize->remove_control( 'custom_css' );

You can also remove the entire section (which won’t show if there are no controls) using the following line of code. However, that may have the unwanted consequences of hiding controls that other plugins/themes have added.

$wp_customize->remove_section( 'custom_css' );

Removing permission

For clients who shouldn’t be editing code, you may already have this set up using a role/cap plugin.

WordPress introduced a new meta capability called edit_css. It is checked before showing the control. This new meta cap is mapped to the unfiltered_html capability. What this means is that users without the unfiltered_html cap won’t see the control in the customizer anyway.

If you have a client who shouldn’t be editing advanced code, it’s best to take that option away by removing the unfiltered_html capability. This will also likely help in any similar scenarios in the future.

To do this, you can grab a copy of my Members plugin and uncheck the unfiltered_html checkbox for the user’s role (see screenshot above).

Customizing permission

There are some scenarios where you might want to allow the user to have the unfiltered_html cap but not be able to edit CSS. This is best handled with a filter on the map_meta_cap filter hook. What you can do is “map” the edit_css meta cap to another capability or set of capabilities.

The following code will disable the capability for everyone by mapping it to the do_not_allow capability. Place the following in a custom plugin file.

add_filter( 'map_meta_cap', 'jt_map_meta_cap', 10, 3 );

function jt_map_meta_cap( $caps, $cap, $user_id ) {

	if ( 'edit_css' === $cap ) {
		$caps = array( 'do_not_allow' );

	return $caps;

You can take that further by utilizing the $user_id variable. Or, you can change do_not_allow to a custom capability you’ve set up (the Members plugin allows you to do this). You can even add multiple capabilities as a requirement for editing CSS. Really, the sky is the limit.