Vertical Alignment of Images using CSS

24 Oct

Introduction

CSS has a great property called ‘vertical-align’. Except that it often doesn’t do what we expect it to. For those of us who started out with tables (not that we’d admit it in public!), we remember the good old “valign” property, which did exactly what it said on the tin. It centered an element vertically within a table cell. Coupled with our other old friend “align”, we were actually able to get something in the middle of a box, which was nice. Now, these 2 elements have been disbarred because we rightly adhere to the principle of separation of content and presentation. But every so often you just wish you could use ‘valign’ to work it’s magic and you end up doing crazy things like changing the ‘display’ property of elements to ‘table’ and ‘table-cell’ in the vain hope that ‘vertical-align’ might work the way you want it.

What we want to achieve

 

First, a brief explanation of how ‘vertical-align’ does actually work. It’s designed for use with inline elements only. The main use case being that it allows you to dictate how an image (or other inline element) will position vertically relative to the baseline of text. There are a few good write ups on this, which really explain it in detail and I’d recommend you check out Chris Coyier’s write up on the subject over on CSS Tricks.

The Problem

The problem with vertical-align is that it only works to align inline elements relative to text. What this means is that if you have no text, ‘vertical-align’ will have no effect. The reason this is a problem for me is that I would like to be able to control vertical positioning of an image or many images within a div where there is no text, without resorting to specific margins or javascript. And my memories of the good old days of ‘valign’ make me think I should be able to do this. I have 2 concrete examples of where I would like to use vertical alignment:

  1. Often I’ll be asked to create a logo bar on a site to show suppliers, brands stocked, businesses involved, etc. Logos come in all shapes and sizes but generally I’d like them to align vertically in the block for better presentation. When there’s no text in the block (because it’s just logo images), vertical-align gives me no control and I feel I have to resort to individual margins which is less than ideal.
  2. I design interfaces for online stores quite a bit. They are built on a content management system and they are mostly used by small businesses who don’t tend to have a graphic designer on hand to prepare images. My trusty devs ensure that product images are resized so they fix within width and height restrictions but the thumbnails are often landscape or vertical whereas the thumbnail space in my design is usually square to allow for either. To make the whole interface look a bit nicer, I’d like to be able to vertically and horizontally centre the thumbnail image within its block but again there’s no text, just an image, so vertical-align doesn’t work for me.

The Solution

Case #1

Starting with case #1, let’s look at a logo bar. Now these HTML5 logos are all nice and tidy, mostly the same width and height except for the larger one in the middle. Doesn’t look too bad but I’d still like to align them along the middle.

View the example – without vertical alignment set to middle.

View the example – with vertical alignment set to middle.

With the technique applied

 

The CSS for this is simple and takes it’s lead from the “clearfix” solution that has been around for quite a while. (Aside: on the subject of clearfix, have you seen the new micro clearfix? No more collapsing margins!) Since vertical-align needs text to work, we give it text! Using the pseudo-element “::after”, we insert a period (“.”) after the content in our div. Then we change the visibility to hidden so that it still takes up space but doesn’t introduce any unnecessary html in our document.

p>

Our logos are just a list of images in HTML wrapped in a div with class “logoBar”. The CSS looks like this:

.logoBar::after {
	content: ".";
    visibility: hidden;
}

.logoBar img {
	vertical-align: middle;
}

It’s not really relevant here, but if you wanted to you can add a line-height (to set the space in which the images align vertically) to the logoBar div as follows:

.logoBar {
	line-height: 256px;
}
Case #2

In our second example, we have only 1 image but we want it to center both vertically and horizontally within a block. There’s a method for centering an image horizontally that I regularly use – you change the ‘display’ property of the image to ‘block’ and set it’s margin to ‘auto’. But that won’t work here as ‘vertical-align’ only works on inline elements (as in ‘display: inline’ OR ‘display: inline-block’ it will work for both. Images are natively ‘inline’). However, because we have added some text to get ‘vertical-align’ to work (in the form of the hidden “.”), ‘text-center’ now works as well.

View the example – single image in a block: horizontal and vertical central alignment

With the technique applied - fully centred

 

Our HTML is simple, it’s a single image wrapped in a div with class ‘thumbnail’. Our CSS looks like this:

.thumbnail {
	background: #ddd;
	width: 350px;
	height: 350px;
	line-height: 350px;
	text-align: center;
}

.thumbnail::after {
	content: ".";
    visibility: hidden;
}

.thumbnail img {
	vertical-align: middle;
}

Apart from using the ‘::after’ pseudo element and ‘vertical-align’ same as the previous example, note that our wrapper has an explicitly set width and height and ‘line-height’ as well as ‘text-align:center’. This technique will work just fine without the ‘width’ and ‘height’ set – the div will inherit the width and the height will be set by the line-height. However, without the line-height set the technique won’t work for vertical aligment and without ‘text-align: center’ the horizontal alignment won’t work.

Conclusion

And there you have it. Getting an image centered horizontally and vertically within a div is something that has annoyed me for a while and I dislike having to hack together solutions using ‘display: table-cell’, ‘position: absolute’ and other complicated techniques. The beauty of this solution is its simplicity. I hope you find many uses for it, I know I have.

Appendix

I mentioned the CSS Tricks article explaining vertical align. You can find it here: http://css-tricks.com/2597-what-is-vertical-align/

Another handy article with explanations of inline vs block elements and some other centering techniques appears on NoobCube: http://www.noobcube.com/tutorials/html-css/horizontal-and-vertical-centering-using-css-a-beginners-guide-/

HTML5 logos are (I presume) property of the W3C and are used under Creative Commons 3.0 Attribution Licence (as far as I can tell!): http://www.w3.org/html/logo/

Bitka works as Web Design Manager at Dragnet Systems & has a number of her own projects on the go. As a web designer, her specialties include HTML, CSS & Photoshop with healthy helpings of Javascript (jQuery for preference), WordPress and PHP. She was raised on Mac OS and when she's not web designing you'll find her designing jewellery over at Jou Jou Jewels. Follow @bitka on Twitter.

Trackbacks and Pingbacks

  1. Image centering with CSS - October 24, 2011

    [...] Stuff4Designers.com. If you’ve come up against this problem, you might find it interesting. Vertical and Horizontal Alignment of Images using css on [...]