Fixe-height and vertically centered image

What I want to achieve is to have a have an image container that limits(crops) the height of the image, but within that mask, the image is vertically-centered.

So I use the following HTML markup:

<div class="hero">
	<img class="hero__img"/>
</div>

And the CSS code:

.hero {
	height: 200px;
	overflow: hidden;
}

.hero__img {
	/* What should I put here to center my image vertically? */
}

By default the image is contained within the hero, but is vertically aligned as top. Any ideas?

If it were a background image, this is easily done with these properties:-

	background-size: cover;
	background-position: center;

If it must be an img there is the object-fit: cover property for that, but it does not have support yet in Microsoft browsers.
There is more on that here along with @PaulOB offering an alternative to object-fit.

I tried that even before but even though I’m using the latest version of Safari, it does not seem to work. By the way, do I set the “object-fit: cover” to the actual image or the image container? I did both, but to no avail. But thanks for the article. I’m gonna read it.

It applies to the image. You also need to set the size on the image too.

I fixed it. Here is the changes in the CSS code:

.hero {
	position: relative;
	height: 200px;
	overflow: hidden;
}

.hero__img {
	position: absolute;
	top: 0;
	bottom: 0;
	margin: auto;
}

It works even without declaring top and bottom, but as far as I know, when a position is declared in CSS, at least 2 of the position values should be present.

I don’t know how much this approach is cross-browser bulletproof though.

1 Like

Not to forget the older methods until the new ones are fully implemented. :wink:

@Braveheart4, You could also try something like this if the context and design allow.

.hero {
    height: 200px;
    overflow: hidden;
    line-height: 200px; /* set its line-height the same as its height */
}

.hero__img {
    margin: -99em auto; /* make sure the image fit within the container height */
    vertical-align: middle; /* of the text line it resides on */
}
1 Like

This is what separates me (a designer who codes) and an actual front-end developer. I can never track older methods for legacy browsers. :slight_smile:

Anyway, I don’t know what those additional lines of code do, but the margin: -99em auto; makes my image disappear. If it’s set only as margin: auto; it works well.

I can’t see how margin:auto would place the image in the middle, are you sure?

Those additional rules makes the text-line that the image resides on as heigh as the container. The inline image can then be vertically aligned to the middle of that “container-heigh” text-line it sits on.

The image has its own anonymous line-box of the same height as itself. If the image is higher than the container that would push it down if it’s need for space wasn’t negated by the vertical margins so it can fit in the container.

When you say the margins I suggested makes the image disappear, it could be that the image is given a block display, e.g. in a css reset style. The vertical align rule has no effect on a block element as it does not sit on a text-line. (Test to comment out the overflow:hidden rule and see where the image went.)

Please try add a display inline-block rule to the image and see if that puts the image back.:

.hero {
    height: 200px;
    overflow: hidden;
    line-height: 200px; /* set its line-height the same as its height */
}

.hero__img {
    display: inline-block; /* make the vertical align rule apply */
    margin: -99em auto; /* make sure the image fit within the container height */
    vertical-align: middle; /* of the text line it resides on */
}

An absolutely placed element will centre both vertically and horizontally within its relative parent using margin:auto as long as top,bottom, left and right are defined as zero and that the absolute element has a width and height set.

Replaced elements (like images) have intrinsic width and height and don’t need to have their width/height defined for this to work.

1 Like

Thanks, I believe I totally missed reading post #5. :blush:

Yes, that would be a good solution for a content image (as I think this is). A drawback could be that the container can’t adapt to the image’s width in case it needs to but apparently it works in his design.

(I still can’t see how margin:auto could work in the code I posted. :stuck_out_tongue:)

My mistake. Apparently I still left the absolute positioning on the .hero and relative positioning on the .hero__img. Once I removed them, your example works too. I assume yours is more cross-browser compatible.

Sounds like you are answering me here.

The code you have in post #5 that @PaulOB referred to is the more crossbrowser compatible I think. It works in your design, use it.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.