Marienkäfer by solemone

Overflow Image with vertical centering for Responsive Web Design

If you want to use an image in your responsive web design you can use fluid images. But there is another way. You can set a maximum height and crop the image.

So how does this work? It's simple. Just put your image in a container and set the width of your image to 100%. Then set the max-height of the container to 450px and hide the overlap by setting the overflow to hidden.

If you now change the width of the container, you will see that the image adapts the container's width but does not exceed the max-height.

Infographic step one

Now you have a cropped image that adapts the width of your container. But the image is only cropped at the bottom. It would be better to steal the same amount of image information at both sides, bottom and top.

To do this you can use JavaScript (jQuery). All you need to do is calculate the overlap divided by two and set the margin-top of the image to this value.

margin-top = (container height - image height) / 2

Then call a JavaScript function on the events load, resize and here comes the special: "transitionend". Why transitionend? Because if you use Media Queries to change the width of the container there is no event like resize that will call the function. (Think of a change from portrait to landscape view on a tablet or smartphone).

So just use a CSS transition to change the max-width and you can fire the callback function when the transition ends.

Infographic step two

You can use a CSS transition for the margin-top of the image to make it smooth. You can also write a fallback with a jQuery animation if the browser doesn't support CSS transitions. Modernizr is your friend ;)

That's it. I think it's a good option for a preview image that isn't essential. Or you might use it for an image on top of a blog post. Use it just as you need it. If you have questions or ideas for improvement please let me know. @solemone

PS: It would be great to see a solution for this technique with CSS only. If you have any idea how to do that, let me know.

The Source Code

HTML


				<div class="image-wrap" id="wrapper">
					<img src="path/to/your/image.jpg" alt="your image">
				</div>

CSS


				.image-wrap {
					max-height: 450px;
					overflow: hidden;
					max-width: 800px;		
					-webkit-transition: max-width .5s ease-out;  /* Saf3.2+, Chrome */
					-moz-transition: max-width .5s ease-out;  /* FF4+ */
					-ms-transition: max-width .5s ease-out;  /* IE10? */
					-o-transition: max-width .5s ease-out;  /* Opera 10.5+ */
					transition: max-width .5s ease-out;
				}
				
					.image-wrap img {
						width: 100%;
						-webkit-transition: margin-top .5s ease-out;  /* Saf3.2+, Chrome */
						-moz-transition: margin-top .5s ease-out;  /* FF4+ */
						-ms-transition: margin-top .5s ease-out;  /* IE10? */
						-o-transition: margin-top .5s ease-out;  /* Opera 10.5+ */
						transition: margin-top .5s ease-out;
					}
					
				@media only screen and (min-width: 1160px) {
					.image-wrap { max-width: 1000px; }
				}

JavaScript

Update: The code has been optimized. I now use the .on() function of jQuery 1.7 to call the centerImage() function on the events load and resize. If you use an previous version of jQuery you can use .bind() instead.


				$(document).ready(function() {

					var imageHeight, wrapperHeight, overlap, container = $('.image-wrap');	
		
					function centerImage() {
						imageHeight = container.find('img').height();
						wrapperHeight = container.height();
						overlap = (wrapperHeight - imageHeight) / 2;
						container.find('img').css('margin-top', overlap);
					}
					
					$(window).on("load resize", centerImage);
					
					var el = document.getElementById('wrapper');
					if (el.addEventListener) {	
						el.addEventListener("webkitTransitionEnd", centerImage, false); // Webkit event
						el.addEventListener("transitionend", centerImage, false); // FF event
						el.addEventListener("oTransitionEnd", centerImage, false); // Opera event
					}
		
				});