将图像缩放以适应边界框

132

是否有一种纯CSS的方法可以将图像缩放到边界框中(保持长宽比)?如果图像大于容器,则可以使用此方法:

img {
  max-width: 100%;
  max-height: 100%;
}

示例:

但我想将图像缩放到某个维度以达到容器的100%。


你的意思是像这样 height: 100%, width: 100% 吗?你有想要达到的特定尺寸吗?否则,你也可以拉伸图片并强制它达到那些尺寸。 - mikevoermans
@mikevoermans 看看我的前两个例子:我想将图像拉伸到其中一个维度为100%,另一个维度<=100%。 - Thomas Guillory
@jacktheripper 当然要保持宽高比... - Thomas Guillory
@gryzzly 这些示例已经说明了一切!如果他们看了这些示例,那就显而易见了。 - Thomas Guillory
@Artimuz 我完全不同意。你的问题有三个答案(包括我的)都表明这并不明显。 - Khan
15个回答

185

CSS3提供了一种解决方案!

该解决方案是将图像设置为background-image,然后将background-size设置为contain

HTML

<div class='bounding-box'>
</div>

CSS

.bounding-box {
  background-image: url(...);
  background-repeat: no-repeat;
  background-size: contain;
}

在此测试: http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain

与最新的浏览器完全兼容:http://caniuse.com/background-img-opts

要使div居中对齐,您可以使用以下变体:

.bounding-box {
  background-image: url(...);
  background-size: contain;
  position: absolute;
  background-position: center;
  background-repeat: no-repeat;
  height: 100%;
  width: 100%;
}

6
如果您不想要任何“letterboxing”,请将其设置为“cover”:背景大小:覆盖; - arxpoetica
3
请注意,您可以使用HTML注入图片URL:<div class=image style="background-image: url('/images/foo.jpg');"></div>。所有其他样式应该使用CSS应用。 - Andrey Mikhaylov - lolmaus
17
我认为这是一种糟糕的做法。通过将它更改为背景图像,你就删除了HTML中图像的语义意义。 - animuson
1
似乎如果这样做,您失去了在图像上放置边框的能力。 - Danny Dulai
18
@animuson: 对我帮助很大,因为我正在使用HTML/CSS制作打印报告,而且对语义不是那么关心 :) - Christian Wattengård
显示剩余6条评论

107
注意:尽管这是被接受的答案,但这个其他答案更准确,并且如果您有使用背景图像的选项,它目前在所有浏览器中都得到支持。
编辑2:在现代时代,使用object-fit可能是一个更好的解决方案:https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit 不,没有纯CSS的方法可以在两个方向上实现这一点。您可以添加
.fillwidth {
    min-width: 100%;
    height: auto;
}

为了使一个元素始终具有100%的宽度,并自动按比例调整高度,或者反过来:
.fillheight {
    min-height: 100%; 
    width: auto;
}

始终按最大高度和相对宽度进行缩放。要同时实现这两个效果,您需要确定宽高比是高于还是低于其容器,而CSS无法做到这一点。
原因是CSS不知道页面的实际情况。它事先设置规则,但只有在元素渲染之后,您才能确切知道处理的尺寸和比例。唯一能检测到这一点的方法是使用JavaScript。
虽然你不是在寻找一个JS解决方案,但我还是会提供一个,如果有人需要的话。用JavaScript处理这个问题最简单的方法是根据比例差异添加一个基于类的解决方案。如果盒子的宽高比大于图像的宽高比,就添加类"fillwidth",否则添加类"fillheight"。

$('div').each(function() {
  var fillClass = ($(this).height() > $(this).width()) 
    ? 'fillheight'
    : 'fillwidth';
  $(this).find('img').addClass(fillClass);
});
.fillwidth { 
  width: 100%; 
  height: auto; 
}
.fillheight { 
  height: 100%; 
  width: auto; 
}

div {
  border: 1px solid black;
  overflow: hidden;
}

.tower {
  width: 100px;
  height: 200px;
}

