How To Create A Totally Custom WordPress Login Page

Let’s face it, in the years since we’ve been using WordPress, the login screen hasn’t changed much. Sure, you can customize it with a logo but beyond that, it doesn’t really offer much variety. In fact, the default WordPress admin login page really breaks the user’s experience when you have a custom theme in place. Going from your beautiful theme to the default WordPress login page is like going from Paris to Siberia in an instant.

Why not change up the game a little bit with a totally custom login page? The possibilities are endless. With a little bit of CSS and Javascript magic, you can have a login page that doesn’t look anything like the default.

In this tutorial we walk through all the steps to creating a WordPress login page with a custom background, custom fonts and styles, as well as a fancy jQuery fade-in effect on the form.

Here’s an example of what we’ll be making:

A totally customized WordPress login page

View the Live Demo

This tutorial will cover several basic modifications to theme files that will allow you to create a stunning login page for your WordPress-powered website.

  • Step 1. Add a Custom Background
  • Step 2. Replace WordPress Logo with a Custom Logo
  • Step 3. Customize the Appearance of the Login Form
  • Step 4. Customize Typography with Google Fonts
  • Step 5: Add a jQuery “Fade-In” Effect to the Form
  • Step 6. Change the Logo Link to a Custom URL
Create a /login/ directory in your current theme’s folder

All of these modifications can be added to your theme. While you could easily add them as a plugin, it makes sense to place the changes in your theme folder since you’re likely to want to match the styles to your current active theme. I suggest keeping your login files in a new /login directory within your theme folder. That will help you to keep everything related to these modifications in one place.

Step 1. Add a Custom Background

Now, if you’ve ever tried to add styles to your theme’s stylesheet in hopes of customizing the login page, then you probably found this out the hard way: WordPress does not load your theme’s stylesheet on the login page.

No worries, we’ll create and load our own for this example. Open a .txt file and name it login-styles.css. Upload it to your new /login/ directory.

Now we will tell WordPress to load this stylesheet on the login page. Add this to your theme’s functions.php file.

1
2
3
4
5
function custom_login_css() {
echo '<link rel="stylesheet" type="text/css" href="'.get_stylesheet_directory_uri().'/login/login-styles.css" />';
}

add_action('login_head', 'custom_login_css');

Select a background from among your own images, use a stock image or grab a creative commons-licensed image. The most important thing to remember is that you’ll need to select an image large enough to look decent on larger monitors. Upload your image the /login/ directory.

Customizing the background can easily be done with CSS. By default, WordPress adds a .login class to the body of the login page, so you can use this class to add your own background:

1
2
3
body.login {
background: #fbfbfb url('your-bg.jpg') no-repeat fixed center;
}

You’ll be overriding the styles located at /wp-admin/css/login.css so feel free to take a look at that file to get a better idea or use firebug to help you target specific styles.

Step 2. Replace WordPress Logo with a Custom Logo

The WordPress logo is included on the login page as the background of the .login h1 a element. Upload your own logo to /login/ and take note of its height and width.

1
2
3
4
5
6
.login h1 a {
background-image: url('../login/logo.png');
background-size: 300px 260px;
width: 300px;
height: 260px;
}

Add the image to the login directory. Replace the background-size, width and height with the dimensions of your own logo.

You may need to adjust the padding a bit depending on the height of the logo.

1
2
3
#login {
padding: 30px 0 0;
}

Step 3. Customize the Appearance of the Login Form

Now let’s do something interesting with the form design. I took a bit of inspiration from a transparent contact form featured on CodePen. We’ll take the form from the default and transform it to look like so:

WordPress default login form vs the new form with custom CSS applied

You can of course use any styles you want, but the CSS below shows how to make the form transparent like the demo.

