Scale an image to maximally fit available space an

2020-03-18 08:31发布

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

标签: css stretch
3条回答
家丑人穷心不美
2楼-- · 2020-03-18 08:42

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)')
查看更多
Ridiculous、
3楼-- · 2020-03-18 08:47

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

查看更多
我命由我不由天
4楼-- · 2020-03-18 09:00

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/

查看更多
登录 后发表回答