HTML5 Development Center

Developed for you in part by
 
808-mediaquery

How to Create a Responsive Centered Image in CSS3

By | | CSS | CSS3 | HTML | HTML5 | Responsive Web Design

Image gallery lightboxes have been around for many years. They generally provide a great user experience until you attempt to load an image which is larger than the viewport dimensions. Developers often forget this important check and you’re presented with a centered image which is difficult to remove. The problem can be exacerbated on mobile devices.

Until recently, image lightboxes would need to implement several equations to determine the viewport and image dimensions then size and center accordingly. Fortunately, we can now rely on CSS3 media queries and transforms to do the hard work for us.

View the demonstration…

The HTML

Little to see here — we have an img and we’ll assign a class of “ri” (responsive image):

<img src="http://lorempixel.com/600/450/" class="ri" />

Remember to remove any height and width attributes.

Fallback CSS

IE6/7/8 do not understand media queries or transforms so our image will end up in the wrong location. There are shims and proprietary properties which could solve this but, in my opinion, they often cause more problems than they solve, i.e. increased page weight, degraded performance, maintenance headaches, etc.

Therefore, the following code provides a reasonable fallback for legacy browsers and should work on most landscape-oriented desktop screens:

img.ri
{
	position: absolute;
	max-width: 80%;
	top: 10%;
	left: 10%;
	border-radius: 3px;
	box-shadow: 0 3px 6px rgba(0,0,0,0.9);
}

The border-radius and box-shadow won’t be understood by old IEs either, but they’ll degrade gracefully.

Positioning the Image

To center the image, we move its top-left corner to the center of the viewport. To move it back to the true center, we use an appropriate transform (with prefixes for older browsers):

img.ri:empty
{
	top: 50%;
	left: 50%;
	-webkit-transform: translate(-50%, -50%);
	-moz-transform: translate(-50%, -50%);
	-ms-transform: translate(-50%, -50%);
	-o-transform: translate(-50%, -50%);
	transform: translate(-50%, -50%);
}

Take note of the selector: img.ri:emptyempty is a structural pseudo-class which only matches elements which have no children (an image should never have any). This is a CSS3 selector so IE8 and below will not parse the declaration. We could have used an alternative, such as Conditional Comments, but this seems a far more efficient solution and requires just six additional characters.

Making the Image Responsive

Our image must respond to the viewport dimensions to ensure it never overlaps the edge:

  • a maximum width must be defined if the viewport is taller than it is wide, and
  • a maximum height must be defined if the viewport is wider than it is tall.

We can use the media query orientation property to do the hard work for us:

@media screen and (orientation: portrait) {
  img.ri { max-width: 90%; }
}
@media screen and (orientation: landscape) {
  img.ri { max-height: 90%; }
}

Simple — and all done without any complicated JavaScripting. View the demonstration…

Please use the code as you like for your own projects. It could be used as the basis of your own modern, lightweight lightbox. Unless you’d like me to write one and provide a handy tutorial? Please forward your requests to @craigbuckler.

Craig Buckler

Craig is a Director of OptimalWorks, a UK consultancy dedicated to building award-winning websites implementing standards, accessibility, SEO, and best-practice techniques.

More Posts - Website

{ 19 comments… read them below or add one }

Ben May 9, 2013 at 8:35 am

What happened to

{
display: block;
margin: 0 auto;
}

for centering?

Reply

Ben May 9, 2013 at 9:05 am

Nevermind, I see that it wouldn’t work in this situation. Doesn’t help with vertical centering and not very useful in absolute positioning.

Reply

Lee May 4, 2013 at 9:40 pm

Isn’t it safer to use both max-height and max-width regardless of orientation? If you have a really wide panorama on a landscape device, it may not be enough to constrain by height. The image will remain proportional if both are in place, right?

I think the :empty trick is clever. However, if you decide to stop supporting IE8, it will much harder to pull the plug because the code is mixed throughout your file. You may be serving those extra characters to modern browsers for a while before you get a chance to refactor everything.

Reply

Craig Buckler May 6, 2013 at 2:03 am

Hi Lee. I think I understand your point but, in practice, the browser should size the image correctly.

With regard to :empty, a search and replace may be enough if you’ve not used it for other selectors. That said, why remove it? Even if you’re dropping further IE8 development, it doesn’t follow that you must rip out all IE8-specific code you previously wrote. You’d only be saving a few bytes and the browser is likely to stick around for many, many years.

Reply

DWD April 26, 2013 at 5:27 am

I’m a newbie, so please bear with me. When I put in the code it moves all of my images of place…
Do I have to style the position of each image in the img html string to get this to work correctly?
Thanks in advance for any help.

Reply

Craig Buckler April 26, 2013 at 7:20 am

Hi DWD. Only images with class=”ri” in the tag should be affected. Remove that class from an image and the problem should disappear.

Reply

DWD April 27, 2013 at 7:35 am

Hi Craig, Do you know how it would work with a img string styled image or if it would even work at all? Thanks for your time and expertise.

Craig Buckler May 9, 2013 at 11:03 am

Hi DWD. Do you mean a data-encoded image defined in HTML or CSS? If so, then yes – it should work.

Larry Botha April 26, 2013 at 1:02 am

Didn’t know about :empty, but I use

:root .class {}

to target IE9+. You can crunch off 1 additional character :P

Nice technique! Interesting alternative to using display: table;

http://www.hughlashbrooke.com/two-methods-for-vertical-centering-in-css/

Reply

Craig Buckler April 26, 2013 at 7:22 am

Ahh, but you need a space between :root and the other selector so there’s no saving! It’s another good option though, thanks.

Reply

Peeter Jozaf April 25, 2013 at 11:34 pm

Hello,
Thanks for sharing excellent post. I am new in this filed and now i got it.

Reply

Michael G April 25, 2013 at 1:22 pm

The demos above displayed fine for me in Chrome but neither displayed at all for me in IE9.0.8xxx. Both look terrific in IE10.

Reply

Delboy Web Designer April 25, 2013 at 10:23 am

Excellent – demos works fine for me. Thanks for sharing.

Reply

Bob Squires April 25, 2013 at 9:57 am

Neither solution seems to work on IE8 on my Win XP system (but great on Firefox, Google Chrome and Opera). What am I missing?
Thanks for the article – very useful !

Bob

Reply

Craig Buckler April 26, 2013 at 7:24 am

Try the demo outside of the code editor…
http://cssdeck.com/labs/full/responsive-image

Reply

BigAB April 24, 2013 at 8:53 am

A simple alternative without Transforms or media queries:
http://cssdeck.com/labs/wrxjveai

Reply

Craig Buckler April 24, 2013 at 10:46 am

Thanks BigAB – that’s very clever and far simpler than my solution! It appears to work better in IE8 too (IE7′s not great, but who cares).

Reply

Reilly May 1, 2013 at 8:18 pm

This one works perfect, this is the way to go!

Reply

Norris April 24, 2013 at 6:52 am

Verry helpfull tutorial. Thanks

Reply

Leave a Comment