Cómo emular background-size: cover on?


¿Cómo puedo cambiar el tamaño y reposicionar la imagen dentro de un cuadro, de tal manera que cubra todo el cuadro, similar a cómo funciona background-size: cover.

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

Sé que tengo que añadir overflow:hidden a la caja y la imagen necesita position: absolute. Pero ¿cuál es la fórmula que me da el nuevo tamaño correcto para la imagen, y la izquierda + posiciones superiores?

Author: Danield, 2013-11-05

15 answers

Esto puede ser más fácil

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}

Esto debería manejar cualquier tamaño/orientación, y no solo redimensionará, sino que desplazará las imágenes. Todos, sin relative o absolute posicionamiento.

Hizo un violín: http://jsfiddle.net/filever10/W8aLN/

 9
Author: FiLeVeR10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-04 01:41:50

Por lo que vale: esto ahora se puede hacer con CSS solo con...

La nueva propiedad CSS object-fit (Soporte actual del navegador )

Simplemente pon object-fit: cover; en el img

¡Ni siquiera necesitas envolver el img en un 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>

Puede leer más sobre esta nueva propiedad en este artículo de la plataforma web .

También, aquí está un violín de lo anterior artículo que muestra todos los valores de la propiedad object-fit.

 114
Author: Danield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-28 15:22:55

Lo suficientemente cerca, solución CSS pura para la simulación de cubierta de tamaño de fondo utilizando la etiqueta img con muy buen soporte para navegadores (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>
 43
Author: Vlatko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-30 00:56:59

La idea es hacer un envoltorio adicional para la imagen:

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

Y usar tales 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%);
}

Este es un ejemplo de trabajo: https://jsfiddle.net/kr60jroe /

 3
Author: Paulius Kripaitis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-06 08:06:39

También para lo que vale, el mismo efecto se puede producir en lugar de establecer "ancho" y "altura" (configurarlos podría romper este enfoque por cierto):

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

O

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

Con

overflow: hidden;

En el padre

:)

 3
Author: SirRodge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-30 13:36:17

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

Por lo tanto, estás buscando hacer el width: 100% o el height: 100%, lo que creará una superposición dentro del padre div. Así que podemos usar la siguiente lógica:

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

El siguiente violín muestra esta función trabajando tanto en una imagen horizontal como vertical.

Http://jsfiddle.net/2r5Cb /

 2
Author: MattDiamant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-04 21:07:39

Aquí está mi enfoque:

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

 2
Author: matewka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-04 21:26:56

Mientras leemos la respuesta aceptada, me sorprende que simplemente probemos si la imagen es 'retrato ' o'paisaje':

   if (ih>iw) {//if portrait

En el caso de la OP, eso es correcto. Pero otros podrían estar tratando con rectángulos y deberían tomar en consideración la relación de aspecto del contenedor y la imagen 'hija':

    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;
    }
 1
Author: Ideogram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-04 12:23:56

Esta es una solución css pura. Puede definir un wrapper con:

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

Y el img:

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

Aquí el ejemplo vivo:

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

 1
Author: Ruben Rizzi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-20 17:31:47

Si desea que la imagen se centre en el cuadro sin cambiar el tamaño de la imagen, simplemente use este código:

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

Si está buscando cambiar el tamaño de la imagen para que quepa, use el siguiente código:

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

Este código dejará algún espacio en blanco si la imagen es más ancha que alta. Si ninguna de estas opciones funciona, puede configurar la imagen como fondo y usar background-size: cover;.

 0
Author: zsaat14,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-04 20:59:04

Para cualquiera que suceda a través de esta respuesta como lo hice hoy en busca de una solución que funcione con imágenes de paisaje, retrato, rectángulo, cuadrado, etc. y tamaños de contenedores arbitrarios, he incluido mi propio código a continuación.

Esto también funcionará responsablemente, solo tendrá que ejecutarlo de nuevo cada vez que la ventana redimensionar.

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

Por supuesto, puede usar bibliotecas como Backstretch que hacen lo mismo, pero encontré que esta solución es mejor para mis propósitos (sin aumento de dependencias, peso más ligero, etc.).

 0
Author: Heath,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-21 14:36:45

He creado una función debajo que debería hacerlo. Tomé prestada parte de la lógica de la respuesta aceptada y la ajusté para trabajar con cualquier contenedor creando una relación para dimensión de la imagen : dimensión del contenedor y luego comparé cuál es mayor para calcular qué dimensión ajustar. También se ha añadido un argumento 'center' ('true' centers, false lo pone en la parte superior/izquierda).

Estoy usando CSS3 con translateX/Y, pero podría hacerlo funcionar sin él con bastante facilidad.

Aquí está el código:

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

Y comprueba el jsfiddle para verlo en acción: https://jsfiddle.net/cameronolivier/57nLjoyq/2 /

 0
Author: Cameron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:28

He hecho algo que podría funcionar para emular un background-size:cover y background-position:center.

Si desea cambiar la posición, simplemente cambie los estilos "arriba" an "izquierda" de la 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" });
     }
});

Esta función debe activarse en los eventos "load" y "resize".

 0
Author: Santi Nunez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-21 12:10:09

Puede usar este estilo para la etiqueta de imagen: "object-fit: cover;" Este enlace también te apoyará https://css-tricks.com/almanac/properties/o/object-fit /

 0
Author: Mohamed Mamdouh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-12 15:13:40

Aquí hay una función JavaScript limpia para hacer esto y un ejemplo de implementación:

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

Aquí hay un ejemplo de implementación:

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
        } );
    } );
} );
 0
Author: Gavin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-06 04:09:25