问题
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
回答1:
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 childimg
will need to be positioned absolutely relative to the container. - Create a new
.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. - Add the
centerImage
class to the containingdiv
s. - Change
.fill-vertical
toheight: 100%;
which will make theimg
fill the vertical space. - Change
.fill-horizontal
towidth: 100%;
which will make theimg
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
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.
.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/
回答2:
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
回答3:
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:
(((horizontalScreenLimit - widthOfImage)/2), ((verticalScreenLimit - heightOfImage)/2)')
来源:https://stackoverflow.com/questions/28439310/scale-an-image-to-maximally-fit-available-space-and-center-it