Last updated September 27, 2012. Created on April 2, 2005.
Edited by forestmars, larowlan, arianek, aufumy. Log in to edit this page.

This seems to be a duplicate (albeit earlier) page

Please see http://drupal.org/node/350634 which is more recent and more accurate.


Description

These snippets allow you to override the default login layout using a custom user_login.tpl.php.

If you want to customize the full page layout, click through to the Customizing the login, registration and request password full page layout handbook page.

Step 1 of 2

In a text editor like notepad.exe, create a file called template.php using the the following snippet. If you already have a template.php file, simply add it to your existing one.

For use with Drupal 4.7.x and Drupal 5.x

<?php
 
/**
   * This snippet catches the default login form and looks for an
   * user_login.tpl.php file in the theme folder
   */

function phptemplate_user_login($form) {
    return
_phptemplate_callback('user_login', array('form' => $form));
}
?>

For use with Drupal 6.x

_phptemplate_callback is deprecated in Drupal 6 in favor of the theme registry and preprocess functions. See the Drupal 6 theme guide for more information.

<?php
function mytheme_theme(&$existing, $type, $theme, $path) {
 
$hooks['user_login'] = array(
   
'template' => 'templates/user_login',
   
'arguments' => array('form' => NULL),
   
// other theme registration code...
 
);
  return
$hooks;
}

function

mytheme_preprocess_user_login(&$variables) {
 
$variables['intro_text'] = t('This is my awesome login form');
 
$variables['rendered'] = drupal_render($variables['form']);
}
?>

For use with Drupal 7.x

Form variables are declared as render elements in hook_theme functions that handle form or element theming. See the hook_theme API documentation for more information.

<?php
function mytheme_theme(&$existing, $type, $theme, $path) {
 
$hooks['user_login'] = array(
   
'template' => 'templates/user_login',
   
'render element' => 'form',
   
// other theme registration code...
 
);
  return
$hooks;
}

function

mytheme_preprocess_user_login(&$variables) {
 
$variables['intro_text'] = t('This is my awesome login form');
 
$variables['rendered'] = drupal_render_children($variables['form']);
}
?>

Step 2 of 2

  1. In a text editor paste the following snippet into your user_login.tpl.php file
  2. Edit the style sheet classes and content to suit
  3. Upload your edited user_login.tpl.php to your active theme folder

For use with Drupal 4.7.x

<div class="login_form"><p>Extra login instructions can go here, just above the Login form</p>
<?php
   
print form_render($form); // this displays the login form.
?>

<p>Extra login instructions can go here, just below the Login form</p>
</div>

For use with Drupal 5.x

<div class="login_form"><p>Extra login instructions can go here, just above the Login form</p>
<?php
   
print drupal_render($form); // this displays the login form.
?>

<p>Extra login instructions can go here, just below the Login form</p>
</div>

For use with Drupal 6.x/7.x

<p><?php print $intro_text; ?></p>

<div class="my-form-wrapper">
  <?php print $rendered; ?>
</div>

Style sheet reference

For controlling how your login form looks using your style sheet, this is what the rendered login form HTML and class names are by default:

<div class="form-item">
<label for="edit-name">Username: <span class="form-required" title="This field is required.">*</span></label>
<input type="text" maxlength="60" name="name" id="edit-name"  size="30" value="" tabindex="1" class="form-text required" />
<div class="description">enter your username</div>
</div>
<div class="form-item">
<label for="edit-pass">Password: <span class="form-required" title="This field is required.">*</span></label>
<input type="password" name="pass" id="edit-pass"  size="40"  tabindex="2" class="form-text required" />
<div class="description">enter your password</div>
</div>
<input type="hidden" name="form_id" id="edit-user-login" value="user_login"  />
<input type="submit" name="op" id="edit-submit" value="Log in"  tabindex="3" class="form-submit" />
<p><a class="textlink" href="?q=user/password">Forgotten your Password?</a></p>

Notes

  • A more advanced login form override (4/5/6 only)
  • Recommended reading for more information and an explanation of how the snippets work: Dominating the User Login Form at Nick Lewis' blog
  • If you have an even more advanced snippet that has been tested, please add a child page to this handbook page
  • This snippet was tested with Drupal 5.x (June 24th 2007) by Dublin Drupaller (Note: If you have the locale.module enabled you may need to refresh your search_index by editing any text string related to the user page before your changes take effect, such as 'password'. )

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

lavignej’s picture

I had to change "user_login" to "user_login_block" to get it to work.

