css for styling Drupal form labels & fields inline?

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
Matt V.'s picture

Does anyone have a generic CSS rule set for styling Drupal forms so that the field labels appear inline with their fields? I've worked on some projects where forms needed to be styled that way and while I've been able to get them working I've not been overly satisfied with the end result. I'm hoping that someone with more CSS chops might have already conquered the problem and be willing to share their solution.

I wrote a rough proof-of-concept Drupal module to apply Uni-Form CSS markup to Drupal forms, but for a variety of reasons (see "Uni-form Cons" below), it ended up being more kludgey than I had hoped. Does anyone have a more Drupal-specific CSS file, that I might use in the module instead of Uni-Form? If not, is anyone interested in working with me to come up with one?

Uni-form Cons
* Drupal's default form output isn't what Uni-Form expects, so there was a fair amount of theme overriding required.
* The Uni-Form inlineLabel styling doesn't seem to work well for fields with more than 2 or 3 checkboxes or radio buttons.
* Uni-Form's "blockLabels" style is similar to Drupal's default style, so about half of the Uni-Form CSS is superfluous within Drupal.
* Uni-Form is CreativeCommons licensed, so it would have to be downloaded separately.
* Uni-Form also includes a jquery script for highlighting fields, but it requires that the Jquery Update module be applied in order to work properly.

Comments

overriding a theme function

couzinhub's picture

Not only the css can be tweaked, but you can override the way drupal output each form item.

on api.drupal.org, look for the theme function that create the form item :

http://api.drupal.org/api/function/theme_form_element/5

it looks like this :

<?php
function theme_form_element($element, $value) {
 
$output  = '<div class="form-item">'."\n";
 
$required = !empty($element['#required']) ? '<span class="form-required" title="'. t('This field is required.') .'">*</span>' : '';

  if (!empty(
$element['#title'])) {
   
$title = $element['#title'];
    if (!empty(
$element['#id'])) {
     
$output .= ' <label for="'. $element['#id'] .'">'. t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
    else {
     
$output .= ' <label>'. t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
  }

 
$output .= " $value\n";

  if (!empty(
$element['#description'])) {
   
$output .= ' <div class="description">'. $element['#description'] ."</div>\n";
  }

 
$output .= "</div>\n";

  return
$output;
}
?>

Now you just need to drop this into your template.php file, replace 'theme_form_element' by '[name of your theme]_form_element' to activate it for your theme, and adapt the output markup as needed.
Then you can add your custom css :)

The Drupal Agency >> www.raincitystudios.com <<
Me on the Web >> www.couzinhub.com <<

thanks

Matt V.'s picture

Thanks for the response. I was aware of the ability to override theme output, but have you used that technique to output form field labels to appear inline with their fields. If so, do you have any code examples for that? It appears that the code above is the original theme_form_element() function, not an override example.

Also, when doing the overriding at the theme layer like that, is there an easy way to avoid having it rewrite all form output? In most cases, I'd like to avoid overriding Drupal's built-in administration forms.

When you're using a theme

couzinhub's picture

When you're using a theme function, you just define what's going to be output by this function. So if you just need to change the label, find which theme function outputs them, and just twaek it in your template.php.
The thing is that if you only want to modify the template of the label, you have to use the entire theme function that contains the output for the label. You can't, in drupal 5, only decide to modify the label. But the function above is really only for label and descrption, so it's very close to what you want I think.

for example, in the following, I just modify the function so the label is just a span, so it becomes inline :

<?php
function theme_form_element($element, $value) {
 
$output  = '<div class="form-item">'."\n";
 
$required = !empty($element['#required']) ? '<span class="form-required" title="'. t('This field is required.') .'">*</span>' : '';

  if (!empty(
$element['#title'])) {
   
$title = $element['#title'];
    if (!empty(
$element['#id'])) {
     
$output .= ' <span>'. t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</span>\n";
    }
    else {
     
$output .= ' <span>'. t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</span>\n";
    }
  }


$output .= " $value\n";

  if (!empty(
$element['#description'])) {
   
$output .= ' <div class="description">'. $element['#description'] ."</div>\n";
  }


$output .= "</div>\n";

  return
$output;
}
?>

Hi

sudalairajt's picture

Hi,
Can we apply uniform- css to drupal forms.Just i tried it.I am not getting any idea about this.If you don't mine,please send some of the samples.

How I applied uniform-css in drupal themes?

Thanks in advance Matt

Regards,
Raj.

one example...

einsicht@drupal.org's picture

(Tested in Drupal 6)
For a specific field I just use

.field-class label, .field-class
{
  display: inline;
}

For multiple fields you can try replacing .field-class with something more generic, like .form-item. Each field is structured more or less like this:
<div class="form-item" id="edit-field-name-wrapper">
<label for="edit-field-name">Name: </label>
<input maxlength="x" name="name" id="edit-field-name" size="y" value="z" class="form-text" type="text">
</div>

Where "field-name" is your field's name as it appears in the $form (between brackets [ and ]).
You could also prefix and suffix the form element with your class of choice if you have control over the form.

Depending on the needs, I either put the CSS in the theme, or in a separate CSS file and add it in my module only on specific pages. Hope this helps!
I'm no CSS expert, so if anyone has better suggestions, feel free to jump in.

Drupal 5 css version

Mark B's picture

I needed to do this for the user registration form without changing any other forms, and used this CSS:

#user-register label, #user-register .form-text {
  display: inline;
}

