web-dev-qa-db-fra.com

Comment émuler la taille de l'arrière-plan: la couverture sur <img>?

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?

62
Alex

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/

10
FiLeVeR10

Pour ce que cela vaut: cela peut maintenant être fait avec CSS seul avec ...

La nouvelle propriété CSS object-fit ( support actuel du navigateur )

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!

VIOLON

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

134
Danield

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>
47
Vlatko

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

:)

5
SirRodge

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/

3
Paulius Kripaitis

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.

http://jsfiddle.net/2r5Cb/

2
MattDiamant

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

VIOLON

2
matewka

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

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:

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

1
Ruben Rizzi

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

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/

1
Mohamed Mamdouh

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

0
Santi Nunez

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/

0
Cameron

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

0
zsaat14

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 :

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

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

0
Heath