<?php
function mytheme_theme() {
  return array(
   
'user_login_block' => array(
     
'template' => 'user_login',
     
'arguments' => array('form' => NULL),
    ),
   
// other theme registration code...
 
);
}

function

mytheme_preprocess_user_login_block(&$variables) {
 
$variables['intro_text'] = t('This is my awesome login form');
 
$variables['rendered'] = drupal_render($variables['form']);
}
?>

Note that the template also needed to be "user_login" instead of "user-login".

sepp68’s picture

Thx. Works great. I manipulate also the Username and Password Input-Field in this way: (I Think this is very useful !)

<?php
function mytheme_preprocess_user_login_block(&$variables) {


 
$variables['form']['name']['#value'] = $variables['form']['name']['#title'];
 
$variables['form']['pass']['#value'] = $variables['form']['pass']['#title'];

 
$variables['form']['name']['#attributes']['OnClick'] = 'this.value=""';
 
$variables['form']['pass']['#attributes']['OnClick'] = 'this.value=""';

 
$variables['form']['name']['#required'] = false;
 
$variables['form']['pass']['#required'] = false;



 
$variables['rendered'] = drupal_render($variables['form']);
}
?>

Greetings

Sepp

Rosamunda’s picture

Probably I´m doing something wrong here, but it just won´t work.
I´ve created the tpl, added the code inside the template, and the form shows exactly the same.
I haven´t changed the style.css yet, but the code should at least show the intro_text $variables['intro_text'] = t('This is my awesome login form');.
I´ve try disabling and enabling again the login block, and clearing all cache... with no luck.
It´s probably a silly mistake... but cannot get this to actually work.
I´ve tried the alternative solutions above too (the ones commented above).
Thanks for your help.

Rosamunda
Buenos Aires | Argentina

s4j4n’s picture

Rosamunda,

I got it to work (i.e. I now see "This is my awesome login form") by...

1. using lavignej's directions (i.e. renaming mytheme_preprocess_user_login to mytheme_preprocess_user_login_block)

2. renaming the user_login.tpl.php file to user-login.tpl.php

cheers
-Rob

ivpoed’s picture

Thanks!!! It works!

urban farmer’s picture

Thanks Sepp68. This worked great for setting that value of the name input field to "username", but I cannot get "password to show up in the password input field. When I look at the page in firebug, there is no value for pass. What am I doing wrong? how can I fix this?

suntog’s picture

Sepp

This is a great! I added one more line of code to make 'Username' reappear if left blank.

<?php
function mytheme_preprocess_user_login_block(&$variables) {


 
$variables['form']['name']['#value'] = $variables['form']['name']['#title'];
 
$variables['form']['pass']['#value'] = $variables['form']['pass']['#title'];

 
$variables['form']['name']['#attributes']['OnClick'] = 'this.value=""';
 
$variables['form']['pass']['#attributes']['OnClick'] = 'this.value=""';

 
//"Username" reappears in username input if left blank
 
$variables['form']['pass']['#attributes']['OnBlur'] = "if (this.value=='') this.value='Username'";

 
$variables['form']['name']['#required'] = false;
 
$variables['form']['pass']['#required'] = false;

 

 
$variables['rendered'] = drupal_render($variables['form']);
}
?>
ericxb’s picture

Thanks to Addison Berry at Lullabot, you can accurately get the proper ID by looking for a hidden input with the name "form_id" in the generated source:

<input type="hidden" name="form_id" id="edit-user-login-block" value="user_login_block"  />

Not to be confused with the id of the form tag itself.

Her article: Modifying Forms in Drupal 5 and 6

Eric W. Bates

Nagyman’s picture

user_login_block and user_login are two different hooks. user_login_block is for the block, and user_login is for your /user/ login page. You can point both hook registrations at the same template if you like and just differ the content (example below). Note: I found I had to clear the Drupal cache to see my changes.

It also doesn't matter what you name your template as long as it matches the file name:

user-login -> user-login.tpl.php
shiver-me-timbers -> shiver-me-timbers.tpl.php
<?php
function mythemename_theme()
{
  return array(
   
'user_login_block' => array(
     
'template' => 'user-login',
     
'arguments' => array('form' => NULL),
    ),
   
'user_login' => array(
     
'template' => 'user-login',
     
'arguments' => array('form' => NULL),
    ),
   
// other theme registration code...
 
);
}

function
mythemename_preprocess_user_login_block(&$variables)
{
 
$variables['intro_text'] = t('This is my awesome login BLOCK');
 
$variables['rendered'] = drupal_render($variables['form']);
}