#user-register .form-text {
  position: absolute;
  left: 320px;
}

(using Drupal 5.11, tested in FF3 and IE6, not got round to testing IE7 yet)

Hi Matt, I'm just in the

webopius's picture

Hi Matt,

I'm just in the process of styling inline forms using CSS only. Here's what I'm using. This is sized for my particular needs and the only non-standard thing is that description is hidden as I'm using JQuery to show the description when the user hovers over the field.

.form-item {
position: relative;
    display: block;
    width: 100%;
   font-size: 80%;
    padding-top: 3px;
  clear: both;
}

.form-item label {
width: 50%;
   float: left;
   display: inline;
   text-align: right;
}

.form-item .form-text {
  width: 40%;
    float: left;
   margin-left: 10px;
display: inline;
   border: 1px solid #ccc;
}

.form-item textarea {
   clear: both;
   width: 100%;
   display: block;
    font-size: 110%;
   border: 1px solid #ccc;
}

.form-item .description {
   position: absolute;
    left: 10%;
width: 200px;
  display: none;
    background-color: #caff9b;
}

.form-item .form-select {
    margin-left: 10px;
}

Rearranging '*' and title

balsama's picture

What if I wanted the required asterisk (*) to come before the label for the field instead of after?

I thought I could just rearrange the items in the array; e.g.:
change:

