【问题标题】:How to emulate background-size: cover on <img>?如何模拟背景大小:覆盖 <img>?
【发布时间】:2013-11-04 20:37:22
【问题描述】:

我如何在框内调整图像的大小和位置,使其覆盖整个框,类似于background-size: cover 的工作原理。

<div class="box" style="width: 100px; height: 100px;">
  <img src="pic.jpg" width="413" height="325">
</div>

我知道我必须在框中添加overflow:hidden,并且图像需要position: absolute。但是,让我获得正确的图像新尺寸和左 + 顶部位置的公式是什么?

【问题讨论】:

  • $('.box').each(function(i) { $(this).children('img:first').height($(this).height()).width($(this).width()).css({ position: 'absolute', top: 0, left: 0 }); })
  • @SpYk3HH 与background: 100% 100% 相同,而不是background-size: cover
  • 您希望图像也居中还是足够大?我正在看这个不使图像居中的示例。 w3schools.com/cssref/…
  • 不太确定你想要什么,因为封面是背景定位。对于内部 img 元素,这似乎是一种不好的姿态,但我想你可以尝试一个确切的公式,虽然我自己不确定这个公式
  • @TreeTree:是的。那是我的错。我认为背景尺寸的封面也会使图像居中:P(也许背景位置:中心也是必需的?)

标签: javascript jquery math background-size


【解决方案1】:

对于它的价值:现在可以单独使用 CSS 来完成...

新的 CSS 属性 object-fit (Current browser support)

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

您甚至不需要将img 包装在div 中!

FIDDLE

img {
  width: 100px;
  height: 100px;
}
.object-fit {
  display: block;
  object-fit: cover;
}
.original {
  width: auto;
  height: auto;
  display: block;
}
<img src="http://lorempixel.com/413/325/food" width="413" height="325">
<p>Img 'squashed' - not good</p>
<img class="object-fit" src="http://lorempixel.com/413/325/food" width="413" height="325">
<p>object-fit: cover -
   The whole image is scaled down or expanded till it fills the box completely, the aspect ratio is maintained. This normally results in only part of the image being visible. </p>
<img class="original" src="http://lorempixel.com/413/325/food" width="413" height="325">
<p>Original ing</p>

您可以在webplatform article 中阅读有关此新属性的更多信息。

另外,这里是上述文章中的a fiddle,它演示了object-fit 属性的所有值。

【讨论】:

  • 不支持 IE11 不知道怎么能得到这么多票
  • 我当然愿意,但我不得不像对待慈父一样对待 IE。
  • @Toskan 这不是公认的答案,因为缺乏 IE 支持。 IE 很烂,但如果它完全不受支持;那么它不是一个完全兼容的解决方案。仍然有很多组织仍然坚持使用 IE,这很不幸,但仍然使其成为基本兼容性标准的要求。不过,使用正在逐渐减少,我希望 IE 不会成为未来的一个因素,因为就像这种情况一样。
  • 你总是可以为那些过时的浏览器使用 polyfill github.com/bfred-it/object-fit-images
  • IE11 使用统计数据每个月都在下降...这个答案将成为公认的答案。
【解决方案2】:

足够接近,纯CSS解决方案,使用img标签模拟背景大小封面,具有非常好的浏览器支持(IE8+):

.container {

  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;

  overflow: hidden;

}

.container img {

  position: absolute;
  top: 50%;
  left: 50%;

  width: auto;
  height: auto;

  max-height: none;
  max-width: none;

  min-height: 100%;
  min-width: 100%;

  transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);

}
<div class="container">
  <img src="//lorempixel.com/400/200/sports/1/" />
</div>

【讨论】:

  • 很好的解决方案!除非它不适用于 IE8。这适用于 IE9+。更多信息:caniuse.com/#feat=transforms2d
  • 当我使用您的解决方案时,图像只是拉伸以适合容器。我做错了吗?
  • @torjinx 看来这个解决方案只扩展较小的图像,它不会收缩比容器大得多的图像。
  • 这应该是公认的答案!简单,在任何地方都得到支持,并且完全符合它的预期。谢谢!
