The default WordPress login page at wp-login.php works fine, but its generic branding sticks out on client projects. WordPress provides hooks to reskin it without touching any core files.
Problem: How do you rebrand the WordPress login page to match your client's site without editing core files?
Solution: Use the login_enqueue_scripts, login_headerurl, and login_headertext hooks to replace the logo, its link, and the page title, then enqueue a custom stylesheet.
The hooks below replace the logo, its link and title, and load a custom stylesheet on the login page:
<?php
// Replace the WordPress logo with your own
add_action( 'login_enqueue_scripts', 'custom_login_logo' );
function custom_login_logo() {
$logo_url = get_stylesheet_directory_uri() . '/images/logo.png';
?>
<style>
#login h1 a {
background-image: url( <?php echo esc_url( $logo_url ); ?> );
background-size: contain;
width: 200px;
height: 60px;
}
</style>
<?php
}
// Make the logo link point to the site, not wordpress.org
add_filter( 'login_headerurl', function() {
return home_url( '/' );
} );
// Update the logo title/alt text
add_filter( 'login_headertext', function() {
return get_bloginfo( 'name' );
} );
// Load a custom stylesheet on the login page
add_action( 'login_enqueue_scripts', 'enqueue_custom_login_styles' );
function enqueue_custom_login_styles() {
wp_enqueue_style(
'custom-login',
get_stylesheet_directory_uri() . '/css/login.css',
[],
wp_get_theme()->get( 'Version' )
);
}
To redirect users to a custom page after login based on their role:
add_filter( 'login_redirect', 'custom_login_redirect', 10, 3 );
function custom_login_redirect( $redirect_to, $request, $user ) {
if ( $user instanceof WP_User ) {
if ( $user->has_cap( 'manage_options' ) ) {
return admin_url();
}
return home_url( '/dashboard/' );
}
return $redirect_to;
}
NOTE: The login_headertext filter was added in WordPress 5.2. For older installs, use the deprecated login_headertitle filter. Always add logo images via CSS — not via <img> tags injected with JavaScript.