<?php
if (!empty($element['#title'])) {
   
$title = $element['#title'];
    if (!empty(
$element['#id'])) {
     
$output .= ' <label for="'. $element['#id'] .'">'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
    else {
     
$output .= ' <label>'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
  }
?>

to:

<?php
if (!empty($element['#title'])) {
   
$title = $element['#title'];
    if (!empty(
$element['#id'])) {
     
$output .= ' <label for="'. $element['#id'] .'">'. $t('!title: !required', array('!required' => $required, '!title' => filter_xss_admin($title))) ."</label>\n";
    }
    else {
     
$output .= ' <label>'. $t('!title: !required', array('!required' => $required, '!title' => filter_xss_admin($title))) ."</label>\n";
    }
  }
?>

But that didn't have any affect. Any ideas?

UPDATE
Doh! Here's the solution for anyone else who is looking:

<?php
if (!empty($element['#title'])) {
   
$title = $element['#title'];
    if (!empty(
$element['#id'])) {
     
$output .= ' <label for="'. $element['#id'] .'">'. $t('!required!title:', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
    else {
     
$output .= ' <label>'. $t('!required!title:', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
    }
  }
?>

That last little block worked

matthewHunt's picture

That last little block worked for me . Thanks.

some jscript is required?

huysonzone's picture

i think :
- api > first required
- css> 2nd
- and need some script to it seem as dynamic and awesome style?
are you sure?

(im just a noob :D)

húyon

kayograco's picture

I'm trying to get this hover and checked effect on my Drupal site's left columns forms.

I've searched all over the web and found:

None of the above could helped me achive it, or, possibly, I'm not reading well!

The code I'm getting with firebug is as follow:

<div>
  <label>
    <input />
  </label>
</div>

What I'm looking for is to syle label when input:checked.

I've read the post, and if I were to rearange my fields... where I have to do it?

Kayo Graco

Interesting solution for D6

bshensky's picture

Here's what worked for us:

  • Add the Form Markup module to your installation. This allows you to shell some HTML of your choice around the form element to be rendered.
  • To your form element, add this Form Markup Prefix: <div class="form-radios-horiz">
  • To the same form element, add this Form Markup Suffix: <div class="clear"></div></div>
  • Add the following CSS to your theme's CSS file - this "floats" the radio buttons in the radio button group (those in which you added the Form Markup tags) so they all stay on a single line:
    .form-radios-horiz .form-item label {
       float: left;
       margin-right: 0.5em;
    }
    .form-radios-horiz .form-item .form-radios .form-item label {
      float: left;
      margin-right: 2em;
    }
    .clear {
        clear: both;
    }
  • Finally, add the following theme override function to your template.php file so that you may target radio groups' labels (the 2 alterations are highlighted below with "!!!")
    function theme_form_element($element, $value) {
      // This is also used in the installer, pre-database setup.
      $t = get_t();

      $output = '<div class="form-item"';
      if (!empty($element['#id'])) {
        $output .= ' id="'. $element['#id'] .'-wrapper"';
      } elseif (!empty($element['#parents'][0])) {
        // !!! supply an alternate div ID for field collections
        $output .= ' id="'. form_clean_id($element['#parents'][0]) .'-wrapper"';
      }
      $output .= ">\n";
      $required = !empty($element['#required']) ? '<span class="form-required" title="'. $t('This field is required.') .'">*</span>' : '';

      if (!empty($element['#title'])) {
        $title = $element['#title'];
        if (!empty($element['#id'])) {
          $output .= ' <label for="'. $element['#id'] .'">'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
        }
        else {
          // !!! New D6 implementation to target aggregate/fieldgroup labels: if the element has no #id, add a class to the label (using the "parent" id to get fieldgroup name)
          $labelClassShim = (empty($element['#parents'][0])) ? '' : ' class="' . $element['#type'] . '-label ' . $element['#type'] . '-label-' . form_clean_id($element['#parents'][0]) . '"';
          $output .= ' <label' . $labelClassShim . '>'. $t('!title: !required', array('!title' => filter_xss_admin($title), '!required' => $required)) ."</label>\n";
        }
      }

      $output .= " $value\n";

      if (!empty($element['#description'])) {
        $output .= ' <div class="description">'. $element['#description'] ."</div>\n";
      }

      $output .= "</div>\n";

      return $output;
    }
  • Now, you can target the labels of radio (and other field-collection) groups within CSS, and set their individual widths accordingly:
    .radios-label-field-some-fieldname {
      min-width: 10em;
    }

I'm still working on how to get labels to wrap when the text exceeds a certain width.

For D7 I used

MickC's picture

For D7 I used this for views - maybe helpful for someone:
.views-label {font-weight:bold; float-left;margin-right:5px;}

The usual problem is that the

alexrayu's picture

The usual problem is that the labels, when placed inline, have different width, thus making the forum look ugly. To correct the mickC's code:

.views-label {
  font-weight: bold;
  float: left;
  margin-right: 5px;
  width: 200px;
  /* width: 64em; */
}

Inline labels

aggentle's picture

Another great thread that has solved the problems with my D7 site. Thanks to allow.

Overriding the standard "label" tag for inline labels affects all the labels, and generally screws up login forms, admin forms and so on. I wanted to override the labels on my customised node forms only.

Einschit's solution above worked for me. Instead of overriding "label", I overrode .xxx label in the template css file, using Firebug to identify the label names and the associated fields.

For example, this gives a nicely aligned set of edit fields for my node.

.form-item-title label,
.form-item-field-status-und label,
(...etc...)
{
  margin-top: 0em;
  clear: none;
  float: left;
  width: 10em;
  display:inline;
}

This will help for a specific

alexrayu's picture

This will help for a specific form where you know the width of the labels. Otherwise, will have to have fingers crossed that the label text does not stretch further than the 10em. Which criticism also applies to my response above, of course.

Agreed

aggentle's picture

The width depends on the label size and needs to be checked. But this should be a "once-only" design decision?

Unless client will create forms

alexrayu's picture

It may change if you are building a website for the client, who will want to add more forms. But that is a separate occasion that will need to be treated separately, I agree.

Theme development

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: