Search the blog

Getting content to align vertically can be a problem in HTML (without using tables). Here’s a nice method that uses JQuery; all you need to do is add a class name to your element and the script does the rest. This doesn’t rely on display: inline-block or display: table-cell so works great across all browsers.

For the impatient, here’s the complete code:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>vAlign Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<style media="all">

body, html {

    height: 100%;
    margin: 0;

}

</style>
<script>

$(function() {

    $('.valignmiddle').each(function() {

        $(this).parent().css('position', 'relative');
        $(this).css('position', 'absolute');
        $(this).css('top', '50%');
        $(this).css('left', '0px');
        $(this).css('width', '100%');

    });

    $(window).resize(function() {

        var thisheight = Math.round(parseInt($('.valignmiddle').outerHeight()) / 2);
        $('.valignmiddle').css('margin-top', '-' + thisheight + 'px');

        if(parseInt($('.valignmiddle').outerHeight()) > parseInt($('.valignmiddle').parent().outerHeight())) {
		
            $('.valignmiddle').parent().outerHeight($('.valignmiddle').outerHeight());
		
        }

    }).trigger('resize');

});

</script>
</head>
<body>
<div style="width: 50%; height: 50%; border: 1px solid red;">
<div class="valignmiddle" style="border: 1px solid green;">Hello</div>
</div>
</body>
</html>

How does it work?

First we set up some styles for both the parent element and the one we want to vertically align. We need an absolutely positioned element inside of a relatively positioned one and then the top value set to 50%.

$('.valignmiddle').each(function() {

    $(this).parent().css('position', 'relative');
    $(this).css('position', 'absolute');
    $(this).css('top', '50%');
    $(this).css('left', '0px');
    $(this).css('width', '100%');

});

The width is set to the same width as the parent element so you can centre text, etc.

This sort of vertically aligns the element but there is too much space at the top. This is because the start of the element begins half way down the parent element. So, what we need to do is add a negative margin that is half its own height.

$(window).resize(function() {
    var thisheight = Math.round(parseInt($('.valignmiddle').outerHeight()) / 2);

    $('.valignmiddle').css('margin-top', '-' + thisheight + 'px'); }).trigger('resize');

Notice how this code is called on when the browser resizes; this means if your parent element changes size (i.e. it is a % or em width), so does the child element as per table cell behaviour.

What if the child content has a greater height than its parent? To prevent it leaking out we simply check the heights and adjust accordingly if need be:

if(parseInt($('.valignmiddle').outerHeight()) > parseInt($('.valignmiddle').parent().outerHeight())) {

    $('.valignmiddle').parent().outerHeight($('.valignmiddle').outerHeight());

}

To use the code simply uses the JQuery code in the script tags above and give your element the class name .valignmiddle.

The CSS is there for demonstration purposes only.
This code assumes you want to align according to the width and height of the parent element regardless of padding.
Tim Bennett is a Leeds-based web designer from Yorkshire. He has a First Class Honours degree in Computing from Leeds Metropolitan University and currently runs his own one-man web design company, Texelate.