Scale an image to maximally fit available space and center it

blueFast picture blueFast · Feb 10, 2015 · Viewed 19.1k times · Source

I am building a single page application. In one of the views I want to show an image which must take as much available space as possible:

  • most important: it must keep the aspect ratio
  • it must not be cropped
  • it must be stretched horizontally and/or vertically (without changing aspect ratio) to cover the maximum possible space
  • the size of the image and viewport are not known
  • it must be centered
  • no js must be used
  • the element must be an img element and no background must be used - I already have a background (in the container)

For example, let's say that the image is 100px x 100px, and that we have a container of 500px x 300px. The image would then be stretched to 300px x 300px, and be horizontally centered so that 100px are left as padding on both sides.

Is this possible?

Here is my non-finished code of what I am trying to accomplish.

In that code I am forced to use a different class for the image depending on whether I want to stretch vertically or horizontally, but actually I want CSS to do this automatically: just one stretch class must be defined.

In short what I want CSS to do is: stretch width and/or height to fit available space, keeping aspect ratio

Answer

Hidden Hobbes picture Hidden Hobbes · Feb 11, 2015

This can be achieved in CSS with a few changes

The required changes are:

  • Create a new .centerImage css rule. overflow: hidden; ensures that the image does not spill out of the container. position: relative; is required as the child img will need to be positioned absolutely relative to the container.
  • Create a new .centerImage img css rule. max-height: 100%; and max-width: 100% ensures the aspect ratio is kept intact. Setting bottom, left, right and top to 0 and margin: auto; centers the image.
  • Add the centerImage class to the containing divs.
  • Change .fill-vertical to height: 100%; which will make the img fill the vertical space.
  • Change .fill-horizontal to width: 100%; which will make the img fill the horizontal space.

.container1 {
	border: 2px;
	border-color: red;
	border-style: solid;
	height: 300px;
	width: 500px;
}
.container2 {
	border: 2px;
	border-color: blue;
	border-style: solid;
	height: 500px;
	width: 300px;
}
.fill-vertical {
	height: 100%;
}
.fill-horizontal {
	width: 100%;
}
.centerImage {
	display: block;
	overflow: hidden;
	position: relative;
	text-align: center;
}
.centerImage img {
	bottom: 0;
	left: 0;
	margin: auto;
	max-height: 100%;
	max-width: 100%;
	position: absolute;
	right: 0;
	top: 0;
}
<h1>Container 1, 500px x 300px, not filled</h1>
<div class="container1 centerImage">
	<img src="http://files.giercownia.pl/upload/avatars/r/ravax.png?v=0">
</div>
<h1>Container 1, filled vertically (should be horizontally centered)</h1>
<div class="container1 centerImage">
	<img class="fill-vertical" src="http://files.giercownia.pl/upload/avatars/r/ravax.png?v=0">
</div>
<h1>Container 300px x 500px, not filled</h1>
<div class="container2 centerImage">
	<img src="http://files.giercownia.pl/upload/avatars/r/ravax.png?v=0">
</div>
<h1>Container 300px x 500px, filled horizontally, should be vertically centered</h1>
<div class="container2 centerImage">
	<img class="fill-horizontal" src="http://files.giercownia.pl/upload/avatars/r/ravax.png?v=0">
</div>

http://jsbin.com/bupuwohica/2/

Further to the above changes, it is possible to achieve this with the CSS property object-fit

To do this you need to:

  • Add object-fit: contain; to the image
  • Set height and width to 100%

The only caveat to this is browser support as while Firefox, Chrome, Safari and Opera have supported this for some time IE and Edge do not and will require either a polyfill or fallback.

.container {
  border: 2px solid red;
  height: 200px;
  overflow: hidden;
  resize: both;
  width: 300px;
}
img {
  object-fit: contain;
  height: 100%;
  width: 100%;
}
<p>The below div is resizable, drag the bottom right corner to see how the image scales</p>
<div class="container">
  <img alt="" src="http://files.giercownia.pl/upload/avatars/r/ravax.png?v=0" />
</div>

https://jsfiddle.net/efyey801/