如何模拟背景大小:在<img>上覆盖

How to emulate background-size: cover on <img>?

本文关键字:img 覆盖 何模拟 模拟 背景      更新时间:2023-09-26

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

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

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

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

新的 CSS 属性对象适合(当前浏览器支持)

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

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

小提琴

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>

您可以在这篇网络平台文章中阅读有关此新属性的更多信息。

此外,这是上面文章中的小提琴,它演示了 object-fit 属性的所有值。

足够接近的纯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>

这可能更容易

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/

同样对于它的价值,可以通过而不是设置"宽度"和"高度"来产生相同的效果(顺便说一句,设置它们可能会破坏这种方法):

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;

在父级上

:)

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

<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/

从 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/

这是我的方法:

//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'
});

小提琴

这里有一个干净的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
        } );
    } );
} );

在阅读公认的答案时,我突然想到,我们只是简单地测试图像是"纵向"还是"横向":

   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;
    }

这是一个纯粹的 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

您可以将此样式用于图像标记:"对象适合:封面;"此链接还将支持您 https://css-tricks.com/almanac/properties/o/object-fit/

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

.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; .

对于像

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

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

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 之类的库来做同样的事情,但我发现这个解决方案更适合我的目的(不增加依赖项、更轻的重量等)。

我在下面创建了一个应该可以做到这一点的函数。我从接受的答案中借用了一些逻辑,并通过为图像尺寸创建一个比率来调整它以适用于任何容器:容器尺寸,然后比较哪个更大以计算要调整的维度。还添加了一个"中心"参数("真"中心,false 将其设置为上/左)。

我正在使用带有翻译X/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/

我做了一些可以模拟背景大小:封面背景位置:中心的东西。

如果要更改位置,只需更改img的"顶部"和"左侧"样式即可

.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" });
     }
});

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