Justify elements using jQuery and CSS

July 9, 2008

When creating a web form you have to make a functional and visually aligned layout. The simplest way to do this is to place elements in a table or by fixing width of labels. Tables stretch its cells according to width of largest element in a column. That way you can have aligned form. Fixing label width will also also allow you to have a hard-coded but aligned form.

But…

But what if you don't want to use tables? Or what if you don't know how long labels could be because you are developing an application that has many localized strings? And you still want to align input elements according to the width of the longest label?

Then you can justify all labels. By justifying I mean to make them same width. And the simplest way to do this is to use jQuery.

If you create a simple web form like in the example below all you have to do is to set float:left and display:block for both label and input field.

without justify

These are the CSS styles:

label, input[type="text"]{
    float:left;
    display:block;
}
label
{
    margin-right: 5px;
}
.field{
    width:100%;
    overflow:auto;
    margin:5px 0px;
}

Looks familiar? Usually, you would set the width of labels to some number, let's say 100px. But, let's do another thing. Let's calculate the width of a largest label and apply it to all labels. jQuery function below does exactly what I wrote:

$(document).ready(function() {
    var max = 0;
    $("label").each(function(){
        if ($(this).width() > max)
            max = $(this).width();   
    });
    $("label").width(max);
});

And visually it looks like this:

with justify

Conclusion

It's easy to do many tricks using jQuery and this was just one of them. Maybe there are simplest solutions to do this, but it was fun to see putting jQuery in most common scenarios like this one.

Let's discuss this on twitter.