First let’s add the styles for the form itself:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.login form {
margin-left: auto;
margin-right: auto;
padding: 30px;
border: 1px solid rgba(0,0,0,.2);
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-background-clip: padding;
-webkit-background-clip: padding-box;
background-clip: padding-box;
background: rgba(0, 0, 0, 0.5);
-moz-box-shadow: 0 0 13px 3px rgba(0,0,0,.5);
-webkit-box-shadow: 0 0 13px 3px rgba(0,0,0,.5);
box-shadow: 0 0 13px 3px rgba(0,0,0,.5);
overflow: hidden;
}

Next, we will customize the input element and add a soft, fuzzy focus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.login form input {
width: 240px;
height: 48px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
display: block;
}

.login form input:focus,
.login form textarea:focus {
background-color: rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 0 5px 1px rgba(255,255,255,.5);
-webkit-box-shadow: 0 0 5px 1px rgba(255,255,255,.5);
box-shadow: 0 0 5px 1px rgba(255,255,255,.5);
overflow: hidden;
}

Depending on the colors you choose for your form, you may also need to customize the labels and adjust the “remember me” checkbox.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.login label {
color: #fff;
line-height: 26px;
}

.login form .input,
.login input[type="text"] { color: #8c8a8a; }
input#rememberme {
height: 18px;
width: 18px;
display: inline;
vertical-align: middle;
margin: 10px 0;
}