【解决方案3】:

这可能更容易

jQuery

$('.box').each(function() {
    //set size
    var th = $(this).height(),//box height
        tw = $(this).width(),//box width
        im = $(this).children('img'),//image
        ih = im.height(),//inital image height
        iw = im.width();//initial image width
    if (ih>iw) {//if portrait
        im.addClass('ww').removeClass('wh');//set width 100%
    } else {//if landscape
        im.addClass('wh').removeClass('ww');//set height 100%
    }
    //set offset
    var nh = im.height(),//new image height
        nw = im.width(),//new image width
        hd = (nh-th)/2,//half dif img/box height
        wd = (nw-tw)/2;//half dif img/box width
    if (nh<nw) {//if portrait
        im.css({marginLeft: '-'+wd+'px', marginTop: 0});//offset left
    } else {//if landscape
        im.css({marginTop: '-'+hd+'px', marginLeft: 0});//offset top
    }
});

css

.box{height:100px;width:100px;overflow:hidden}
.wh{height:100%!important}
.ww{width:100%!important}

这应该可以处理任何大小/方向,并且不仅会调整大小,还会偏移图像。都没有relativeabsolute定位。

做了一个小提琴:http://jsfiddle.net/filever10/W8aLN/

【讨论】:

  • 嗨。我想用这个很好的例子。但是当父 div 被 css 可见性隐藏时它不起作用。有人有解决方案吗?
  • @MrRebel 是的,按钮 不起作用 因为 line 28 也需要从 $(this).siblings('.box'); 更新到 $(this).siblings('ul').children('.box'); 它确实在 cmets 中提到了这一点在那一行... "//定义与动作相关的元素"。该按钮只是执行某些触发更改的操作的一般表示,您可以将其设为$('.nedmnthnguwnt') 以使事件发生。 jsfiddle.net/filever10/jnrsrcr3
  • 我喜欢这种方法,但是我必须交换添加和删除的类,并将另一个条件放入 if 语句中,if (ih>iw || th>tw),如果 (nhtw).
  • 喜欢它 :) 为任何尺寸的容器(不仅是正方形)更新:jsfiddle.net/W8aLN/265
  • 哇 :) 好吧,我不得不为全屏固定背景图像重新发明这个,因为使用 background-size:cover 时的 IE 行为是错误的。是的,我忘了提到应该先加载图像,我为此使用了一个小插件,imagesloaded.js
【解决方案4】:

同样,对于它的价值,可以通过设置“宽度”和“高度”来产生相同的效果(设置它们可能会破坏这种方法):

min-width: 100%; min-height: 100%;

min-width: (your desired percent of viewport width)vw; min-height: (your desired percent of viewport height)vh;

overflow: hidden;

在父级上

:)

【讨论】:

  • 这是一个简洁而优秀的解决方案!
【解决方案5】:

这个想法是为图像制作额外的包装器:

<div class="wrap">
  <div class="inner">
    <img src="http://placehold.it/350x150">
  </div>
</div>

并使用这样的 CSS:

.wrap {
  position: relative;
  width: 100%;
  height: 200px;
  background: rgba(255, 0, 0, 0.3);
  overflow: hidden;
}

.inner {
  position: absolute;
  min-width: 100%;
  height: 100%;
  left: 50%;
  -moz-transform: translateX(-50%);
  -o-transform: translateX(-50%);
  -ms-transform: translateX(-50%);
  -webkit-transform: translateX(-50%);
  transform: translateX(-50%);
}

