如何模拟背景大小:<img/>上的封面?

时间:2013-11-04 20:37:22

标签: javascript jquery math background-size

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

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

我知道我必须在框中添加overflow:hidden,图片需要position: absolute。但是什么样的公式能让我获得适合图像的新尺寸,并留下+顶部位置?

15 个答案:

答案 0 :(得分:125)

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

新的CSS属性object-fitCurrent browser support

只需在object-fit: cover;

上设置img即可

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

<强> FIDDLE

&#13;
&#13;
img {
  width: 100px;
  height: 100px;
}
.object-fit {
  display: block;
  object-fit: cover;
}
.original {
  width: auto;
  height: auto;
  display: block;
}
&#13;
<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>
&#13;
&#13;
&#13;

您可以在此webplatform article中详细了解此新属性。

此外,上面的文章中的a fiddle演示了object-fit属性的所有值。

答案 1 :(得分:44)

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

&#13;
&#13;
.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%);

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

答案 2 :(得分:10)

这可能更容易

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

答案 3 :(得分:5)

同样对于它的价值,可以通过设置&#34; width&#34;来产生相同的效果。和&#34;身高&#34; (设置它们可以打破这种方法):

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;

父母

上的

:)

答案 4 :(得分:3)

我们的想法是为图像制作额外的包装器:

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

使用这样的CSS:

&#13;
&#13;
.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%);
}
&#13;
&#13;
&#13;

这是一个有效的例子:https://jsfiddle.net/kr60jroe/

答案 5 :(得分:2)

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

答案 6 :(得分:2)

这是我的方法:

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

答案 7 :(得分:1)

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

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

答案 8 :(得分:1)

这是一个纯粹的CSS解决方案。您可以使用以下命令定义包装器:

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

和img:

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

答案 9 :(得分:1)

您可以将此样式用于图片标记:&#34; object-fit:cover;&#34; 此链接还将为您https://css-tricks.com/almanac/properties/o/object-fit/

提供支持

答案 10 :(得分:1)

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

答案 11 :(得分:0)

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

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

答案 12 :(得分:0)

对于今天我正在寻找可以处理横向,纵向,矩形,正方形等图像和任意容器尺寸的解决方案而遇到此答案的任何人,我在下面都包含了我自己的代码。

这也会起作用,只要窗口调整大小,你就需要再次运行它。

<强>的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这样的库来做同样的事情,但我发现这个解决方案对我的目的来说更好(没有增加依赖性,减轻重量等)。

答案 13 :(得分:0)

我在下面创建了一个应该这样做的函数。我借用了accepted answer中的一些逻辑,并通过创建图像尺寸比例来调整它以适用于任何容器:容器尺寸,然后比较哪个更大来计算要调整的尺寸。还增加了一个中心&#39;参数(&#39; true&#39; center,false将其设置为top / left)。

我在使用CSSX时使用了translateX / Y,但是如果没有足够的话可以让它工作。

以下是代码:

UINT camThread1( LPVOID pParam )
{
CDlg* pView = (CMyDlg*) pParam;
boost::asio::io_service io_service;

// to be able to interrupt the timer from the GUI Thread
pView->m_timer.reset(new boost::asio::deadline_timer(io_service)); 

boost::posix_time::ptime lastLoop;
typedef boost::asio::time_traits<boost::posix_time::ptime> time_traits_t;
lastLoop = time_traits_t::now();
while (1)
{
  boost::posix_time::ptime nextFrameTime;
  // calculate the time to wait
  nextFrameTime = lastFrameTime + boost::posix_time::seconds(pView->m_interval);

  // start the timer
  pView->m_timer->expires_at(nextFrameTime);
  pView->m_timer->async_wait(boost::bind(&CDlg::timer_handler, pView, boost::asio::placeholders::error));
  if(io_service.stopped()) {
    io_service.reset();
  }
  io_service.run();

  lastLoop = time_traits_t::now(); // get the current time

  // do something
}

并结帐jsfiddle以查看其实际效果:https://jsfiddle.net/cameronolivier/57nLjoyq/2/

答案 14 :(得分:0)

我做了一些可以模拟 background-size:cover background-position:center

如果您想更改位置,只需更改样式&#34; top &#34; &#34; &#34; 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" });
     }
});

此功能应在&#34; load&#34;上激活。并且&#34;调整大小&#34;事件