30 Comments

  • Muhammad Mosa (July 9, 2008)

    Nice easy trick Janko!
    Good one

  • Joel Carlson (July 9, 2008)

    Very cool, I love simple solutions to annoying problems.

  • Mark Kordon (July 10, 2008)

    Really nice. Good trick :o)

  • Loga (July 10, 2008)

    Very nice.. Its looks awesome…

  • DailyCoding (July 11, 2008)

    great trick.. thanks!!

  • Andrew (July 11, 2008)

    cool solution. don’t you find that although this works, it can sometimes cause the page to annoyingly re-gig if a resource, such as a script, takes long to load and causes onready to fire some time after the browser has already rendered the page?

  • Alex (July 11, 2008)

    Andrew: if you use $(document).ready(function() { … }); or plain $(function() { … }); in jQuery, the script will be executed the moment the DOM is ready. This means the script to be executed does not need to wait for all resources like external scripts and images to be loaded (unlike the standard window.onload event), so the "re-gig" should not be observable mostly.

  • Alex (July 11, 2008)

    Another observation: you might have different fieldsets or forms which need their own alignment on the same page with differing label widths. A nice way to implement this would be to add an "align-labels" class to the form/fieldset/whatever and run your script this way:

    $(document).ready(function() {
    $(‘.align-labels’).each(function(container) {
    var max = 0;
    $("label", container).each(function(){
    if ($(this).width() > max)
    max = $(this).width();
    });
    $("label",container).width(max);
    });
    });

  • Janko (July 11, 2008)

    @Andrew: Actually, Alex answered correctly.

    @Alex: That should absolutely be the case in a production code. This was only for the example :)

  • sa (July 12, 2008)

    Cool, but you I would rather align labels to the right http://www.smashingmagazine.com/2008/07/04/web-form-design-patterns-sign-up-forms/

  • Janko (July 15, 2008)

    @sa: it’s a matter of choice and preferences. You can read my past article on this: http://www.jankoatwarpspeed.com/post/2008/06/06/Building-a-better-web-forms-Labels-in-form-layouts.aspx (pay attention on additional links I provided there) ;)
    In this case, it really doesn’t matter how would you align labels; whatever you chose, you’ll still have to justify them if you wish to create this effect.

  • Brian (August 19, 2008)

    Thanks for the idea, but I took it a step further to make it more generic and made it a plug-in. This way you can apply it any element, class or id:

    $(‘label’).autoWidth();

    To make the labels flexible, but not to go beyond a fixed width (so to not break a layout), just pass a max/limiting width you don’t want them to go beyond:

    $(‘label’).autoWidth({limitWidth: 350});

    jQuery.fn.autoWidth = function(options)
    {
    var settings = {
    limitWidth : false
    }

    if(options) {
    jQuery.extend(settings, options);
    };

    var maxWidth = 0;

    this.each(function(){
    if ($(this).width() > maxWidth){
    if(settings.limitWidth && maxWidth >= settings.limitWidth) {
    maxWidth = settings.limitWidth;
    } else {
    maxWidth = $(this).width();
    }
    }
    });

    this.width(maxWidth);
    }

  • Janko (August 19, 2008)

    Brian, that is great, thanks for sharing this!

  • Chris (August 26, 2008)

    Would be nice to see how you could do this with a multi-column form layout…

    Everything I’ve tried fails especially when you have real-time validation.

    I’ve restorted to tables with four <td>s (label, field, label, field).

  • http://css-edge.blogspot.com (August 28, 2008)

    Thanks for sharing!

  • Janko (August 28, 2008)

    Chris, if I understand correctly that shouldn’t be a problem. You can use left floating divs for colomns and place content inside.

  • artlover (August 30, 2008)

    hey, it is gRrrReat! you really saving life :)

    but there is sth, isnt it working at InternetExplorer? or am I doing sth wrong? it is working great at firefox, but not at IE…

  • kaerast (August 31, 2008)

    Can you give the html code you used to generate the form? When I try this I get a linebreak between the label and the input, and not one between the input and the next label.

  • Janko (August 31, 2008)

    @artlover: it works in IE 7 and FF. I don’t know about IE6, I am not supporting that browser anymore.

    @kaerast: html code could be done this way:

    <fieldset>
    <label for="txtName" class="fieldLabel">Name</label>
    <input typ="text" ID="txtName" class="fieldInput" />
    </fieldset>

    or (althought it is not that clean)

    <label for="txtEmail" class="fieldLabel">Email address</label>
    <input typ="text" ID="txtEmail" class="fieldInput"/><br />

  • artlover (September 2, 2008)

    @Janko: thanks for reply. yes I tested at IE6, still there are many people who use IE6, so I need to sort this out somehow.

    thanks anyway for this great solution :)

  • GamesNow (September 10, 2008)

    Thanks …. great example. Comes in handy when you’ve got lots of forms to style and align. Made a couple of functions starting from your example and started using them on a couple of projects …so far I’ve tested them in IE6, IE 7, FireFox 2, 3 , Google Chrome and Safari for Win ….and no problem.

  • MikeyJ (September 18, 2008)

    Cool concept! Unfortunately, I must be missing something because I can’t get it to work. I feel like the example is a little incomplete without showing the html code for the form that matches the example given for the css and js. I know that near the bottom of the comments someone says the same thing but the example given there doesn’t match the code up top.

    Thx!

  • Webdesign Grafische Vormgeving (September 22, 2008)

    Nice solution, thanks!

  • Wardell (January 13, 2009)

    Nice tutorial. I’m gonna sit down and familiarize my self with jQuery syntax one of these days.

  • Luis (February 4, 2009)

    This is great, but when I use "width:100%" on .field the text inputs get below the labels. What am I doing wrong?
    This is my code, I’ve set a class to the fieldset so the script and styles only apply to this part of the site.
    [quote]
    <fieldset class="form_registro">
    <label for="nombre">Nombre</label><input id="nombre" name="nombre" class="field" type="text" />
    <label for="apellido">Apellido</label><input id="apellido" name="apellido" class="field" type="text" />
    </fieldset>
    [/quote]

  • Firmino (March 3, 2009)

    Congratulations, a simple solution to a problem of routine! :D

  • brianzet (June 28, 2009)

    Very nice indeed, I like it.

  • Miwark (July 17, 2009)

    Thanks for your script, this was a good starting point for me !
    Il have change it a bit to have alignment different in each fieldset of a form :

    === css ===
    fieldset label {
    float: left;
    text-align: right;
    }

    === jquery script ===
    $(function() {
    maxi = 0
    $("fieldset").each(function() {
    $(this).find("label").each(function() {
    width = $(this).width()
    if (width > maxi) {
    maxi = width
    }
    });
    $(this).find("label").width(maxi);
    maxi = 0
    });
    });

    One important point is to use label before input like this :
    <label for="a_field">Field :</label> <input id="a_field" name="a_field" type="text" />

    and avoid this :
    <label for="a_field">Field : <input id="a_field" name="a_field" type="text" /></label>
    Wich will may breack things

  • Ben (August 26, 2009)

    Great trick, tables seem like the obvious option here but this works much better.

  • Ken (November 11, 2009)

    Nice trick! Thanks! :) It’s still hard for me to understand jquery but anyway this kind of tutorials help me a lot.