.trailer {
  width: 200px;
  height: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tower">
  <img src="http://placekitten.com/150/150" />
</div>
<div class="trailer">
  <img src="http://placekitten.com/150/150" />
</div>


8
实际上有一个解决方案:将CSS3的background-size设置为contain。请看我的答案。 - Thomas Guillory
你说得完全正确。虽然现在已经过去了一年半,但我还是编辑了我的帖子。 - Stephan Muller
4
我认为这是正确的答案,回答的问题是img标签的CSS代码。这很重要,因为从语义上讲,img标签是内容,将图像作为div的背景则不是。尽管有些情况下这种做法可能不切实际(比如你不知道图像与容器的比例),但对于其他情况而言则非常合适。谢谢。 - duncanwilcox
1
对于像我一样在谷歌上找到这篇文章的人:您可以使用object-fit属性来使用纯CSS实现此操作。https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit - lxhom
1
谢谢 @lxhom,我也加上那个信息了 :) - Stephan Muller

40

这里是我发现的一个不太正式的解决方案:

#image {
    max-width: 10%;
    max-height: 10%;
    transform: scale(10);
}

这将使图像放大十倍,但将其限制在最终大小的10%以内 - 从而将其限制在容器内。

background-image解决方案不同,这也适用于<video>元素。

交互式示例:

 function step(timestamp) {
     var container = document.getElementById('container');
     timestamp /= 1000;
     container.style.left   = (200 + 100 * Math.sin(timestamp * 1.0)) + 'px';
     container.style.top    = (200 + 100 * Math.sin(timestamp * 1.1)) + 'px';
     container.style.width  = (500 + 500 * Math.sin(timestamp * 1.2)) + 'px';
     container.style.height = (500 + 500 * Math.sin(timestamp * 1.3)) + 'px';
     window.requestAnimationFrame(step);
 }

 window.requestAnimationFrame(step);
 #container {
     outline: 1px solid black;
     position: relative;
     background-color: red;
 }
 #image {
     display: block;
     max-width: 10%;
     max-height: 10%;
     transform-origin: 0 0;
     transform: scale(10);
 }
<div id="container">
    <img id="image" src="https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png">
</div>


1
我喜欢这个解决方案。它不仅实际回答了问题(我知道,这是一个想法),而且在所有现代浏览器中都能完美运行,无需使用JavaScript! - ndm13
2
我很想看看那个。在我的测试中,将img放置在400x400容器中,img只会被裁剪在角落里。 - cyberwombat
3
好的回答!@Yashua 您需要添加 transform-origin: top left 以停止裁剪。/Zombie - XwipeoutX
1
有趣,但在Chrome上无法工作。会导致图像的一行被裁剪。 - MattK
1
@Konstantin 只有在您想要放大图像(当它小于容器的宽度或高度时)时才需要缩放。 - Vladimir Panteleev
显示剩余6条评论

29

4
截至撰写时间(2016年9月12日上午10:56),IE仅占约16%的市场份额,并持续下降,因此这对我来说是最好的答案:D。 - Zhang
14
不要更改其他人的答案来修复除拼写错误或损坏链接之外的内容。我不会在 SO 的答案中说出像“有一个补丁程序适用于糟糕的浏览器”这样幼稚的话,而且我不喜欢我的答案被编辑成看起来像我说了那句话。如果你想用自己的话,就放在你自己的答案里。 - Glenn Maynard
我认为问题不在IE上,而是在Edge浏览器上。根据caniuse网站,Edge浏览器对于object-fit的支持仍在开发中。 - BairDev
这应该是2017年及以后最受欢迎的答案之一...根据上面的caniuse链接,全球90%的用户现在使用支持此功能的浏览器。 - fgblomqvist
我刚刚发布了一个答案,它可以在有或没有 object-fit 的情况下工作:https://dev59.com/Vmkw5IYBdhLWcg3wSovA#46456673 - gabrielmaldi
在缩放后,您如何获取图像的尺寸? - Max Waterman

10

html:

    <div class="container">
      <img class="flowerImg" src="flower.jpg">
    </div>

CSS:

.container{
  width: 100px;
  height: 100px;
}


.flowerImg{
  width: 100px;
  height: 100px;
  object-fit: cover;
  /*object-fit: contain;
  object-fit: scale-down;
  object-position: -10% 0;
  object-fit: none;
  object-fit: fill;*/
}

5
你可以通过纯CSS实现此功能,且完全支持垂直长图片和水平长图片,以下是适用于Chrome、Firefox和Safari的代码片段(使用object-fit: scale-down或不使用都可):

figure {
  margin: 0;
}

.container {
  display: table-cell;
  vertical-align: middle;
  width: 80px;
  height: 80px;
  border: 1px solid #aaa;
}

.container_image {
  display: block;
  max-width: 100%;
  max-height: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container2_image2 {
  width: 80px;
  height: 80px;
  object-fit: scale-down;
  border: 1px solid #aaa;
}
Without `object-fit: scale-down`:

<br>
<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>

<br> Using `object-fit: scale-down`:

<br>
<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>


3

另一种解决方案,无需背景图片,也无需容器(尽管必须知道边界框的最大大小):

img{
  max-height: 100px;
  max-width: 100px;
  width: auto;    /* These two are added only for clarity, */
  height: auto;   /* as the default is auto anyway */
}

如果需要使用容器,则可以将max-width和max-height设置为100%:
img {
    max-height: 100%;
    max-width: 100%;
    width: auto; /* These two are added only for clarity, */
    height: auto; /* as the default is auto anyway */
}

div.container {
    width: 100px;
    height: 100px;
}

为此,您需要类似于以下内容:

对于这个问题,您可以有如下解决方案:

<table>
    <tr>
        <td>Lorem</td>
        <td>Ipsum<br />dolor</td>
        <td>
            <div class="container"><img src="image5.png" /></div>
        </td>
    </tr>
</table>

1
这个示例可以按比例拉伸图像以适应整个窗口。 对以上正确代码的改进是添加$( window ).resize(function(){});
function stretchImg(){
    $('div').each(function() {
      ($(this).height() > $(this).find('img').height()) 
        ? $(this).find('img').removeClass('fillwidth').addClass('fillheight')
        : '';
      ($(this).width() > $(this).find('img').width()) 
        ? $(this).find('img').removeClass('fillheight').addClass('fillwidth')
        : '';
    });
}
stretchImg();

$( window ).resize(function() {
    strechImg();
});

这里有两个if条件。第一个条件不断检查图像高度是否小于div并应用.fillheight类,而下一个条件检查宽度并应用.fillwidth类。 在两种情况下,使用.removeClass()删除另一个类。

以下是CSS样式:

.fillwidth { 
   width: 100%;
   max-width: none;
   height: auto; 
}
.fillheight { 
   height: 100vh;
   max-width: none;
   width: auto; 
}

如果你想在一个div中拉伸图片,可以用100%代替100vh。这个例子能让图片成比例地伸展以适应整个窗口。


OP明确要求只使用CSS的方法。 - Colton McCormack

0

你想要向上扩展,但不想向下缩小吗?

div {
    border: solid 1px green;
    width: 60px;
    height: 70px;
}

div img {
    width: 100%;
    height: 100%;
    min-height: 500px;
    min-width: 500px;
    outline: solid 1px red;
}

然而,这并不锁定宽高比。


5
在对别人的回答进行负评之前,尽可能明确你的期望,并特别是在他们回答你的问题之前,先通过编辑澄清你的问题。请注意语气友好,避免误解。 - Khan
2
另外,请尽量礼貌一些。如果你说话的方式不好,没有人会帮助你。 - Misha Reyzlin
@Artimuz 如果我误导了您,我深感抱歉,但是我认为您希望保持宽高比不清楚,这就是为什么我特别评论的原因。此外,您会注意到我从示例中粘贴了您的代码片段。如果您指定宽度,我相信保持高度:自动;将为您完成此操作。 - ericosg

0

首先是一些 CSS:

div.image-wrapper {
    height: 230px; /* Suggestive number; pick your own height as desired */
    position: relative;
    overflow: hidden; /* This will do the magic */
    width: 300px; /* Pick an appropriate width as desired, unless you already use a grid, in that case use 100% */
}
img {
    width: 100%;
    position: absolute;
    left: 0;
    top: 0;
    height: auto;
}

HTML代码:

<div class="image-wrapper">
  <img src="yourSource.jpg">
</div>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接