function
mythemename_preprocess_user_login(&$variables)
{
 
$variables['intro_text'] = t('This is my awesome login PAGE');
 
$variables['rendered'] = drupal_render($variables['form']);
}
?>
scifisi’s picture

There's a good tut I came across here:

http://www.caspianit.co.uk/drupal-6-custom-login-form/

urban farmer’s picture

I had to make these changes as well to get it to work in D7. Also be sure you put user_login.tpl.php in your themes template folder.

dylanrao’s picture

Hey lavignej,

I'm trying to use this code to change the order of my login block fields in a template file. I have the look I'm going for by using this for my template.php

<?php
function austinart_theme() {
  return array(
   
'user_login_block' => array(
     
'template' => 'user_login',
     
'arguments' => array('form' => NULL),
    ),
   
// other theme registration code...
 
);
}

function
austinart_preprocess_user_login_block(&$variables) {
 
$variables['username'] = drupal_render($variables['form']['name']);
 
$variables['password'] = drupal_render($variables['form']['pass']); 
 
$variables['submit'] = drupal_render($variables['form']['submit']); 
 
$variables['links'] = drupal_render($variables['form']['links']); 
}
?>

and this for my user_login.tpl.php:

<?php
<div class="my-form-wrapper">
  <?
php print $links;
?>
<?php
 
print $username;
?>
<?php
 
print $password;
?>
<?php
 
print $submit;
?>

?>

which works for the display that I want except by dropping $variables['rendered'] the submit action doesn't actually work. Can anyone help me get the right display order without losing the functionality?

sunset_bill’s picture

Since we're customizing the login block, here are a couple useful things I found while doing my first one.

I wanted my login in a nice, tight block, but the default form layout had too much vertical space. While there seem to be plenty of tips for putting the login in a nifty bar layout, I didn't find anything for theming a box, so here's the CSS I came up with. This fits my login form in an area 200px wide by 100px high (with a font size of 12px, that is), with plenty of room for Register and Forgot Password? links below the login button (see http://rageagainstthecubefarm.com).

/* put prompts on same line as fields */
#user-login-form label, #user-login-form input, #user-login-form .form-item, #edit-name, #edit-pass { display : inline; } 
#block-user-0 h2, #user-login-form .item-list { display : none; }
#user-login-form { text-align : right; }
#user-login-form input { font-size : 0.9em; }
#user-login-form .form-text { width:120px; }   /* sets the field widths */
.form-submit, #edit-submit {      /* puts the login button right under the password field */
  margin-top:0;
}

Second useful thing is more of a newbie trap. Since we're hooking into Drupal's own user_login block, we get the default behavior, which is that the login block just goes away on a successful login. Very discouraging when you've finally gotten your first custom-themed login working and suddenly find yourself with a blank space where you don't want one. Getting something to replace the login form, like a Welcome message with links to log out or the user's account, is a simple matter of going to Admin > Site Building > Blocks, creating a new block with the desired content and putting it in the same region as the login block.

salud,
Bill

PS--Correction, 14 Feb: I should have mentioned this is in a theme based on Frameworks. Element names for Zen and other themes will likely be different. For your theme, do a View Source to see the HTML for your login form and change element names accordingly. Sorry about that.

seutje’s picture

for Drupal 5

I often get the request from my clients to put the links above the textfields (can't rly blame them as it's a little bit more logical)

anyway, the solution is pretty easy, like described above set it to use a user_login.tpl.php and then inside that file, use this:

<?php
 
print drupal_render($form['links']); // renders only the links
 
$form['links'] = array(); // set the links to an empty array
 
print drupal_render($form); // this displays the rest of the login form
?>

you could add a check to see if $form['links'] is already an empty array (like on the /user page) and avoid a useless call to the drupal_render function, but it isn't rly needed that bad unless u need every drop of performance u can get

brendoncrawford’s picture

If you want more exact control in Drupal 6, here is a good reference..

http://thefaultandfracture.blogspot.com/2009/04/theming-drupal-user-logi...

doors’s picture

The shows but the rest of the form shows nothing.

The $rendered variable is empty. Why is that?

I added $variables['display_form'] = $variables['form']; and use print_r and it shows all the variables and even prints out the form but

$variables['rendered'] = drupal_render($variables['form']); with the drupal_render() function the variable becomes empty.

Is there something wrong with drupal_render()?

doors’s picture

I had to make the following changes to the preprocess function:

function mytheme_preprocess_user_login(&$variables) {
$variables['intro_text'] = t('This is my awesome login form');
$variables['rendered'] = $variables['form'];
$variables['display_form'] = drupal_render($variables['rendered']);
}

