WP Login/Register Click To Show Forms

There are many tutorials and plugins for custom WordPress login and registration forms. In addition, the native WordPress login/register forms and functions do an excellent job. Even so, every site has its own needs which can require different ways of handling login and registration.

Here is one way to add Login and Register buttons to your site. This method is different from other tutorials that I found, specifically in these ways:

Key Features:

  • No forms taking up space. Only buttons. Click a button to show the form.
  • Log in or register from any page and stay on that page.
  • No “Login” page, rather just buttons somewhere convenient on your site, such as the top right corner. Users can login/register from any page on your site and stay on that page after the login/registration is successful.
  • When registering, they pick their own password. No emailed passwords, since I really don’t think that emailing passwords is safe.
  • User is automatically logged in after registering.
  • “Lost Password” form is filled out on front end, without redirecting to Admin back end.
  • Logged-in users will instead see their name and a Logout button.

Here’s how it will look:


Try it yourself: Click the Log In button to open the login form. Click the “Lost Password” link on the login form to open the “Reset password” form. Click the Register button to show the Register form. Click “Hide” to hide the form.

How To Implement

You’ll need to add the functions, the JavaScript (note that this requires jQuery), and some CSS to your WordPress site. Then simply use the template tag in a template file where you want to show the buttons. This is broken into 4 easy steps. Step 1 lists all the functions that you must add to your functions. Step 2 shows you the necessary JavaScript. Step 3 shows you the necessary CSS. Step 4 show you how to use the template tag.

Step 1: Functions

You can simply copy all of the functions from Step 1 to your child theme’s functions.php or to a custom plugin. These will work as is, but I’ll explain each a little bit in case you want to customize anything.

The 2 functions to process our registration form and log the user in after registration:

 * Register And Login New User
 * @param 	array   $user_data
 * @return 	integer
