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="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">
<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">
<img class="fillIt" 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">
<img class="fill-horizontal" src="http://files.giercownia.pl/upload/avatars/r/ravax.png?v=0">
</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
Yes it's entirely possible. You just need to make sure you have "Bounds" or limits on your possible max size for X or horizontal and Y or vertical limits. Once you know the max dimensions then you can make those constants to compare to. The easiest method i know of is to compare X and Y as Vectors so you can see their change. To get it centered is also easy at this point:
Here's one way to do it, relying on
background-size
. This does useimg
tags, as required, but the visible graphic is loaded as background to take advantage of available css rules.Here's some more information on background-size: https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
This can be achieved in CSS with a few changes
The required changes are:
.centerImage
css rule.overflow: hidden;
ensures that the image does not spill out of the container.position: relative;
is required as the childimg
will need to be positioned absolutely relative to the container..centerImage img
css rule.max-height: 100%;
andmax-width: 100%
ensures the aspect ratio is kept intact. Settingbottom
,left
,right
andtop
to0
andmargin: auto;
centers the image.centerImage
class to the containingdiv
s..fill-vertical
toheight: 100%;
which will make theimg
fill the vertical space..fill-horizontal
towidth: 100%;
which will make theimg
fill the horizontal space.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:
object-fit: contain;
to the imageheight
andwidth
to100%
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.
https://jsfiddle.net/efyey801/