And print the $variables['display_form'] variable instead of the $variables['rendered'].

webcomm’s picture

That worked for me too, doors. Though I can't imagine why the intermediary $variables['rendered'] is necessary here. From a PHP standpoint it makes no sense that I can see.

acquixada’s picture

hi, folks
the snippet never worked, for some reason, so i removed all the code and deleted user-login-block.tpl.php, but now drupal gives me the following error message, right on the content area:

"warning: include(./sites/all/themes/aboutpeople/user-login-block.tpl.php) [function.include]: failed to open stream: No such file or directory in /Users/ACQM/Sites/trabalhos/drupaltrilha/includes/theme.inc on line 1066.
warning: include() [function.include]: Failed opening './sites/all/themes/aboutpeople/user-login-block.tpl.php' for inclusion (include_path='.:/Applications/MAMP/bin/php5/lib/php') in /Users/ACQM/Sites/trabalhos/drupaltrilha/includes/theme.inc on line 1066."

if i create the tpl file, the message goes away, but i cannot see the login block; if i delete the file, i see the login block, but the message shows up. any idea?
thanks,
antonio

vkersten’s picture

For those looking for a solution where you have only private pages on your site:
http://drupal.org/project/customerror
totally does the job!

awasson’s picture

After reading through this a fair bit I have come to the conclusion that many of the Drupal 6 comments are aimed at the login block that you can add to your site in the blocks administration section whereas there isn't a clear definition about how to modify the regular login form on the login page at: /user

This is my attempt at solving this dilema but I wouldn't have figured it out without all of the examples that are laid out before me on this thread.

PART #1
Make a template.php file in your theme or add the following to the existing one:
(change mytheme to the name of your theme)

function mytheme_theme() {
  return array(
    'user_login' => array(
      'template' => 'user-login', // This refers to the template "user-login.tpl.php".
      'arguments' => array('form' => NULL),
    ),
    // any other theme registration code if necessary...
  );
}

