Comment puis-je redimensionner et repositionner l'image à l'intérieur d'une boîte, de manière à ce qu'elle recouvre toute la boîte, de la même manière que background-size: cover
Fonctionne.
<div class="box" style="width: 100px; height: 100px;">
<img src="pic.jpg" width="413" height="325">
</div>
Je sais que je dois ajouter overflow:hidden
À la boîte et que l'image a besoin de position: absolute
. Mais quelle est la formule qui me donne la nouvelle taille correcte pour l'image, et les positions les plus à gauche?
cela peut être plus facile
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}
Cela devrait gérer n’importe quelle taille/orientation et non seulement redimensionner, mais aussi décaler les images. Tous sans relative
ou absolute
positionnement.
fait un violon: http://jsfiddle.net/filever10/W8aLN/
Pour ce que cela vaut: cela peut maintenant être fait avec CSS seul avec ...
Il suffit de définir object-fit: cover;
sur le img
Vous n'avez même pas besoin d'envelopper le img
dans 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>
Vous pouvez en savoir plus sur cette nouvelle propriété dans ce article webplatform .
En outre, voici n violon de l'article ci-dessus qui montre toutes les valeurs du object-fit
propriété.
Une solution CSS assez proche pour la simulation de la couverture de la taille de l’arrière-plan à l’aide de la balise img avec un très bon support du navigateur (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>
Aussi, pour ce que ça vaut, le même effet peut être produit en utilisant plutôt "largeur" et "hauteur" (leur réglage risquerait de briser cette approche):
min-width: 100%; min-height: 100%;
ou
min-width: (your desired percent of viewport width)vw; min-height: (your desired percent of viewport height)vh;
avec
overflow: hidden;
sur le parent
:)
L'idée est de créer un wrapper supplémentaire pour l'image:
<div class="wrap">
<div class="inner">
<img src="http://placehold.it/350x150">
</div>
</div>
Et utilisez un tel 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%);
}
Cet exemple fonctionne: https://jsfiddle.net/kr60jroe/
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.
Donc, soit vous cherchez à faire le width: 100%
ou la height: 100%
, celui qui créera un chevauchement dans le parent div
. Nous pouvons donc utiliser la logique suivante:
var makeBackgroundCover = function (div) {
$(div + " img").css("height", "100%");
if ($(div + " img").width() < $(div).width()) {
$(div + " img").css({
"height": "auto",
"width": "100%"
});
}
}
Le violon suivant montre que cette fonction fonctionne à la fois sur une image horizontale et verticale.
Voici mon approche:
//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'
});
En lisant la réponse acceptée, il me semble que nous vérifions simplement si l'image est 'portrait' ou 'paysage':
if (ih>iw) {//if portrait
Dans le cas de l'OP, c'est vrai. Mais d'autres pourraient avoir affaire à des rectangles et devraient prendre en compte les proportions du conteneur et l'image de l'enfant:
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;
}
Ceci est une solution pure CSS. Vous pouvez définir un wrapper avec:
div.cover {
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
}
et le img:
img.cover {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
overflow-x: hidden;
}
Voici l'exemple en direct:
Voici une fonction JavaScript propre pour faire cela et un exemple d'implémentation:
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 };
}
Voici un exemple d'implémentation:
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
} );
} );
} );
Vous pouvez utiliser ce style pour la balise d'image: "object-fit: cover;" Ce lien vous soutiendra également https://css-tricks.com/almanac/properties/o/object-fit/
J'ai fait quelque chose qui pourrait fonctionner pour émuler une taille de l'arrière-plan: cover et background-position: center .
Si vous voulez changer la position, changez simplement les styles " top " un " left "de l'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" });
}
});
Cette fonction doit être activée lors des événements "load" et "resize".
J'ai créé une fonction ci-dessous qui devrait le faire. J'ai emprunté une partie de la logique de réponse acceptée et je l'ai ajustée pour fonctionner avec n'importe quel conteneur en créant un rapport pour la dimension image: dimension du conteneur, puis comparé, ce qui est supérieur pour déterminer la dimension à ajuster. Également ajouté un argument 'center' ('true' centres, false le positionne en haut/à gauche).
J'utilise CSS3 avec translateX/Y, mais je pourrais le faire fonctionner sans cela assez facilement.
Voici le code:
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%)'
});
}
}
}
et vérifiez le jsfiddle pour le voir en action: https://jsfiddle.net/cameronolivier/57nLjoyq/2/
Si vous voulez centrer l'image dans la boîte sans la redimensionner, utilisez simplement le code suivant:
.box {
width: 100px;
height: 100px;
overflow: hidden;
position: relative;
}
.box img {
width: 413px;
height: 325px;
position: absolute;
left: 50%;
top: 50%;
}
Si vous souhaitez redimensionner l'image, utilisez le code suivant:
.box {
width: 100px;
height: 100px;
}
.box img {
width: 100%;
height: auto;
}
Ce code laissera un espace blanc si l'image est plus large que haute. Si aucune de ces méthodes ne fonctionne, vous pouvez simplement définir l'image en tant qu'arrière-plan et utiliser background-size: cover;
.
Pour tous ceux qui rencontrent cette réponse, comme je le faisais aujourd’hui, à la recherche d’une solution compatible avec les images de paysage, portrait, rectangle, carré, etc. et les tailles de conteneur arbitraires, j’ai inclus mon propre code ci-dessous.
Cela fonctionnera également en mode réponse, il vous suffira de l'exécuter à chaque fois que la fenêtre sera redimensionnée.
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
});
});
Vous pouvez bien sûr utiliser des bibliothèques telles que Backstretch qui font la même chose, mais j’ai trouvé cette solution meilleure pour mes besoins (pas d’augmentation des dépendances, un poids plus léger, etc.).