.inner img {
  position: absolute;
  min-height: 100%;
  min-width: 100%;
  top: 50%;
  left: 50%;
  -moz-transform: translate(-50%, -50%);
  -o-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

这是工作示例:https://jsfiddle.net/kr60jroe/

【讨论】:

  • 似乎不适用于您的示例中的所有情况。例如,3000x2010 图像超出了其容器的边界。
【解决方案6】:

来自https://developer.mozilla.org/en-US/docs/Web/CSS/background-size

cover
    This keyword specifies that the background image should be scaled to be as small as possible while ensuring both its dimensions are greater than or equal to the corresponding dimensions of the background positioning area.

因此,您正在考虑创建width: 100%height: 100%,以在父div 中创建重叠。所以我们可以使用如下逻辑:

var makeBackgroundCover = function (div) {
    $(div + " img").css("height", "100%");
    if ($(div + " img").width() < $(div).width()) {
        $(div + " img").css({
            "height": "auto",
            "width": "100%"
        });
    }
}

下面的小提琴展示了这个函数在水平和垂直图像上的工作。

http://jsfiddle.net/2r5Cb/

【讨论】:

  • 这是否也像 background-size: cover 那样使图像居中?
  • background-size: cover 不会使图像居中。如果您查看我的 jsfiddle,您会发现我已包含 background-size: cover 比较图像以显示此函数创建了相同的复制。
  • 你完全正确,但看起来最初的问题希望发生这种情况,或者它不会要求尺寸定位。
  • 很好的答案,我喜欢你遵循实际规范。
【解决方案7】:

这是我的方法:

//collect the nodes
var parent = $('.box');
var img = $('image', box);

//remove width and height attributes
img.removeAttr('width');
img.removeAttr('height');

//set initial width
img.attr('width', parent.width());

//if it's not enough, increase the width according to the height difference
if (img.height() < parent.height()) {
    img.css('width', img.width() * parent.height() / img.height());
}

//position the image in the center
img.css({
    left: parseInt((img.width() - parent.width())/-2) + 'px',
    top: parseInt((img.height() - parent.height())/-2) + 'px'
});

FIDDLE

【讨论】:

  • 我喜欢这个解决方案,因为它减少了打字。虽然如果第一次尺寸不正确,它会计算并设置图像的尺寸 两次
【解决方案8】:

这是一个干净的 JavaScript 函数来执行此操作和一个实现示例:

function backgroundCover(elementSizes, containerSizes) {
    var elementRatio = elementSizes.width / elementSizes.height,
        containerRatio = containerSizes.width / containerSizes.height;
        width = null,
        height = null;
    if (containerRatio > elementRatio) {
        width = Math.ceil( containerSizes.width );
        height = Math.ceil( containerSizes.width / elementRatio );
    } else {
        width = Math.ceil( containerSizes.height * elementRatio );
        height = Math.ceil( containerSizes.height );
    }
    return { width, height };
}

这是一个实现示例:

HTML

<!-- Make sure the img has width and height attributes. The original image's width and height need to be set in order to calculate the scale ratio. -->
<div class="photo"><img src="photo.jpg" width="400" height="300"></div>

CSS

.photo {
    position: relative;
    overflow: hidden;
    width: 200px;
    padding-bottom: 75%; /* CSS technique to give this element a 4:3 ratio. */
}
.photo img {
    position: absolute;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    -moz-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}

JavaScript

$( window ).on( 'resize', function() {
    $( '.cover-photo' ).each( function() {
        var img = $( 'img', this ),
            imgWidth = img.attr( 'width' ),
            imgHeight = img.attr( 'height' ),
            containerWidth = $( this ).width(),
            containerHeight = $( this ).height(),
            newSizes = backgroundCover( { width: imgWidth, height: imgHeight }, { width: containerWidth, height: containerHeight } );
        img.css( {
            width: newSizes.width,
            height: newSizes.height
        } );
    } );
} );

【讨论】:

    【解决方案9】:

    在阅读接受的答案时,令我震惊的是,我们只是测试图像是“肖像”还是“风景”:

       if (ih>iw) {//if portrait
    

    在 OP 的情况下,这是正确的。但其他人可能正在处理矩形,应该考虑容器的纵横比和“子”图像:

        var int_container_width  = parseInt( $_container.width()  );
        var int_container_height = parseInt( $_container.height() );
        var num_container_aspect = int_container_width/int_container_height;
    
        var int_image_width      = parseInt( $_image.width() );
        var int_image_height     = parseInt( $_image.height());
        var num_image_aspect     = int_image_width/int_image_height;
    
        if ( num_image_aspect > num_container_aspect){
          num_scale = int_container_width/int_image_width * 100;
        } else {
          num_scale = int_container_height/int_image_height * 100;
        }
    

    【讨论】:

    • 如果父节点不是正方形,那肯定很重要,但如果是正方形,则无关紧要。
    【解决方案10】:

    这是一个纯 css 解决方案。你可以定义一个包装器:

    div.cover {
      position: fixed; 
      top: -50%; 
      left: -50%; 
      width: 200%; 
      height: 200%;
    }
    

    还有图片:

    img.cover {
      position: absolute; 
      top: 0; 
      left: 0; 
      right: 0; 
      bottom: 0; 
      margin: auto; 
      min-width: 50%;
      min-height: 50%;
      overflow-x: hidden;
    }
    

    这里是活生生的例子:

    http://codepen.io/ErwanHesry/pen/JcvCw

    【讨论】:

    • 这仅适用于图像小于其容器的情况(在本例中为 .box)。这将使图像增长以适合其容器,但不会使其缩小以适合其容器。
    • 当然这不是一个完美的解决方案,但它可能是唯一不使用 javascript 的解决方案。也许您可以使用非常小的 svg 图像来解决这个问题。
    【解决方案11】:

    你可以使用这个样式给图片标签:"object-fit:cover;" 这个链接也会支持你https://css-tricks.com/almanac/properties/o/object-fit/

    【讨论】:

      【解决方案12】:

      如果您希望图像在框中居中而不调整图像大小,只需使用以下代码:

      .box {
          width: 100px;
          height: 100px;
          overflow: hidden;
          position: relative;
      }
      .box img {
          width: 413px;
          height: 325px;
          position: absolute;
          left: 50%;
          top: 50%;
      }
      

      如果您希望调整图像大小以适合,请使用以下代码:

      .box {
          width: 100px;
          height: 100px;
      }
      .box img {
          width: 100%;
          height: auto;
      }
      

      如果图像宽于高,此代码将留下一些空白。如果这些都不起作用,您可以将图像设置为背景并使用background-size: cover;

      【讨论】:

      • 如果图片是横向的会怎样?
      • 第一段代码就像是通过一个小洞看图片,所以只要图片比盒子大,盒子就会被填满。对于第二段代码,横向图像将在其下方(上方取决于您的填充)留下空间。为避免这种情况,您可以添加第二张图片并删除所有填充和边距。
      【解决方案13】:

      对于任何遇到这个答案的人,就像我今天所做的那样,寻找一种适用于横向、纵向、矩形、正方形等图像和任意容器大小的解决方案,我在下面包含了我自己的代码。

      这也可以响应式地工作,您只需在窗口调整大小时再次运行它。

      JSFiddle

      http://jsfiddle.net/66c43ao1/

      HTML

      <div class="test">
          <div class="cover">
              <img src="http://d2ws0xxnnorfdo.cloudfront.net/character/meme/cool-dog.jpg" width="590" height="590"/>
          </div>
      </div>
      

      CSS

      /* modify the width and height below to demonstrate coverage */
      .test {
          height: 300px;
          position: relative;
          width: 500px;
      }
      /* you will need the below styles */
      .cover {
          height: 100%;
          left: 0;
          overflow: hidden;
          position: absolute;
          top: 0;
          width: 100%;
          z-index: 1;
      }
      

      JS

      $('.cover').each(function() {
          var containerHeight = $(this).height(),
              containerWidth  = $(this).width(),
              image           = $(this).children('img'),
              imageHeight     = image.attr('height'),
              imageWidth      = image.attr('width'),
              newHeight       = imageHeight,
              newWidth        = imageWidth;
      
          if (imageWidth < containerWidth) {
              // if the image isn't wide enough to cover the space, scale the width
              newWidth        = containerWidth;
              newHeight       = imageHeight * newWidth/imageWidth;
          }
          if (imageHeight < containerHeight) {
              // if the image isn't tall enough to cover the space, scale the height
              newHeight       = containerHeight;
              newWidth        = imageWidth * newHeight/imageHeight;
          }
      
          var marginLeft      = (newWidth - containerWidth)/2;
          var marginTop       = (newHeight - containerHeight)/2;
      
          image.css({
              marginLeft  : '-' + marginLeft + 'px',
              marginTop   : '-' + marginTop + 'px',
              height      : newHeight,
              width       : newWidth
          });
      });
      

      您当然可以使用诸如 Backstretch 之类的库来做同样的事情,但我发现这个解决方案更适合我的目的(不增加依赖项,重量更轻等)。

      【讨论】:

        【解决方案14】:

        我在下面创建了一个应该执行此操作的函数。我从accepted answer 中借用了一些逻辑,并通过为图像尺寸创建一个比率来调整它以与任何容器一起使用:容器尺寸,然后比较哪个更大以找出要调整的尺寸。还添加了一个 'center' 参数('true' 中心,false 将其设置为顶部/左侧)。

        我正在使用带有 translateX/Y 的 CSS3,但没有它也可以很容易地工作。

        代码如下:

        var coverImage = function(wrap, center) {
        
          if (typeof center === 'undefined') {
            center = true;
          }
        
            var wr = $(wrap),
                wrw = wr.width(),
                wrh = wr.height();
        
          var im = wr.children('img'),
                imw = im.width(),
                imh = im.height();
        
          var wratio = wrw / imw;
            var hratio = wrh / imh;
        
          //Set required CSS
          wr.css({'overflow' : 'hidden'});
          im.css({'position' : 'relative'});
        
        
          if (wratio > hratio) {
            im.width(wrw);
            im.css({'height' : 'auto'});
        
            if (center) {
              im.css({
                'top' : '50%',
                'transform' : 'translateY(-50%)'
              });
            }
          } else {
            im.height(wrh);
            im.css({'width' : 'auto'});
        
            if (center) {
              im.css({
                'left' : '50%',
                'transform' : 'translateX(-50%)'
              });
            }
          }
        }
        

        并检查 jsfiddle 以查看它的实际效果:https://jsfiddle.net/cameronolivier/57nLjoyq/2/

        【讨论】:

          【解决方案15】:

          我做了一些可以模拟 background-size:coverbackground-position:center 的东西。

          如果您想更改位置,只需更改样式“top”和“left”图片

          CSS

          .box{
              overflow:hidden;
              position:relative;
          }
          
          .box img{
              position: absolute;
              top: 50%;
              left: 50%;
              transform: translate(-50%, -50%);
              -ms-transform: translate(-50%, -50%);
              -webkit-transform: translate(-50%, -50%);
          }
          

          JS

          $('.box').each(function() {
               //aspect ratio of container
               var boxRatio = $(this).height() / $(this).width(); 
               //aspect ration of image
               var imageRatio = $(this).children('img').height() / $(this).children('img').width();
               //set width or height 100% depend of difference
               if (imageRatio > boxRatio) {
                    $(this).children('img').css({"width":"100%","height":"auto"});                
               } else {
                    $(this).children('img').css({"height":"100%","width":"auto" });
               }
          });
          

          此功能应在“加载”和“调整大小”事件时激活。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-04
            • 1970-01-01
            • 1970-01-01
            • 2012-04-25
            • 1970-01-01
            • 2011-12-26
            • 1970-01-01
            • 2014-03-24
            相关资源
            最近更新 更多