Pretty Forms with CSS & jQuery

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?

UglyForm

<!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.

LessUglyForm

<!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.

OkayForm

<!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.

PrettyForm

<!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>
Advertisement

Author: Adam Prescott

I'm enthusiastic and passionate about creating intuitive, great-looking software. I strive to find the simplest solutions to complex problems, and I embrace agile principles and test-driven development.

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: