Raphael Rafatpanah Raphael Rafatpanah - 2 months ago 16
CSS Question

Vertically Center Responsive Image

I am wondering if there is a simple way to vertically center a responsive image.

Please refer to the following jsFiddle: http://jsfiddle.net/persianturtle/yawTb/1/

Basic HTML:

<img class="mobile-title-size" src="http://zx85.dyndns.org/raphtest/img/title.png" alt="Logo">


Basic CSS:

.mobile-title-size {
position: absolute;
top: 2.5%;
left: 6%;
width: 70%;
max-width: 300px;


}

This is the mobile header that uses the same image that is displayed on tablet and desktop viewports. Since the image is already being loaded anyway, I am looking to use this same image, resize it smaller and vertically align it so that I can use one image for all viewports.

The Problem: On browser resize, the image does get smaller, but it does not vertically align in the center.

The Goal: Even though the width overlaps badly in this example, it is not an issue on my site. The goal is only to vertically center the image as the browser resizes.

I am okay with using a javascript/jQuery solution but of course, simple CSS is preferred.

Any help is greatly appreciated!

Answer

There are several ways to do it - purely CSS or a JS-based method.


Updated answer

Update: With the advent of CSS transform support, here is a rather elegant solution of positioning elements using pure CSS. With the given markup:

<div class="container">
    <img src="..." alt="..." title="..." />
</div>

For your CSS:

.container {
    /* The container has to have a predefined dimension though */
    position: relative;
}
.container img {
    position: absolute;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}

Updated JSFiddle


Old answer

For CSS, you can construct a ghost element within the container of the <img> element. Chris Coyier did an excellent write up on this technique. Let's say your HTML code looks like this:

<div class="container">
    <img src="..." alt="..." title="..." />
</div>

Then your CSS would be:

.container {
    font-size: 0;
    text-align: center;
}
.container:before {
    content: "";
    display: inline-block;
    height: 100%;
    vertical-align: middle;
}
.container > img {
    display: inline-block;
    vertical-align: middle;
}

The functional CSS fix can be seen working in this fiddle - http://jsfiddle.net/teddyrised/yawTb/8/

Or, you can use a JS-based method:

$(document).ready(function() {
    $(window).resize(function() {
        $(".container > img").each(function() {
            var cHeight = $(this).parent(".container").height(),
                cWidth = $(this).parent(".container").width(),
                iHeight = $(this).height(),
                iWidth = $(this).width();

            $(this).css({
                top: 0.5*(cHeight - iHeight),
                left: 0.5*(cWidth - iWidth)
            });
        });
    }).resize();  // Fires resize event when document is first loaded
});

But you will have to use the following CSS:

.container {
    position: relative;
}
.container img {
    position: absolute;
    z-index: 100;
}

[Edit]: For the JS-based method where you absolutely position the image element, you will have to explicitly state the dimensions of the .container element, or have some content in it (but it kind of defeats the purpose because the image will be above the content). This is because the image element has been taken out of the document flow, and therefore its dimensions will not affect the size of the parent container.

The working example of the JS version is here - http://jsfiddle.net/teddyrised/yawTb/7/