Let’s say you’re making a web form. You want it to look nice, so you’d like the input controls to line up and be consistently sized. You know that you shouldn’t be using tables for formatting, but how else can you avoid creating an ugly mess of labels smushed-up against their controls?
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <script type="text/javascript"></script> <style type="text/css"></style> </head> <body> <div> <label for="name">Name:</label><input type="text" name="name"/><br/> <label for="email">Email:</label><input type="text" name="email"/><br/> <label for="password">Password:</label><input type="password" name="password"/><br/> <label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/><br/> <label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/> </div> </body> </html>
I found a cool trick to fix the spacing of labels and controls using jQuery. The idea is simple: loop through all labels and set their widths equal to the widest. The logic to do this is a typical CS-101 find-the-max loop, but there’s also a not-so-obvious second step. In order for the widened labels to display, they must be floated to the left.
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <script type="text/javascript"> $(function() { var max = 0; $("label").each(function () { if ($(this).width() > max) max = $(this).width(); }); $("label").width(max + 5); }); </script> <style type="text/css"> label { float: left; } </style> </head> <body> <div> <label for="name">Name:</label><input type="text" name="name"/><br/> <label for="email">Email:</label><input type="text" name="email"/><br/> <label for="password">Password:</label><input type="password" name="password"/><br/> <label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/><br/> <label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/> </div> </body> </html>
Fixing the label spacing helps, but it’s still pretty ugly. You don’t want the textboxes rubbing shoulders like that, and why are the password boxes slightly shorter than the textboxes? We can fix both of those items with some simple CSS.
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <script type="text/javascript"> $(function() { var max = 0; $("label").each(function () { if ($(this).width() > max) max = $(this).width(); }); $("label").width(max + 5); }); </script> <style type="text/css"> label { float: left; } input { margin: 2px; } [type=text], [type=password] { width: 150px; } </style> </head> <body> <div> <label for="name">Name:</label><input type="text" name="name"/><br/> <label for="email">Email:</label><input type="text" name="email"/><br/> <label for="password">Password:</label><input type="password" name="password"/><br/> <label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/><br/> <label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/> </div> </body> </html>
Okay, now we’re starting to look like a respectable form! We can make our form a little nicer by adding a fieldset control to house our controls, and we can add a label to controls through the fieldset’s legend. In order to facilitate auto-sizing of the fieldset–it’s 100% width by default–I moved the labels and inputs into a list, and that required another jQuery loop and some CSS. As final step, add more CSS to further improve aesthetics. For this example, I added a custom web font and made the fieldset legend bold and red.
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script> <script type="text/javascript"> $(function() { var max = 0; $("label").each(function () { if ($(this).width() > max) max = $(this).width(); }); $("label").width(max + 5); max = 0; $("fieldset").each(function() { $(this).find("li").each(function () { var w = $(this).find("label").width() + $(this).find("input").width(); if (w > max) max = w; }); $(this).width(max + 10); }); }); </script> <link href='http://fonts.googleapis.com/css?family=Unkempt' rel='stylesheet' type='text/css'> <style type="text/css"> body { font-family: 'Unkempt', sans-serif; } fieldset { margin: 10px; padding: 10px; } fieldset legend { font-weight: bold; color: maroon; } fieldset ul { margin: 0; padding: 0; } fieldset li { list-style: none; padding-bottom: 10px; } label { float: left; } input { margin: 2px; } [type=text], [type=password] { width: 150px; } </style> </head> <body> <fieldset> <legend>User Info</legend> <ul> <li><label for="name">Name:</label><input type="text" name="name"/></li> <li><label for="email">Email:</label><input type="text" name="email"/></li> <li><label for="password">Password:</label><input type="password" name="password"/></li> <li><label for="confirmPassword">Confirm:</label><input type="password" name="confirmPassword"/></li> <li><label for="newsletter">Email me about stuff!</label><input type="checkbox" name="newsletter"/></li> </ul> </fieldset> </body> </html>