jQuery: taming table-based layouts

Table-based layouts are not dead. In many worst-case scenarios they're still widely used to display web pages. The problem with this kind of layout is that it's practically impossible to tame it only with the aid of CSS. More precisely, CSS could be used to turn table elements into block-level elements but even if you follow this approach you'll probably end up with having many inconsistencies. Here it comes jQuery.

Consider the following layout:


<form action="" id="contact" method="post">
    <table width="100" cellpadding="0" cellspacing="0">
        <tr>
            <td width="20%">
                <label for="name">Name</label>
            </td>
            <td width="60%">
                <input type="text" id="name" name="name" />
            </td>
        </tr>
        <tr>
            <td width="20%">
                <label for="email">Email</label>
            </td>
            <td width="60%">
                <input type="text" id="email" name="email" />
            </td>
        </tr>
        <tr>
            <td width="20%">
                <label for="message">Message</label>
            </td>
            <td width="60%">
                <textarea name="message" id="message" cols="30" rows="30"></textarea>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <p>
                    <input type="submit" id="submit" value="Send" />
                </p>
            </td>
        </tr>
    </table>
</form>

To normalize this layout, a pure CSS approach would be as follows:


#contact table,
#contact tr,
#contact td {
	display: block;
}

#contact tr {
	padding-bottom: 1em;
	overflow: hidden;
}

#contact tr td[width="20%"] {
	float: left;
	width: 25%;
	margin-right: 0.5em;
}

#contact tr td[width="60%"] {
	float: left;
	width: 30%;
}

This approach has its limits: CSS is not able to work with ill-formed HTML structures because it heavily depends on the well-formedness of the DOM structure. jQuery, instead, can overcome these limits by inspecting the contents of each node and act accordingly:


(function ($) {

    $.fn.normalizeForm = function () {
        return this.each(function () {
            var form = $(this);
            var trs = $('tr', form);
            var html = '';

            trs.each(function () {
                var $tr = $(this);
                var $td = $('td', $tr);
                html += '<div class="row">';

                $td.each(function () {
                    html += $(this).html();

                });

                html += '</div>';

            });

            form.html(html);

        });
    };

})(jQuery);

$(function () {
    $('#contact').normalizeForm();

});

The above code entirely replaces the table-based DOM structure with a more CSS-compliant one. As you can see, the final layout is exactly displayed as we wanted.

[view-example url="http://jsfiddle.net/gabrieleromanato/7LnTB/"]
Back to top