Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scale an image to maximally fit available space and center it

Tags:

css

stretch

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.

.container1 {
  width: 500px;
  height: 300px;
  border: 2px;
  border-color: red;
  border-style: solid;
}
.container2 {
  width: 300px;
  height: 500px;
  border: 2px;
  border-color: blue;
  border-style: solid
}
.fill-vertical {
  border: 2px;
  border-style: solid;
  border-color: green;
  display: block;
  max-width: 100%;
}
.fill-horizontal {
  width: 100%;
  border: 2px;
  border-style: solid;
  border-color: green;
}
 <h1>Container 1, 500px x 300px, not filled</h1>
<div class="container1">
  <img src="https://dummyimage.com/100x100/000/fff">
</div>
<h1>Container 1, filled vertically (should be horizontally centered)</h1>

<div class="container1">
  <img class="fill-vertical" src="https://dummyimage.com/100x100/000/fff">
</div>

<h1>Container 300px x 500px, not filled</h1>

<div class="container2">
  <img class="fillIt" src="https://dummyimage.com/100x100/000/fff">
</div>

<h1>Container 300px x 500px, filled horizontally, should be vertically centered</h1>

<div class="container2">
  <img class="fill-horizontal" src="https://dummyimage.com/100x100/000/fff">
</div>

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

like image 987
blueFast Avatar asked Feb 10 '15 18:02

blueFast


People also ask

How do I scale an image to fit the screen in HTML?

One of the simplest ways to resize an image in the HTML is using the height and width attributes on the img tag. These values specify the height and width of the image element. The values are set in px i.e. CSS pixels. For example, the original image is 640×960.

How do I resize an image and keep the aspect ratio CSS?

The Simple Solution Using CSS By setting the width property to 100%, you are telling the image to take up all the horizontal space that is available. With the height property set to auto, your image's height changes proportionally with the width to ensure the aspect ratio is maintained.

How do I stretch an image to fit in a div?

Answer: Use the CSS max-width Property You can simply use the CSS max-width property to auto-resize a large image so that it can fit into a smaller width <div> container while maintaining its aspect ratio.


2 Answers

#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="https://picsum.photos/500/500">
</div>
<h1>Container 1, filled vertically (should be horizontally centered)</h1>
<div class="container1 centerImage">
    <img class="fill-vertical" src="https://picsum.photos/500/500">
</div>
<h1>Container 300px x 500px, not filled</h1>
<div class="container2 centerImage">
    <img src="https://picsum.photos/500/500">
</div>
<h1>Container 300px x 500px, filled horizontally, should be vertically centered</h1>
<div class="container2 centerImage">
    <img class="fill-horizontal" src="https://picsum.photos/500/500">
</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="https://picsum.photos/500/500" />
</div>

https://jsfiddle.net/efyey801/

like image 175
Hidden Hobbes Avatar answered Oct 20 '22 04:10

Hidden Hobbes


Here's one way to do it, relying on background-size. This does use img tags, as required, but the visible graphic is loaded as background to take advantage of available css rules.

.container {
  background-color: #edc;
  position: relative;
  margin: 2em;
}

.container img {
  display: block;
  width: 100%;
  height: 100%;

  background-image: url(http://www.clipartbest.com/cliparts/yck/eXb/yckeXboMi.png);
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
}

#c1 {
  width: 400px;
  height: 100px;
}


#c2 {
  width: 400px;
  height: 600px;
}
<div id="c1" class="container">
  <img src="">
</div>

<div id="c2" class="container">
  <img src="">
</div>

Here's some more information on background-size: https://developer.mozilla.org/en-US/docs/Web/CSS/background-size

like image 45
recursive Avatar answered Oct 20 '22 03:10

recursive