javascript - div - css background image size to fit
Cómo emular el fondo de pantalla: ¿tapa en<img>? (15)
¿Cómo puedo redimensionar y reposicionar la imagen dentro de un cuadro, de modo que cubra todo el cuadro, de forma similar a cómo funciona el background-size: cover
?
<div class="box" style="width: 100px; height: 100px;">
<img src="pic.jpg" width="413" height="325">
</div>
Sé que tengo que agregar el overflow:hidden
al cuadro y la imagen necesita una position: absolute
. ¿Pero cuál es la fórmula que me da el nuevo tamaño correcto para la imagen, y las posiciones superiores izquierda +?
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''
});
Aquí hay una función de 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
} );
} );
} );
Creé una función a continuación que debería hacerlo. Tomé prestada parte de la lógica de la respuesta aceptada y la ajusté para que funcione con cualquier contenedor creando una relación para la 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 agregó un argumento ''centro'' (''verdadero'' centros, falso lo establece arriba / izquierda).
Estoy usando CSS3 con translateX / Y, pero podría hacerlo funcionar sin suficiente 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 revise el jsfiddle para verlo en acción: https://jsfiddle.net/cameronolivier/57nLjoyq/2/
Desde 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.
Entonces, estás buscando hacer el width: 100%
o la height: 100%
, lo que creará una superposición dentro del div
principal. Entonces 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.
Esta es una solución pura de CSS. Puede definir un contenedor 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 en vivo:
Hice algo que podría funcionar para emular un fondo de tamaño: portada y posición de fondo: centro .
Si desea cambiar la posición simplemente cambie los estilos " arriba " y " 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 eventos de "carga" y "cambio de tamaño".
La idea es crear un contenedor adicional para la imagen:
<div class="wrap">
<div class="inner">
<img src="http://placehold.it/350x150">
</div>
</div>
Y usa dicho 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/
Lo suficientemente cerca, la solución de CSS puro para la simulación de la cubierta de tamaño de fondo usando la etiqueta img con muy buena compatibilidad con el navegador (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>
Mientras leo la respuesta aceptada, me parece que simplemente probamos si la imagen es ''retrato'' o ''paisaje'':
if (ih>iw) {//if portrait
En el caso del OP, es correcto. Pero otros podrían estar tratando con rectángulos y deberían tener en cuenta la relación de aspecto del contenedor y la imagen "infantil":
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;
}
Para cualquiera que encuentre esta respuesta como lo hice hoy buscando una solución que funcione con imágenes de paisajes, retratos, rectángulos, cuadrados, etc. y tamaños de contenedores arbitrarios, he incluido mi propio código a continuación.
Esto también funcionará de manera responsable, solo tendrá que ejecutarlo cada vez que la ventana cambie de tamaño.
JSFiddle :
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 utilizar bibliotecas como Backstretch que hacen lo mismo, pero esta solución me pareció mejor para mis propósitos (sin aumento de dependencias, menor peso, etc.).
Por lo que vale: esto ahora se puede hacer con CSS solo con ...
El nuevo object-fit propiedad CSS object-fit ( Soporte actual del navegador )
Solo establece object-fit: cover;
en el img
¡Ni siquiera necesitas envolver el img
en un 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>
Puede leer más sobre esta nueva propiedad en este artículo de plataforma web .
Además, aquí hay un violín del artículo anterior que muestra todos los valores de la propiedad de object-fit
.
Puede usar este estilo para la etiqueta de imagen: "object-fit: cover;" Este enlace también te ayudará https://css-tricks.com/almanac/properties/o/object-fit/
Si desea que la imagen esté centrada 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á algo de espacio en blanco si la imagen es más ancha que alta. Si ninguno de estos funciona, puede simplemente establecer la imagen como fondo y usar background-size: cover;
.
También por lo que vale, se puede producir el mismo efecto en lugar de establecer "ancho" y "alto" (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
:)
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 cambiará el tamaño, sino que compensará las imágenes. Todo sin posicionamiento relative
o absolute
.
hecho un violín: http://jsfiddle.net/filever10/W8aLN/