function isa_register_login_new_user( $user_data = array() ) {
	// Verify the array
	if ( empty( $user_data ) )
		return -1;

	$user_args = array(
			'user_login'		=> isset( $user_data['user_login'] ) ? $user_data['user_login'] : '',
			'user_pass'			=> isset( $user_data['user_pass'] )  ? $user_data['user_pass']  : '',
			'user_email'		=> isset( $user_data['user_email'] ) ? $user_data['user_email'] : '',
			'user_registered' 	=> date( 'Y-m-d H:i:s' ),
			'role'				=> 'subscriber'

	// Insert new user
	$user_id = wp_insert_user( $user_args );

	// Validate inserted user
	if ( is_wp_error( $user_id ) )
		return -1;
	if ( $user_id < 1 )

	// Login new user
	wp_set_current_user( $user_id, $user_data['user_login'] );
	wp_set_auth_cookie( $user_id );
	do_action( 'wp_login', $user_data['user_login'], get_userdata( $user_id ) );

	return $user_id;

 * Process Register Form
 * @param array $data Data sent from the register form
function isa_process_register_form( $data ) {

	if( is_user_logged_in() ) {
	if( empty( $_POST['isa_wp_register'] ) ) {
	// Block spam bots
	if ( ! empty( $_POST['isa_hundred_acre_wood_field'] ) ) {
	$reg_errors = array();

	if( empty( $data['register_user_login'] ) ) {
		$reg_errors[1] = true;
	if( username_exists( $data['register_user_login'] ) ) {
		$reg_errors[2] = $data['register_user_login'];
	if( ! validate_username( $data['register_user_login'] ) ) {
		$reg_errors[3] = $data['register_user_login'];
	if( email_exists( $data['register_user_email'] ) ) {
		$reg_errors[4] = $data['register_user_email'];
	if( empty( $data['register_user_email'] ) || ! is_email( $data['register_user_email'] ) ) {
		$reg_errors[5] = true;
	if( empty( $_POST['register_user_pass'] ) ) {
		$reg_errors[6] = true;
	if( ( ! empty( $_POST['register_user_pass'] ) && empty( $_POST['register_user_pass_again'] ) ) || ( $_POST['register_user_pass'] !== $_POST['register_user_pass_again'] ) ) {
		$reg_errors[7] = true;

	$referrer = $data['isa_register_permalink'];

	// Check for errors and register if none present
	if ( ! $reg_errors ) {

		isa_register_login_new_user( array(
			'user_login'      => $data['register_user_login'],
			'user_pass'       => $data['register_user_pass'],
			'user_email'      => $data['register_user_email']
		) );

		$redirect = add_query_arg( array( 'isa_register' => 'successful' ), $referrer );

	} else {

		$query_args = array();

		$query_args['isa_register'] = 'failed';

		// add query args for registration errors
		foreach ( $reg_errors as $k => $v ) {
			if ( $v ) {
				$error_key = 'e' . $k;
				$query_args[$error_key] = $v;
		$redirect = add_query_arg( $query_args, $referrer );

	wp_safe_redirect( esc_url_raw( $redirect ) );
add_action( 'isa_user_register', 'isa_process_register_form' );

The second function above, isa_process_register_form, processes the registration form. It checks for errors. If there are no errors, it calls the first function, isa_register_login_new_user to register and log the user in. If errors were found, we add query args for the errors so that we can show error messages to the visitor. The user is safely redirected back to their current page.

Next, the function that fires our action when our registration form is submitted. This action, isa_user_register, is used to hook our previous function to.

 * Listen for our Registration form submit
function isa_init() {
	if ( isset( $_POST['isa_register_action'] ) ) {
		do_action( 'isa_user_register', $_POST );
add_action('init', 'isa_init');

Next, the function to create a template tag that holds all the HTML for the buttons and forms. In this function, change all instances of ‘textdomain’ to your own textdomain.

 * The template tag to display the login/register buttons.
function isa_show_login_register() {
	// did they just try to register?
	$just_reg = empty( $_GET['isa_register'] ) ? '' : $_GET['isa_register'];
	// Get URL for redirecting back to current page
	if ( is_tax() ) {
		$permalink = get_term_link( get_query_var( 'term' ), get_query_var( 'taxonomy' ) );
	} elseif ( is_post_type_archive() ) {
		$permalink = get_post_type_archive_link( get_query_var('post_type') );
	} elseif ( is_home() ) {
		$permalink = get_permalink( get_option( 'page_for_posts' ) );
	} else {
		$permalink = get_permalink();

    if ( is_user_logged_in() ) {
        // If they just registered, show a success message
        if ( 'successful' == $just_reg ) { ?>
            <span id="isa-register-success"><?php _e( 'Registration successful! Welcome to your journey!', 'textdomain' ); ?></span>
        <?php } else {
            // Show a button with a user icon and their name, linking to their profile page.
            // And a Log Out button
            $current_user = wp_get_current_user();
            Next is a link to the user's profile page.
            For example, if using bbPress, you can link to:
            bbp_get_user_profile_url( $current_user->ID )
            If you don't have profile pages on your site, you can change this link
            instead to be a span element with a simple greeting.
            <a class="button isa-inline-buttons" href="#" title="<?php _e( 'View profile', 'textdomain' ); ?>">
                <i class="fa fa-user"></i> <?php echo $current_user->display_name; ?>
            <!-- Log Out button -->
            <a href="<?php echo wp_logout_url( get_permalink() ); ?>" class="button isa-inline-buttons" title="<?php _e( 'Log out', 'textdomain' ); ?>"><?php _e( 'Log Out', 'textdomain' ); ?></a><?php
    } else {
        <!-- Login and Register buttons -->
        <button type="button" id="isa_loginbutton"><?php _e( 'Log in', 'textdomain' ); ?></button>
        <button type="button" id="isa_registerbutton"><?php _e( 'Register', 'textdomain' ); ?></button>
        // If login just failed, show login failed msg
        $login_failed = empty( $_GET['login'] ) ? '' : $_GET['login'];
        if ( 'failed' == $login_failed ) { ?>
            <span id="isa-login-error" class="box_error"><strong><?php _e( 'ERROR:', 'textdomain' ); ?></strong><br /><?php _e( 'Invalid username or password. Please try logging in again.', 'textdomain' ); ?></span>
        <?php }
        // If Lost Password form was just filled out, show Reset PW message
        $resetpw = empty( $_GET['resetpw'] ) ? '' : $_GET['resetpw'];
        if ( true == $resetpw ) { ?>
            <span id="isa-reset-pw"><?php _e( 'Check your email to reset your password.', 'textdomain' ); ?></span>
        <?php }
        // if Registration attempt just failed, show registration errors
        if ( 'failed' == $just_reg ) {
            $errors = '';
            $e1 = empty( $_GET['e1'] ) ? '' : $_GET['e1'];
            $e2 = empty( $_GET['e2'] ) ? '' : $_GET['e2'];
            $e3 = empty( $_GET['e3'] ) ? '' : $_GET['e3'];
            $e4 = empty( $_GET['e4'] ) ? '' : $_GET['e4'];
            $e5 = empty( $_GET['e5'] ) ? '' : $_GET['e5'];
            $e6 = empty( $_GET['e6'] ) ? '' : $_GET['e6'];
            $e7 = empty( $_GET['e7'] ) ? '' : $_GET['e7'];
            if ( $e1 ) {
                $errors .= __( 'Invalid username.', 'textdomain' ) . '<br />';
            if ( $e2 ) {
                $errors .= sprintf( __( 'Username "%s" is already taken.', 'textdomain' ), $e2 ) . '<br />';
            if ( $e3 ) {
                $errors .= sprintf( __( 'Invalid username: %s.', 'textdomain' ), $e3 ) . '<br />';
            if ( $e4 ) {
                $errors .= sprintf( __( 'Email address "%s" already exists. Please log in.', 'textdomain' ), $e4 ) . '<br />';
            if ( $e5 ) {
                $errors .= __( 'Invalid email.', 'textdomain' ) . '<br />';
            if ( $e6 ) {
                $errors .= __( 'Please enter a password.', 'textdomain' ) . '<br />';
            if ( $e7 ) {
                $errors .= __( 'Passwords do not match.', 'textdomain' ) . '<br />';
            <span id="isa-register-errors">
                <strong><?php _e( 'Registration Error:', 'textdomain' ); ?></strong>
                <br />
                <?php echo $errors; ?>
        <!-- Login Form -->
        <?php wp_login_form(array('form_id' => 'isa_loginform','value_remember' => true)); ?>
        <!-- Register Form -->
        <form name="isa_registerform" id="isa_registerform" action="" method="post">
            <p class="register-username">
                <label for="register_user_login"><?php _e( 'Username', 'textdomain' ); ?></label>
                <input type="text" name="register_user_login" id="register_user_login" class="input" value="" size="20" required />
            <p class="register-email">
                <label for="register_user_email"><?php _e( 'Email', 'textdomain' ); ?></label>
                <input type="email" name="register_user_email" id="register_user_email" class="input" value="" size="20" required />
            <p class="register-password">
                <label for="register_user_pass"><?php _e( 'Password', 'textdomain' ); ?></label>
                <input type="password" name="register_user_pass" id="register_user_pass" class="input" value="" size="20" required />
            <p class="register-password-again">
                <label for="register_user_pass_again"><?php _e( 'Password Again', 'textdomain' ); ?></label>
                <input type="password" name="register_user_pass_again" id="register_user_pass_again" class="input" value="" size="20" required />
            <p id="isa-hundred-acre-wood">
                <label for="isa-hundred-acre-wood-field" id="isa-hundred-acre-wood-label"><?php _e( 'For Official Use Only', 'textdomain' ); ?></label>
                <input name="isa_hundred_acre_wood_field" type="text" id="isa-hundred-acre-wood-field" value="" />
            <p class="register-submit">
                <input type="hidden" name="isa_register_action" value="user_register" />
                <input type="hidden" name="isa_register_permalink" value="<?php echo esc_url( $permalink ); ?>" />
                <input type="submit" name="isa_wp_register" id="isa-wp-register" value="<?php _e( 'Register', 'textdomain' ); ?>" />
        <!-- Lost Password form -->
        <form name="lostpasswordform" id="isa_lostpwform" action="<?php echo site_url('wp-login.php?action=lostpassword', 'login_post') ?>" method="post">
            <p><strong><?php _e( 'Reset your password', 'textdomain' ); ?></strong>
                <label for="user_login"><?php _e( 'Username or E-mail:', 'textdomain' ); ?></label>
                <input type="text" name="user_login" id="user_login" value="" />
            <p class="submit">
                <input type="hidden" name="redirect_to" value="<?php echo esc_url( $permalink ); ?>?resetpw=true">
                <input type="submit" name="wp-submit" id="wp-submit" value="Get New Password" />

There are a couple spots where you may want to edit this last function.

  • Line 14. Edit the success message shown to users after they register.
  • Lines 35–37. This is a link with a Font Awesome “user” icon and the user’s name. I use this to link to the user’s profile page. Replace the “#” with the URL of your user’s profile page. If you don’t have a profile page for user’s, then change these 3 lines to a simple span element and something like “Hi, Name”, like so:
        <?php printf( 'Hi, %s', $current_user->display_name ); ?>

I’ll explain the function above just a little.

If a user is logged in, this checks if the user was just registered. If the user just now registered, they see the “Registration Successful” message on line 14. If they did not just register, they see their name and a log out button.

If the visitor is not logged in, they see the “Log in” and “Register” buttons just like on the demo at the top of this page. If they just had a failed login attempt, they see a message saying, “Invalid username or password. Please try logging in again.” If they just submitted the “Forgot Password” form, they’ll see a message saying, “Check your email to reset your password.” If they just had a failed registration attempt, they’ll see the errors. For example, “Username ‘SomeName’ is already taken.”

Next, we have to add the “Lost Password?” link to the WP login form. We’re using the native WordPress login form, and calling it with wp_login_form. It does not, by default, include the “Lost Password” link. Add it like this:

 * Add Lost Password? link to login form.
function isa_lost_password_link() {
    return '<p><button id="lostpw">' . __( 'Lost Password?', 'textdomain' ) . '</button></p>';
add_action( 'login_form_bottom', 'isa_lost_password_link' );

It’s important to keep the id="lostpw" so that when clicked, it will show the form. Also, change ‘textdomain’ to your own textdomain.

If our visitor tries to log in with an incorrect username or password, this next function makes sure that he will stay on the same page and not be redirected to the back-end admin.

 * Redirect back to front on failed login attempt.
 * Only catches incorrect username or password if both fields are filled in.
 * @todo doesn't work on empty fields. 
function isa_login_fail( $username ) {
	$referrer = $_SERVER['HTTP_REFERER'];
	// if there's a valid referrer, and it's not the default log-in screen
	if ( !empty($referrer) && ! strstr( $referrer,'wp-login' ) && ! strstr( $referrer,'wp-admin' ) ) {
		$url = add_query_arg( array( 'login' => 'failed' ), $referrer );
		wp_safe_redirect( esc_url_raw( $url ) );
add_action( 'wp_login_failed', 'isa_login_fail' );

The next function is not absolutely necessary, but it improves the user experience. Since we’re handling login and registration on the front end of the site, let’s remove the Lost Password and Register links from the back-end WP login page. There are 3 cases in which our visitors can end up back there. If we remove those back-end Password and Register links, the time spent back there will be short and sweet and our visitors will be redirected back to their original page on the front end. On the other hand, if they see these links and click on them, then it breaks our smooth redirect to the front, and our visitor will end up logged in to the back end (admin page). (The 3 cases in which our user can end up on the back-end WP login page are, 1. If they submit the login form with an empty field. Highly unlikely. 2. If they submit the “Forgot Password” form empty. Highly unlikely. 3. Clicking the Reset password link that they received through email.)

 * Hide the Lost Password and Register links on wp-login.
function isa_login_css() {
	echo '<style>body.login #login p#nav {display:none}</style>';
add_action('login_head', 'isa_login_css');

That is the end of the functions.

Step 2: JavaScript (jQuery)

jQuery(document).ready(function (jQuery) {

    // detect click and/or touch

    if ('ontouchstart' in window) {
        evt = 'touchstart';
    } else if (window.navigator.pointerEnabled) {
        evt = 'pointerdown';
    } else if (window.navigator.msPointerEnabled) {
        evt = 'MSPointerDown';
    } else {
        evt = 'click';

    // show login form 

    jQuery('#isa_loginbutton').on(evt, function () {
        jQuery('#isa_loginform').slideToggle('fast', function () {

            // Hide Lost PW orm either way

            if (jQuery('#isa_loginbutton').text() === 'Log in') {
                // hide register button
            } else {
                jQuery('#isa_loginbutton').text('Log in');
                // show register button

    // show register form

    jQuery('#isa_registerbutton').on(evt, function () {
        jQuery('#isa_registerform').slideToggle('fast', function () {

            // Hide Lost PW form either way

            if (jQuery('#isa_registerbutton').text() === 'Register') {
                // hide login button
            } else {
                // show login button

    // show lost pw form

    jQuery('#lostpw').on(evt, function (e) {

        e.preventDefault(); // button should not submit anything

        // hide login form

        // restrore button text
        jQuery('#isa_loginbutton').text('Log in');
        // restore register button

        // show lost pw form



Paste the JavaScript above into a new file. For example, name the file “login-register.js”. Then load it with wp_enqueue_script. Be sure to add jQuery as a dependency in the 3rd parameter, like this:

	get_template_directory_uri() . '/js/login-register.js',
	array( 'jquery' )

You must edit line 3 to be the URL of your new file, depending on where you place it. If you’re using a child theme, use get_stylesheet_directory_uri() instead of get_template_directory_uri(). If you’re placing this all into a plugin, use plugin_dir_url( __FILE__ ) instead of get_template_directory_uri(), and note that plugin_dir_url( __FILE__ ) does add a trailing slash to the URL. So, you would remove the slash before ‘js/’ on line 3, like this:

plugin_dir_url( __FILE__ ) . 'js/login-register.js',

Step 3: CSS

You can add the CSS to any existing stylesheet, or else paste it into a new file and use wp_enqueue_style to load it. (Or use the Custom CSS Jetpack Module, or any other Custom CSS plugin that lets you easily add custom CSS.)

Here are 3 blocks of CSS. The 1st is necessary to make the form work. The 2nd is optional CSS for visual styling. The 3rd is another block of optional CSS which will align the buttons to the right side in case you want to place the login/register buttons at the top right corner of your site.

This is necessary CSS for functionality and form structure:

/* Necessary CSS for functionality */

 #isa_loginform, #isa_registerform, #isa_lostpwform {
#isa-hundred-acre-wood, #isa-hundred-acre-wood-field, #isa-hundred-acre-wood-label {
    position: absolute;
    overflow: hidden;
    clip: rect(0px, 0px, 0px, 0px);
    height: 1px;
    width: 1px;
    margin: -1px;
    border: 0px none;
    padding: 0px;
button#lostpw {
    border: none;
    color: inherit;
    background-color: transparent;
    padding-left: 0;
    text-transform: none;
#isa-reset-pw, #isa-register-errors, #isa-register-success, #isa-login-error {
    display: inline-block;
    padding: 10px;
    text-align: left;
    margin: 10px 0px;
    border: 1px solid;
    border-radius: 0.5em;
#isa-register-errors, #isa-login-error {
    color: #D8000C;
    background-color: #FFBABA;
#isa-reset-pw {
#isa-register-success {
#isa_lostpwform {

This is optional CSS for styling. This makes the buttons look just like in the Demo at the top.

/* Optional CSS for styling */

 #isa_loginbutton, #isa_registerbutton {
#isa_loginform input#wp-submit, input#isa-wp-register, #isa_lostpwform input#wp-submit, #isa_loginbutton, #isa_registerbutton {
    cursor: pointer;
    display: inline-block;
    padding: 10px 20px 11px;
    color: #FFF;
    font-family:"Trebuchet MS", Arial, Helvetica, sans-serif;
    font-size: 18px;
    line-height: 1.22em;
    text-transform: uppercase;
    letter-spacing: -1px;
#isa_loginform p, #isa_registerform p, #isa_lostpwform {
#isa_registerform label {
#isa_loginform #user_login, #isa_loginform #user_pass, #isa_registerform #register_user_login, #isa_registerform #register_user_pass, #isa_registerform #register_user_pass_again, #isa_registerform #register_user_email, #user_login {
    max-width: 100%;

The following CSS is optional. It will align the buttons (and forms) to the right side in case you want to place the login/register buttons at the top right corner of your site.

/* Contain login/register buttons to right side */
#isa_loginbutton, #isa_registerbutton,
#isa_loginform, #isa_registerform, #isa_lostpwform{
	float:right; margin:0 2px 2px 2px;

Step 4: Use the template tag where you want to display the login/register buttons

Place this template tag where you want to display the login and register buttons. For example, you can place it in the header.php, near the top of your site, or in your sidebar.

<?php isa_show_login_register(); ?>

See more:


Questions and Comments are Welcome

Your email address will not be published. All comments will be moderated.

Please wrap code in "code" bracket tags like this: