对于图像元素,是否有与background-size: cover和contain等效的选项?

335

我有一个包含许多页面和不同背景图片的网站,我想通过CSS来显示它们,类似于以下代码:

body.page-8 {
    background: url("../img/pic.jpg") no-repeat scroll center top #000;
    background-size: cover;
}

然而,我想在一个页面上使用 <img> 元素显示不同(全屏)的图片,并且我希望它们具有与上面的 background-image: cover; 属性相同的属性(这些图片不能从 CSS 中显示,必须从 HTML 文档中显示)。

通常我使用以下代码:

div.mydiv img {
    width: 100%;
}

或者:

div.mydiv img {
    width: auto;
}

如何使图片充满整个屏幕并且具有响应式布局。但是当屏幕变得太窄时,图片会缩小得太多(width: 100%),并在底部屏幕显示页面的背景颜色。另一种方法,width: auto;,只会将图像设置为全尺寸而不响应屏幕大小。

是否有一种方法可以像 background-size: cover 一样显示图片?


1
很棒的问题。 - wonsuc
14个回答

536

解决方案 #1 - object-fit属性 (不支持IE)

只需在img元素上设置 object-fit: cover;

body {
  margin: 0;
}
img {
  display: block;
  width: 100vw;
  height: 100vh;
  object-fit: cover; /* or object-fit: contain; */
}
<img src="https://loremflickr.com/1500/1000" alt="A random image from Flickr" />

请见MDN有关object-fit:cover的说明:

替换内容将按其纵横比进行缩放,同时填充整个元素的内容框。如果对象的纵横比不匹配其框的纵横比,则将裁剪该对象以适合。

对于object-fit:contain

替换内容被缩放以保持其纵横比,同时适合元素的内容框。整个对象都被制作成填充盒子,同时保留其宽高比,因此如果对象的宽高比与盒子的宽高比不匹配,则该对象将被加上黑边来适应盒子的形状。

此外,请参见this Codepen demo,其中比较了应用于图像的object-fit:cover和应用于背景图像的background-size:cover
解决方案#2-使用CSS替换img为背景图片

body {
  margin: 0;
}

img {
  position: fixed;
  width: 0;
  height: 0;
  padding: 50vh 50vw;
  background: url("https://loremflickr.com/1500/1000") no-repeat;
  background-size: cover;
}
<img src="https://via.placeholder.com/1500x1000" alt="A random image from Flickr" />


4
截至本评论撰写时,Internet Explorer的任何版本(包括Edge)都尚未支持object-fit。但是,微软正在考虑支持该功能。点击此链接了解详情。 - Mike Kormendy
4
object-fit在IE浏览器中仍不受支持。如果你在生产网站中关心IE用户,建议避免使用它。 - Travis Michael Heller
2
你也可以为IE和旧版Safari添加#1的polyfill: https://github.com/bfred-it/object-fit-images - Valera Tumash
1
小心使用第二种解决方案。最好不要在移动浏览器上依赖vh:https://nicolas-hoizey.com/2015/02/viewport-height-is-taller-than-the-visible-part-of-the-document-in-some-mobile-browsers.html - sudokai
2
@RoCk,你可以在caniuse上找到这样的东西:https://caniuse.com/#search=background-att :) 顺便说一句,我想我们都可以放心,IE永远不会支持这个功能,因为也没有任何polyfill,所以我们只能通过JS / CSS hack来解决,直到微软决定(终于)通过从Windows中删除IE来“杀死”它。 - SidOfc
显示剩余7条评论

33

其实有一个非常简单的CSS解决方案,即使在IE8上也可以使用:

.container {
  position: relative;
  overflow: hidden;
  /* Width and height can be anything. */
  width: 50vw;
  height: 50vh;
}

img {
  position: absolute;
  /* Position the image in the middle of its container. */
  top: -9999px;
  right: -9999px;
  bottom: -9999px;
  left: -9999px;
  margin: auto;
  /* The following values determine the exact image behaviour. */
  /* You can simulate background-size: cover/contain/etc.
     by changing between min/max/standard width/height values.
     These values simulate background-size: cover
  */
  min-width: 100%;
  min-height: 100%;
}
<div class="container">
    <img src="http://placehold.it/200x200" alt="" />
</div>


9
这不是复制cover的行为,而是从src图片中裁剪一个居中的部分。请参见 http://jsfiddle.net/sjt71j99/4/ -- 第一张图是您裁剪的图片,下一张是通过background-size: cover得到的,也就是我们想要的,第三张是原始图片。我发现对于横向图片,将min-height和min-width替换为max-height: 100%;,对于纵向图片,则使用max-width: 100%。如果有既适用于横向又适用于纵向的方法,那就再好不过了。这是我目前见过的最好的跨浏览器解决方案。 - terraling
1
你是对的,它不能完全做到同样的事情,我尝试了一些东西,但似乎你实际上无法让它完全复制覆盖物,只要图像在一个维度上比容器小,它就能工作。 - Simon
@terraling, 我知道这是一个旧的评论,但请查看我的答案。它使用transform将img定位在中心。 - Thiago Barcala

33

假设您已经安排好要填充的容器元素,这似乎可行,但感觉有点hackish。实质上,我只是在较大的区域上使用 min / max-width/height ,然后将该区域缩放回原始尺寸。

.container {
  width: 800px;
  height: 300px;
  border: 1px solid black;
  overflow:hidden;
  position:relative;
}
.container.contain img {
  position: absolute;
  left:-10000%; right: -10000%; 
  top: -10000%; bottom: -10000%;
  margin: auto auto;
  max-width: 10%;
  max-height: 10%;
  -webkit-transform:scale(10);
  transform: scale(10);
}
.container.cover img {
  position: absolute;
  left:-10000%; right: -10000%; 
  top: -10000%; bottom: -10000%;
  margin: auto auto;
  min-width: 1000%;
  min-height: 1000%;
  -webkit-transform:scale(0.1);
  transform: scale(0.1);
}
<h1>contain</h1>
  <div class="container contain">
    <img 
       src="https://www.google.de/logos/doodles/2014/european-parliament-election-2014-day-4-5483168891142144-hp.jpg" 
       />
    <!-- 366x200 -->
  </div>
  <h1>cover</h1>
  <div class="container cover">
    <img 
       src="https://www.google.de/logos/doodles/2014/european-parliament-election-2014-day-4-5483168891142144-hp.jpg" 
       />
    <!-- 366x200 -->
  </div>


2
完全同意。这是所有上述解决方案中最适合一般使用的。 - Varis Vītols
很棒。它帮助了我。谢谢。 - Oro

25

我找到了一种纯CSS的简单解决方案,可以模拟封面和包含两种情况,在动态尺寸的容器中使用,而且不会限制图片比例。

请注意,如果您不需要支持IE或Edge 16之前的版本,则最好使用object-fit。

background-size: cover

.img-container {
  position: relative;
  overflow: hidden;
}

.background-image {
  position: absolute;
  min-width: 1000%;
  min-height: 1000%;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%) scale(0.1);
  z-index: -1;
}
<div class="img-container">
  <img class="background-image" src="https://picsum.photos/1024/768/?random">
  <p style="padding: 20px; color: white; text-shadow: 0 0 10px black">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
</div>

本处使用1000%是为了防止图片的原始大小大于其所显示的尺寸。例如,如果图像的大小为500x500,但容器只有200x200。通过这种解决方案,图像将被调整大小为2000x2000(由于min-width/min-height),然后缩小为200x200(由于transform: scale(0.1))。

x10因子可以替换为x100或x1000,但通常不理想,因为在20x20的div上呈现2000x2000的图像并不合适。 :)

background-size: contain

Following the same principle, you can also use it to emulate background-size: contain:

.img-container {
  position: relative;
  overflow: hidden;
  z-index: 0;
}

.background-image {
  position: absolute;
  max-width: 10%;
  max-height: 10%;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%) scale(10);
  z-index: -1;
}
<div style="background-color: black">
  <div class="img-container">
    <img class="background-image" src="https://picsum.photos/1024/768/?random">
    <p style="padding: 20px; color: white; text-shadow: 0 0 10px black">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
  </div>
</div>


比例尺技巧已经在这里给出[https://dev59.com/_Ggt5IYBdhLWcg3w-SP1#28771894],所以我看不出再发一个的意义,而且在许多答案中也是如此。 - Asons
如果您想要进行解释,请更新该答案,因为没有必要使用相同的解决方案两次。 - Asons
3
谢谢您的评论@LGSon。我以前没有看过那个答案,但我仍然认为我的答案在这里有价值。方法基本相同,但我认为我的呈现方式略微更清晰。许多其他答案在这里提供了相同的解决方案,并且它们都不完整(除了您链接的那个)。因此,如果我的答案不应在此处,其他答案也不应在此处。 - Thiago Barcala
1
我发现在安卓的Chrome移动浏览器上(在LG G3和Samsung S9上测试),它会缩小图像,但我没有在iOS上使用Chrome进行测试。在安卓的Firefox移动浏览器上,它可以正确显示。 - Jecko

11

,你不能像background-size:cover那样轻易实现,但是..

这种方法非常接近:它使用JavaScript确定图像是横向还是纵向,并相应地应用样式。

JS

 $('.myImages img').load(function(){
        var height = $(this).height();
        var width = $(this).width();
        console.log('widthandheight:',width,height);
        if(width>height){
            $(this).addClass('wide-img');
        }else{
            $(this).addClass('tall-img');
        }
    });
CSS
.tall-img{
    margin-top:-50%;
    width:100%;
}
.wide-img{
    margin-left:-50%;
    height:100%;
}

http://jsfiddle.net/b3PbT/


4
你可以使用“style”属性向元素添加背景图片,这样你仍然会在HTML中调用图像,但你仍然可以使用“background-size: cover” css属性来实现相应的效果:

HTML:

    <div class="image-div" style="background-image:url(yourimage.jpg)">
    </div>

CSS:
    .image-div{
    background-size: cover;
    }

这是我在需要动态加载到HTML的元素上添加background-size: cover行为的方法。然后,您可以使用很棒的CSS类,如background-position: center。嘭

1
主要是关注点分离,但这里还有一些其他的:http://programmers.stackexchange.com/a/271338 - Daan

3

我需要模拟 background-size: contain,但由于不支持object-fit,因此无法使用。我的图像具有定义的容器尺寸,这种方法适用于我:

.image-container {
  height: 200px;
  width: 200px;
  overflow: hidden;
  background-color: rebeccapurple;
  border: 1px solid yellow;
  position: relative;
}

.image {
  max-height: 100%;
  max-width: 100%;
  margin: auto;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
}
<!-- wide -->
<div class="image-container">
  <img class="image" src="http://placehold.it/300x100">
</div>

<!-- tall -->
<div class="image-container">
  <img class="image" src="http://placehold.it/100x300">
</div>


你可以使用 min-height: 100%; max-height:100%; 来达到 background-size: cover 的效果。 - Chris Seufert
1
min-height: 100%; max-height:100%;不会保持宽高比,因此并不完全等同。 - Reedyn

2
我们可以采用ZOOM方法。如果图像的高度或宽度小于所需的高度或宽度,最大缩放效果可以达到30%(或更多,最高可达100%)。我们可以使用overflow: hidden隐藏不需要的部分。
.image-container {
  width: 200px;
  height: 150px;
  overflow: hidden;
}
.stage-image-gallery a img {
  max-height: 130%;
  max-width: 130%;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
}

这将调整不同宽度或高度的图像。


1
这个是唯一一个对我有效的,真的很模拟封面。太棒了!+1 - MichaelJorgensenDK

2

使用CSS可以模拟object-fit: [cover|contain];。它使用transform[max|min]-[width|height]这不是完美的。 如果图像比容器更宽并且更短,则无法正常工作。

.img-ctr{
  background: red;/*visible only in contain mode*/
  border: 1px solid black;
  height: 300px;
  width: 600px;
  overflow: hidden;
  position: relative;
  display: block;
}
.img{
  display: block;

  /*contain:*/
  /*max-height: 100%;
  max-width: 100%;*/
  /*--*/

  /*cover (not work for images wider and shorter than the container):*/
  min-height: 100%;
  width: 100%;
  /*--*/

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
<p>Large square:
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x1000"></span>
</p>
<p>Small square:
<span class="img-ctr"><img class="img" src="http://placehold.it/100x100"></span>
</p>
<p>Large landscape:
<span class="img-ctr"><img class="img" src="http://placehold.it/2000x1000"></span>
</p>
<p>Small landscape:
<span class="img-ctr"><img class="img" src="http://placehold.it/200x100"></span>
</p>
<p>Large portrait:
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x2000"></span>
</p>
<p>Small portrait:
<span class="img-ctr"><img class="img" src="http://placehold.it/100x200"></span>
</p>
<p>Ultra thin portrait:
<span class="img-ctr"><img class="img" src="http://placehold.it/200x1000"></span>
</p>
<p>Ultra wide landscape (images wider and shorter than the container):
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x200"></span>
</p>


1
尝试同时设置min-heightmin-width,并使用display:block
img {
    display:block;
    min-height:100%;
    min-width:100%;
}

(fiddle)

提供你的图片所在的元素具有position:relativeposition:absolute,图片将覆盖容器。但是,它不会居中。
如果您知道它是否会水平溢出(设置margin-left:-50%)或垂直溢出(设置margin-top:-50%),则可以轻松地将图像居中。可能可以使用CSS媒体查询(以及一些数学)来找到答案。

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