Customise the standard WordPress login page for the admin area of your website. Change the logo & background image without a plugin. To do this, we’re going to use a custom child theme, and we’re going to keep our functions.php file clean by creating a little reusable module.
Set up the Theme Files
The first thing we need to do is set up some files where we can put our custom PHP and CSS files. In your custom child theme folder, create a PHP file for the code and a CSS file for the styles. Place these 2 files in a new sub-folder, so you end up with this in your custom child theme.
File System Object | Description |
---|---|
functions.php | Your custom child theme’s main functions. This should already exist. |
style.css | Your custom child theme’s main CSS classes. This should already exist. |
login-page/functions.php | A new file to hold some custom code we’re going to use here. |
login-page/style.css | Custom login page CSS classes. |
login-page/my-website-logo.png | Optional. A landscape-orientated logo for our website. Size: 320px x 125px |
login-page/background.jpg | Optional. A full-page background image. |
This effectively creates a little custom module, with all the assets in the “login-page” folder within our custom child theme. All we need to do now is reference it from our main functions.php file.
Add the following to somewhere near the top of your custom child theme’s functions.php file.
/** * Settings for custom login page. */ define('IS_CUSTOM_LOGIN_ENABLED', true); // << Set this to false for default login. // Example settings. define('CUSTOM_LOGIN_BUTTON_BG', '#00739c'); // << Your theme's button BG colour. define('CUSTOM_LOGIN_BUTTON_FG', 'white'); // << Your theme's button text colour. define('CUSTOM_LOGIN_PAGE_BG_FILE_NAME', 'background.jpg'); define('CUSTOM_LOGIN_LOGO_FILE_NAME', 'my-website-logo.png'); define('CUSTOM_LOGIN_ADDITIONAL_CSS', 'style.css'); // Customise our login page. // Comment-out this line to go back to the boring WordPress login page. require_once 'login-page/functions.php';
Let’s Write some Code
Here’s the code that does the actual work of customising the WordPress login page. Create the login-page/functions.php file, then copy-and-paste this into your new file.
/** * FILE: login-page/functions.php * * Customise the WordPress login page. * * Optional Constants: * CUSTOM_LOGIN_PAGE_BG_FILE_NAME (string) def="login-background.jpg" * CUSTOM_LOGIN_LOGO_FILE_NAME (string) def="login-logo.png" * CUSTOM_LOGIN_ADDITIONAL_CSS (string) def="style.css" * CUSTOM_LOGIN_BUTTON_BG (string) def="#00739c" * CUSTOM_LOGIN_BUTTON_FG (string) def="white" */ // Block direct access. if (!defined('WPINC')) { exit('Do NOT access this file directly.'); } if (defined('IS_CUSTOM_LOGIN_ENABLED') && (IS_CUSTOM_LOGIN_ENABLED === true)) { function hw_login_page_scripts() { // Sensible defaults. $background_file_name = 'login-background.jpg'; $logo_image_file_name = 'login-logo.png'; $additional_url_file_name = 'style.css'; $login_button_background_colour = '#00739c'; $login_button_text_colour = 'white'; $logo_image_width = '320px'; $logo_image_height = '125px'; $base_dir = basename(dirname(__FILE__)); // 'login-page' $base_full_path = dirname(__FILE__); // Initialise what we're going to customise on the login page... $background_full_path = null; if (defined('CUSTOM_LOGIN_PAGE_BG_FILE_NAME')) { $background_file_name = CUSTOM_LOGIN_PAGE_BG_FILE_NAME; } if (!empty($background_file_name)) { $background_full_path = trailingslashit($base_full_path) . $background_file_name; } $logo_image_full_path = null; if (defined('CUSTOM_LOGIN_LOGO_FILE_NAME')) { $logo_image_file_name = CUSTOM_LOGIN_LOGO_FILE_NAME; } if (!empty($background_file_name)) { $logo_image_full_path = trailingslashit($base_full_path) . $logo_image_file_name; } if (defined('CUSTOM_LOGIN_BUTTON_BG')) { $login_button_background_colour = CUSTOM_LOGIN_BUTTON_BG; } if (defined('CUSTOM_LOGIN_BUTTON_FG')) { $login_button_text_colour = CUSTOM_LOGIN_BUTTON_FG; } $additional_url_full_path = null; if (defined('CUSTOM_LOGIN_ADDITIONAL_CSS')) { $additional_url_file_name = CUSTOM_LOGIN_ADDITIONAL_CSS; } if (!empty($background_file_name)) { $additional_url_full_path = trailingslashit($base_full_path) . $additional_url_file_name; } // Register external styles? if (is_readable($additional_url_full_path)) { $additional_css_url = get_stylesheet_directory_uri() . '/' . $base_dir . '/' . $additional_url_file_name; wp_enqueue_style('custom-login-css', $additional_css_url, false); } // Add inline styles. echo '<style type="text/css">'; // Background image? if (is_readable($background_full_path)) { $image_url = get_stylesheet_directory_uri() . '/' . $base_dir . '/' . $background_file_name; echo 'body:after {'; printf('background-image: url( "%s" );', esc_url($image_url)); echo '}'; } // Logo image? if (is_readable($logo_image_full_path)) { $image_url = get_stylesheet_directory_uri() . '/' . $base_dir . '/' . $logo_image_file_name; echo '#login h1 a {'; printf('background-image: url( "%s" );', esc_url($image_url)); printf('width: %s;', $logo_image_width); printf('height: %s;', $logo_image_height); echo '}'; } // The login button FG and BG. echo '#login .button-primary {'; if (!empty($login_button_text_colour)) { printf('color: %s;', $login_button_text_colour); } if (!empty($login_button_background_colour)) { printf('background-color: %s;', $login_button_background_colour); } echo '}'; echo '</style>'; // Inline login styles. } add_action('login_enqueue_scripts', 'hw_login_page_scripts', 20); /** * So when you click on the logo on the login page, it takes the user to our * site isntead of wordpress.org. */ function hw_login_headerurl($login_header_url) { return home_url(); } add_filter('login_headerurl', 'hw_login_headerurl'); }
There’s quite a bit to take in here, but it’s actually pretty simple. The key points are:
- If IS_CUSTOM_LOGIN_ENABLED is either not defined, or is not true, then don’t apply any of our customisation.
- Hook the standard WordPress login_enqueue_scripts action to apply our modifications.
- Most actions and filters are called with a priority of 10. We’re calling ours with a priority of 20 to make sure it’s called after any standard WordPress actions.
- When our custom_login_page_scripts() function is called, we just do this:
- Pull our configuration settings from a bunch of global constants and store them in local variables.
- If login-page/style.css (or whatever you’ve set in CUSTOM_LOGIN_ADDITIONAL_CSS) exists then enqueue it, so WordPress will put it in the headers.
- Write some inline styles to apply standard colours and the login logo.
- Have a look at the end of the code and you’ll see that we hook into login_headerurl. This is so that when a user clicks on the logo above the login box, they will be directed to our site’s front page, instead of wordpress.org. It’s a nice final touch.
Here’s our style.css, which we’re trying to keep fairly generic and reusable.
/** * Custom login CSS. */ #login h1 a { background-size: contain; } #login .button-primary { font-weight: bold; transition: 0.3s; } #login .button-primary:hover { opacity: 0.80; } body:after { background-size: cover; content: ' '; position: fixed; left: 0; top: 0; width: 100%; height: 100%; color: white; opacity: 0.50; z-index: -1; -webkit-filter: blur(5px); }
Now, we could reduce the code in our function to next-to-nothing, and just put the colours, login logo & background image straight into our CSS file. And there would be nothing wrong with that. But… your theme will probably already have access to some standard colours in PHP variables – things like like your standard button colours. By adding our colours programmatically (instead of to style.css), we can reuse all the assets in the login-page folder between multiple projects without having to change any lines of code. Everything that’s site-specific is in the custom child theme’s functions.php.
Finish and Deploy
Here’s what our finished login-page folder should look like, complete with the two image assets…
That’s it! We’ve hooked a single WordPress action to call a custom function. The new code exists in its own little file, tucked-away in a folder with the related assets. This means we can easily reuse this snippet on another WordPress website copying the login-page folder, and adding a couple of lines to the theme’s functions.php.