function mytheme_preprocess_user_login(&$variables) {

  //Make the form fields "size = 35"
  $variables['form']['name']['#size'] = 35;
  $variables['form']['pass']['#size'] = 35;

  //Add some sweet intro text
  $variables['intro_text'] = t('Welcome to the MY-WEBSITE member's section. Please use the fields below to login.');
  $variables['rendered'] = drupal_render($variables['form']);
}

PART #2
Create a file called user-login.tpl.php and add the following to it:

<p><?php print $intro_text; ?></p>

<div class="my-form-wrapper">
  <?php print $rendered; ?>
</div>

Now go to your /admin/settings/performance and clear the cache.

All we've done so far is added some text to the form and changed the size from the default 60 to 35 but armed with this you can do much much more.

iparsin’s picture

Thank you for this post. This is working great.

coolesting’s picture

In drupal 7,
error message:" Notice: Undefined index: render element in theme() (line 811 of /var/www/dp/includes/theme.inc) "

Step one , My template.php

<?php
 
//.......
function mysim_theme(){
    return array(
       
'user_login_block' => array(
           
'template' => 'templates/user-login',
           
'arguments' => array('form' => NULL),
        ), 
    ); 
}

function
mysim_preprocess_user_login_block(&$variables){
   
//$variables['form']['name']['#sive'] = 40;
    //$variables['form']['pass']['#sive'] = 35;

   
$variables['intro_text'] = t('This is my awesome login form.');
   
$variables['rendered'] = drupal_render($variables['form']);                
}



 
// The sign below is nothing in my file.    
?>

Step two, the file : templates/user-login.tpl.php

   <p> <?php print $intro_text; ?></p>                                        
   <div class="my-form-wrapper">
    <?php print $rendered; ?>
   </div>

What happen to this ?

larowlan’s picture

you need

<?php
//.......
function mysim_theme(){
    return array(
       
'user_login_block' => array(
           
'template' => 'templates/user-login',
           
'render element' => 'form',
        ),
    );
}
?>

Lee Rowlands

--author="larowlan <larowlan@395439.no-reply.drupal.org>"
Sameo’s picture

Why I'm getting:

Notice: Undefined variable: intro_text in include()
Notice: Undefined variable: rendered in include()

??

charl.souma’s picture

HI

I am following these steps, working on the active theme. After I refresh my site I get a empty browser window. I am adding the snippet at the end of the template and ommitting the php tags. I have confirmed that the tpl naming is the as the templates/user_login. Using Drupal 7.9 and sky theme.

choitz’s picture

Fairly straight forward solution:
http://www.victheme.com/blog/drupal-7-creating-horizontal-login-bar-with...

Both functions go into template.php while

<?php
 
print login_bar ();
?>

works in page.tpl.php.

Hopefully will stop you having to try various more complex methods.

clem.chuang@gmail.com’s picture

In drupal 7, just create a file named 'block--user--login.tpl.php' in your theme folder, and filled in whatever you want.

suntog’s picture

The password input is hide protected, but if you are willing to use a bit of jQuery and CSS you can place the label over the input field and accomplish the same thing. (see http://blog.stannard.net.au/2011/01/07/creating-a-form-with-labels-insid... for a more complete tutorial).

Set the to position:absolute and its container to position:relative. (You can adjust the position of the label within the input field using CSS top and left values for ).

For D7 I believe the password login label container has classes .form-item and .form-item-pass, so in CSS set the following styles:

#user-login-form div.form-item { position: relative; }
#user-login-form label { position: absolute; top: 2px; left: 5px; }

Then place this jQuery Script somewhere your page can get to it:

$(document).ready(function(){

// Find each of our input fields
var fields = $("form.login input");

// If a field gets focus then hide the label
// (which is the previous element in the DOM).
fields.focus(function(){
$(this).prev().hide();
});

// If a field loses focus and nothing has
// been entered in the field then show the label.
fields.blur(function(){
if (!this.value) {
$(this).prev().show();
}
});

// If the form is pre-populated with some values
// then immediately hide the corresponding labels.
fields.each(function(){
if (this.value) {
$(this).prev().hide();
}
});

});
If you are using the devel modules you may need to be more specific about your elements in jQuery, spcifically $(this).prev(). may take you to the wrong tag if you are in devel mode.
Now you have hidden-unhidden text in your password input field. It worked for me.

szt’s picture

This is my working solution for D7:

(function($) {

$(document).ready(function(){

// Find each of our input fields
var fields = $("#user-login-form input");

// If a field gets focus then hide the label
// (which is the previous element in the DOM).
fields.focus(function(){
$(this).prev().hide();
});

// If a field loses focus and nothing has
// been entered in the field then show the label.
fields.blur(function(){
if (!this.value) {
$(this).prev().show();
}
});

// If the form is pre-populated with some values
// then immediately hide the corresponding labels.
fields.each(function(){
if (this.value) {
$(this).prev().hide();
}
});

});

}(jQuery));

gravious’s picture

To see which template is used by a page go to include/theme.inc.
Look for the following code at the bottom of function function theme($hook, $variables = array()):

<?php
   
// Render the output using the template file.
   
$template_file = $info['template'] . $extension;
    if (isset(
$info['path'])) {
     
$template_file = $info['path'] . '/' . $template_file;
    }
   
$output = $render_function($template_file, $variables)
?>

Add an echo $template_file like this:

<?php
   
// Render the output using the template file.
   
$template_file = $info['template'] . $extension;
    if (isset(
$info['path'])) {
     
$template_file = $info['path'] . '/' . $template_file;
      echo
$template_file;
    }
   
$output = $render_function($template_file, $variables)
?>

It will show what template file the page is using. If you've made a new template you may have to clear the cache as explained in Drupal 7 Theme Hook Suggestions of the theme guide.

For small theme changes in the login, register and password reset pages I go to page.tpl.php and use:

<?php if(!$logged_in) { ?>
    <b>only on the login, register and password reset page</b>
<?php } ?>

To disable the default CSS for anonymous users and on the front page (page--front.tpl.php) edit [theme_name]_preprocess_html in template.php:

<?php
function [theme_name]_preprocess_html(&$vars) {
    if (!
$vars["is_front"] && $vars["logged_in"]!=null) {
     
// Add conditional CSS for IE8 and below.
     
drupal_add_css(path_to_theme() . '/ie.css', array('group' => CSS_THEME, 'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE), 'weight' => 999, 'preprocess' => FALSE));
    }
}
?>
yokosatan’s picture

I theme the log in block and i found something that might useful for new drupal developer.

To change the text of "Username", "Password", and "Log in" I put the following this into template.php in function theme_preprocess_user_login_block(&$variables):

  $variables['form']['name']['#title'] = 'TestUsername';
  $variables['form']['pass']['#title'] = 'TestPassword';
  $variables['form']['submit']['#value'] = 'TestLogin';

Hope this help :)

And I have one question: I want to make the size of the log in block smaller, what should I do? CSS?

Thank you