Finally, we’ll tackle the button style and give it a gradient to match the theme:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
input.button-primary {
width: 138px;
height: 44px;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
float:right;
border: 1px solid #3d5a5a;
background: #416b68;
background: -webkit-gradient(linear, left top, left bottom, from(#6da5a3), to(#416b68));
background: -webkit-linear-gradient(top, #6da5a3, #416b68);
background: -moz-linear-gradient(top, #6da5a3, #416b68);
background: -ms-linear-gradient(top, #6da5a3, #416b68);
background: -o-linear-gradient(top, #6da5a3, #416b68);
background-image: -ms-linear-gradient(top, #6da5a3 0%, #416b68 100%);
padding: 10.5px 21px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
-webkit-box-shadow: rgba(255,255,255,0.1) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
-moz-box-shadow: rgba(255,255,255,0.1) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
box-shadow: rgba(255,255,255,0.1) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
text-shadow: #333333 0 1px 0;
color: #e1e1e1;
}

input.button-primary:hover {
border: 1px solid #3d5a5a;
text-shadow: #333333 0 1px 0;
background: #416b68;
background: -webkit-gradient(linear, left top, left bottom, from(#77b2b0), to(#416b68));
background: -webkit-linear-gradient(top, #77b2b0, #416b68);
background: -moz-linear-gradient(top, #77b2b0, #416b68);
background: -ms-linear-gradient(top, #77b2b0, #416b68);
background: -o-linear-gradient(top, #77b2b0, #416b68);
background-image: -ms-linear-gradient(top, #77b2b0 0%, #416b68 100%);
color: #fff;
}

input.button-primary:active {
margin-top:1px;
text-shadow: #333333 0 -1px 0;
border: 1px solid #3d5a5a;
background: #6da5a3;
background: -webkit-gradient(linear, left top, left bottom, from(#416b68), to(#416b68));
background: -webkit-linear-gradient(top, #416b68, #609391);
background: -moz-linear-gradient(top, #416b68, #6da5a3);
background: -ms-linear-gradient(top, #416b68, #6da5a3);
background: -o-linear-gradient(top, #416b68, #6da5a3);
background-image: -ms-linear-gradient(top, #416b68 0%, #6da5a3 100%);
color: #fff;
-webkit-box-shadow: rgba(255,255,255,0) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
-moz-box-shadow: rgba(255,255,255,0) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
box-shadow: rgba(255,255,255,0) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
}

Step 4. Customize Typography with Google Fonts

Want your login page fonts to match your theme? Not a problem! We can do that too. In this example we’ll use Google Fonts to customize the bottom nav links and the Logged Out message:

Typography customized with Google Fonts

We’ll add it the same way we called the custom login-styles.css file. Add this to your functions.php file:

1
2
3
4
5
function custom_fonts() {
echo '<link href="http://fonts.googleapis.com/css?family=Open+Sans+Condensed:300,700" rel="stylesheet" type="text/css">';
}

add_action('login_head', 'custom_fonts');

Paste in the link that the Google Fonts site gives you for using the font.

Now you can use the custom font on the login page. In the demo we have customized the links below the login form as well as the logged out message:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.login #nav a,
.login #backtoblog a {
font-family: 'Open Sans Condensed', sans-serif;
color: #00667!important;
font-size: 17px;
}

div.updated,
.login .message {
background-color: lightYellow;
border-color: #E6DB55;
font-family: 'Open Sans Condensed', sans-serif;
font-size: 16px;
font-weight: 700;
}

Step 5: Add a jQuery “Fade-In” Effect to the Form

Here’s where we add a bit of sparkle. You’ll have to view the Live Demo in order to see how it works. Essentially, we are loading the page with the form and the bottom links hidden and then fading them in slowly.

You can add this bit of jQuery to the login page and specify the selectors to which you’d like to apply the effect. The number in the parentheses next to the fadeIn sets how long (in milliseconds) you want the fading to take until complete.

1
2
3
4
5
6
7
8
add_action( 'login_head', 'untame_fadein',30);

function untame_fadein() {
echo '<script type="text/javascript">// <![CDATA[
jQuery(document).ready(function() { jQuery("#loginform,#nav,#backtoblog").css("display", "none");          jQuery("#loginform,#nav,#backtoblog").fadeIn(3500);     
});
// ]]></script>';
}

Step 6. Change the Logo Link to a Custom URL

One of the last steps is to make sure that your logo points to your website, instead of wordpress.org. This can be done by adding a filter to your functions.php file.

1
2
3
4
add_filter( 'login_headerurl', 'custom_login_header_url' );
function custom_login_header_url($url) {
return 'http://untame.net/';
}

Replace the URL with your own site’s URL and add this to your functions.php file.

So there you have it. Just a few simple lines of CSS and jQuery can transform your WordPress login into a totally custom, branded page that will match your theme.

A custom login page design is something you want to seriously consider if you have users logging into your WordPress site all the time. It’s one more opportunity for you to brand your site and services. We often forget that users are also returned to this page after they log out and many times it is the last impression they receive of your website. So take a few minutes and design a login experience that will make the right impression.

Featured Plugin - WordPress Facebook Plugin

Would you like to add Facebook comments, registration, 'Like' buttons and autoposting to your WP site? Well, The Ultimate Facebook plugin has got that all covered!
Find out more

Featured Plugin - WordPress Newsletter Plugin

Now there's no need to pay for a third party service to sign up, manage and send beautiful email newsletters to your subscriber base - this plugin has got the lot.
Find out more

Featured Plugin - WordPress Google Maps Plugin

Simply insert google maps into posts, sidebars and pages - show directions, streetview, provide image overlays and do it all from a simple button and comprehensive widget.
Find out more

Featured Plugin - WordPress Wiki Plugin

To get a wiki up and running you used to need to install Mediawiki and toil away for days configuring it... not any more! This plugin gives you *all* the functionality you want from a wiki, in WordPress!!!
Find out more

Featured Plugin - WordPress Membership Site Plugin

If you're thinking about starting a paid, or just private, membership site then this is truly the plugin you've been looking for. Easy to use, massively configurable and ready to go out of the box!
Find out more

Featured Plugin - WordPress Appointments Plugin

Take, set and manage appointments and client bookings without having to leave WordPress. Appointments+ makes it easy.
Find out more

Featured Plugin - WordPress Q&A Site Plugin

It's now incredibly easy to start your own Q&A site using nothing more than WordPress - The Q&A plugin simply and brilliantly transforms any site, or page, into a perfect support or Q&A environment.
Find out more

Featured Plugin - WordPress Pop-Up Chat Plugin

No javascript required, no third part chat engine, just fully featured chat right in your own database on your own WP sites - couldn't be easier.
Find out more

Featured Plugin - WordPress Ecommerce Shopping Cart Plugin

Out of all the WordPress ecommerce plugins available, MarketPress has got to be the winner - easy to configure, powerful functionality, multiple gateways and more. A simply brilliant plugin!
Find out more

Comments (58)

  1. I would love to know if this tutorial works on a WP-Network install or how it should be tweaked to get it to work across a WP-Network?

    And I totally agree, as a user of WPMUdev’s awesome Ultimate Branding plugin, being able to accomplish these same aesthetic feats with that plugin would be a spectacular update.

  2. Hi Sarah,
    this is fantastic and everything works well so far – except when I log in from my now customized login page it wouldn’t redirect me to my WordPress blog.

    Could be I missed something, but frankly I did copy simply the code shown here for the most part.

    The blog I am building up right now is here:
    rams.exklotz.de

    Any idea on where I may have failed?

    Thanks
    Oliver

  3. Hi Sarah,

    Great post. One thing you forgot was the logo title. All one needs to do is this code to functions.php:

    add_filter(“login_headertitle”, ‘custom_login_title’);
    function custom_login_title() {
    return (‘Powered by red-tulip.co.uk’);
    }

    (change as needed)

  4. Great article!
    However I have a problem with the code on (http://nside.se/wp-login.php)
    On my mac the “remember me” checkbox fits perfectly, but on my windows computer it’s huge, both computers are running the latest versions of Chrome.

    On a side note, I wan’t to implement this custom login page for the Registration form aswell, and make it work with all of the sites on our Multisite network. Is this possible?

  5. Sarah,

    Your article was excellent and easy to follow.

    I ran into a problem with the jQuery effects. After research and trial and error I resolved the problem by deregistering the default jQuery script and registering the Google jQuery version with the code below. Can you help me understand why this was necessary and how it works?

    //Making jQuery Google API
    function modify_jquery() {
    if (!is_admin()) {
    // comment out the next two lines to load the local copy of jQuery
    wp_deregister_script(‘jquery’);
    wp_register_script(‘jquery’, ‘http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js’, false, ’1.8.1′);
    wp_enqueue_script(‘jquery’);
    }
    }
    add_action(‘init’, ‘modify_jquery’);

  6. Great Guide!
    I’m using a theme from WooThemes so it allows me to directly do quite a few things, changing the login branding and the link being a few of them.
    Adding a custom background is something I found interesting. That can make the login page completely mix up with the site’s main theme. Your login form at untame really is so appealing. Thanks for this guide. I’m going to try this thing out :)

  7. Thank you very much for this code! I am having the same problem as a few other people. On a smaller screen, there is a white bar across the bottom of the login form.. I have tried re adjusting in the background css but can’t seem to fix it. It seems to have something to do with scrolling the page down on a smaller monitor. Can you help?

  8. This is an amazing tutorial! Thanks so much,

    I am having one problem though and it seems to be happening to other also, the WHITE BAR at the bottom, how do we overcome this issue??

    Thanks again for this, it’s great.

  9. OK, I give in…:)

    How do i also get the “lost your pass” and “back to untame” on the same line??

    This bit is driving me crazy, i cant seem to find the css for it.

    Hope someone can help.

  10. I haven’t gone into detail about the white area at the bottom, but would hazard a guess that it’s to do with the background scaling. In the wp-admin css settings there is the line below:

    .login #nav, .login #backtoblog {
    margin: 0 0 0 16px;
    padding: 16px 16px 0;
    text-shadow: 0 1px 0 #FFFFFF;
    }

    If you add a background color you’ll see that changes the white area. If I get time later I’ll see if I can find why the image isn’t scaling. It might be a simple as adding a @media statement to your CSS for that area for the screen size where it occurs, to compensate for any padding or margins being used.

    I hope that helps, for now.

    Steve

  11. In step 1, I don’t understand where you put the second piece of code. I’ve changed the functions.php file. does this code go in functions.php or in the new login-styles.css you had me create?

    Reference:

    body.login {
    background: #fbfbfb url(‘your-bg.jpg’) no-repeat fixed center;
    }

    Thanks

      • Thank you Steve.

        She has me create login.styles.css, under the new folder /login. Once I put the code in there, it did not change the background.

        The path I have is:

        public_html/wp-content/themes/gamepress/login/login-styles.css

        The entire contents of login-styles.css is just that code. Am I supposed to be copying more code from the original file she mentions?

        “You’ll be overriding the styles located at /wp-admin/css/login.css”

        I only have experience with two wordpress sites and have coded one simple CSS site by myself, so I’m not a professional, and I rely mostly on the plugins to do things for me, but I’d like to feel more confident with the CSS itself.

        • I just noticed I don’t have this file she has pointed to as being an example. Nothing with the word login at all in that folder. :(

          /wp-admin/css/login.css

          • You don’t need that file – the CSS code you put into the login-styles.css file will override the original, but only for the styles that you call out. Did you add the code to the functions.php for the tutorial?

            Here’s my login-styles.css for instance. This is not to say that this one will work for you, but it gives you a clue as to what goes in there.

            It’s going to be trial and error a little if you’re not used to it, but you will get there. I use the web developer plugin and the firebug plugin to see what CSS does what.

            If you post the URL to your site I could take a look this weekend.

            /* Login page */
            body.login {
            background: #fbfbfb url(‘image-bg.jpg’) no-repeat fixed center;
            }

            .login h1 a {
            background-image: url(‘../login/logo.png’);
            background-size: 325px 71px;
            width: 325px;
            height: 71px;
            margin: 0 0 10px -19px;
            }

            .login form {
            margin-left: auto;
            margin-right: auto;
            padding: 30px;
            border: 1px solid rgba(0,0,0,.2);
            -moz-border-radius: 5px;
            -webkit-border-radius: 5px;
            border-radius: 5px;
            -moz-background-clip: padding;
            -webkit-background-clip: padding-box;
            background-clip: padding-box;
            background: rgba(0, 0, 0, 0.5);
            -moz-box-shadow: 0 0 13px 3px rgba(0,0,0,.5);
            -webkit-box-shadow: 0 0 13px 3px rgba(0,0,0,.5);
            box-shadow: 0 0 13px 3px rgba(0,0,0,.5);
            overflow: hidden;
            }

            .login form input {
            width: 240px;
            height: 48px;
            -moz-border-radius: 4px;
            -webkit-border-radius: 4px;
            border-radius: 4px;
            display: block;
            }

            .login form input:focus,
            .login form textarea:focus {
            background-color: rgba(0, 0, 0, 0.2);
            -moz-box-shadow: 0 0 5px 1px rgba(255,255,255,.5);
            -webkit-box-shadow: 0 0 5px 1px rgba(255,255,255,.5);
            box-shadow: 0 0 5px 1px rgba(255,255,255,.5);
            overflow: hidden;
            }

            .login label {
            color: #fff;
            line-height: 26px;
            }

            .login form .input,
            .login input[type="text"] { color: #8c8a8a; }
            input#rememberme {
            height: 18px;
            width: 18px;
            display: inline;
            vertical-align: middle;
            margin: 10px 0;
            }

            #login input.button-primary {
            font-size: 16px;
            text-transform: uppercase;
            width: 258px;
            height: 44px;
            -moz-border-radius: 4px;
            -webkit-border-radius: 4px;
            border-radius: 4px;
            float:right;
            border: 1px solid #3d5a5a;
            background: #416b68;
            background: -webkit-gradient(linear, left top, left bottom, from(#6da5a3), to(#416b68));
            background: -webkit-linear-gradient(top, #6da5a3, #416b68);
            background: -moz-linear-gradient(top, #6da5a3, #416b68);
            background: -ms-linear-gradient(top, #6da5a3, #416b68);
            background: -o-linear-gradient(top, #6da5a3, #416b68);
            background-image: -ms-linear-gradient(top, #6da5a3 0%, #416b68 100%);
            padding: 10.5px 21px;
            -webkit-border-radius: 6px;
            -moz-border-radius: 6px;
            border-radius: 6px;
            -webkit-box-shadow: rgba(255,255,255,0.1) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
            -moz-box-shadow: rgba(255,255,255,0.1) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
            box-shadow: rgba(255,255,255,0.1) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
            text-shadow: #333333 0 1px 0;
            color: #e1e1e1;
            }

            #login input.button-primary:hover {
            border: 1px solid #3d5a5a;
            text-shadow: #333333 0 1px 0;
            background: #416b68;
            background: -webkit-gradient(linear, left top, left bottom, from(#77b2b0), to(#416b68));
            background: -webkit-linear-gradient(top, #77b2b0, #416b68);
            background: -moz-linear-gradient(top, #77b2b0, #416b68);
            background: -ms-linear-gradient(top, #77b2b0, #416b68);
            background: -o-linear-gradient(top, #77b2b0, #416b68);
            background-image: -ms-linear-gradient(top, #77b2b0 0%, #416b68 100%);
            color: #fff;
            }

            #login input.button-primary:active {
            margin-top:1px;
            text-shadow: #333333 0 -1px 0;
            border: 1px solid #3d5a5a;
            background: #6da5a3;
            background: -webkit-gradient(linear, left top, left bottom, from(#416b68), to(#416b68));
            background: -webkit-linear-gradient(top, #416b68, #609391);
            background: -moz-linear-gradient(top, #416b68, #6da5a3);
            background: -ms-linear-gradient(top, #416b68, #6da5a3);
            background: -o-linear-gradient(top, #416b68, #6da5a3);
            background-image: -ms-linear-gradient(top, #416b68 0%, #6da5a3 100%);
            color: #fff;
            -webkit-box-shadow: rgba(255,255,255,0) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
            -moz-box-shadow: rgba(255,255,255,0) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
            box-shadow: rgba(255,255,255,0) 0 1px 0, inset rgba(255,255,255,0.7) 0 1px 0;
            }

            .login #nav a,
            .login #backtoblog a {
            font-family: ‘Open Sans Condensed’, sans-serif;
            color: #00667!important;
            font-size: 17px;
            }

            div.updated,
            .login .message {
            background-color: lightYellow;
            border-color: #E6DB55;
            font-family: ‘Open Sans Condensed’, sans-serif;
            font-size: 16px;
            font-weight: 700;
            }

  12. So basically what I did was copy your code just now and put it in the login-styles.css file, except with my own bg file. It’s not doing anything so whatever is going on in functions is not recognizing it.

  13. Also I just noticed my comment is pending approval from yesterday for whatever reason. I wrote:

    “Did you add the code to the functions.php for the tutorial?”

    I think so. The site is abrahadabra.com. Gamepress is the site’s theme. In the file /public_html/wp-content/themes/gamepress/functions.php

    (I also posted the code from functions in the original post, but again, it’s “pending approval”)

  14. well nevermind I totally gave up, I can’t figure out why it’s not recognizing the command in step 1 and I guess I can use the Theme My Login plugin even if it makes the site slower

  15. For the button, your example uses input.button-primary.

    But I have to use .wp-core-ui input.button-primary.

    Turns out the file that overrides everything is the buttons.min.css stylesheet.

    While I don’t think it’s a big issue, I’m still curious as to why I’ve gotta use a different selector than in the example in the tutorial.

    Thanks.

Participate