Como você estica uma imagem para preencher um <div> enquanto mantém a proporção da imagem?

201

Preciso fazer com que essa imagem se estenda ao tamanho máximo possível sem transbordar <div>ou distorcer a imagem.

Como não posso prever a proporção da imagem, não há como saber se deve usar:

<img src="url" style="width: 100%;">

ou

<img src="url" style="height: 100%;">

Não posso usar os dois (ou seja, style = "width: 100%; height: 100%;") porque isso esticará a imagem para se ajustar ao <div>.

O <div>tamanho é definido pela porcentagem da tela, o que também é imprevisível.

Giffyguy
fonte
2
Se você precisar que a imagem preencha altura ou largura para as dimensões correspondentes da div, só consigo pensar em usar javascript. É algo que você deseja explorar?
Ok

Respostas:

189

Atualização 2016:

Navegador moderno se comporta muito melhor. Tudo o que você precisa fazer é definir a largura da imagem para 100% ( demo )

.container img {
   width: 100%;
}

Como você não conhece a proporção, precisará usar alguns scripts. Aqui está como eu faria isso com o jQuery ( demo ):

CSS

.container {
    width: 40%;
    height: 40%;
    background: #444;
    margin: 0 auto;
}
.container img.wide {
    max-width: 100%;
    max-height: 100%;
    height: auto;
}
.container img.tall {
    max-height: 100%;
    max-width: 100%;
    width: auto;
}​

HTML

<div class="container">
 <img src="http://i48.tinypic.com/wrltuc.jpg" />
</div>
<br />
<br />
<div class="container">
 <img src="http://i47.tinypic.com/i1bek8.jpg" />
</div>

Roteiro

$(window).load(function(){
 $('.container').find('img').each(function(){
  var imgClass = (this.width/this.height > 1) ? 'wide' : 'tall';
  $(this).addClass(imgClass);
 })
})
Mottie
fonte
O usuário pode ver a imagem antes do redimensionamento? Alguém testou isso?
precisa saber é o seguinte
A solução está quase correta, basta inverter a altura e a largura no css: se a imagem for 'alta', a largura deve ser 100% e não a altura (que será maior e transborda). O contrário é para fotos amplas.
Mbritto
@mbritto: Você está certo, eu tive que mudar o css para max-largura / altura e eu adicionei uma demonstração
Mottie
@Mottie há uma maneira para atender a uma imagem de tamanho 930 px de largura para um recipiente de 960 px, sem perder a qualidade da imagem
Vivek Dragão
15
Por que essa é a resposta aceita? A questão é sobre as imagens serem muito pequenas para o contêiner. ou seja, como uma imagem pode ser dimensionada para preencher a largura ou a altura do contêiner, sem prejudicar a proporção da imagem. Além disso, em sua demonstração, remover as propriedades width:autoou height:autonão afeta a exibição de suas imagens. Por uma questão de fato, de todas as propriedades que você está aplicando à imagem, max-width: 100%tem algum efeito e afeta apenas a imagem da paisagem. Mas o mais importante é que sua resposta não ajuda a esticar uma imagem pequena para encher um recipiente maior.
matty
78

Existe uma maneira muito mais fácil de fazer isso usando apenas CSSeHTML :

HTML:

<div class="fill"></div>

CSS:

.fill {
    overflow: hidden;
    background-size: cover;
    background-position: center;
    background-image: url('path/to/image.jpg');
}

Isso colocará sua imagem como plano de fundo e a estenderá para caber no divtamanho sem distorção.

Ryan
fonte
isso é possível com um número indefinido de imagens?
TrtG 25/02
background-size: cover;é a verdadeira magia aqui, e é CSS3, mas tem suporte ao navegador razoável na maioria das versões recentes (ver: w3schools.com/cssref/css3_pr_background-size.asp )
Jon Kloske
1
Pode valer a pena incluindo o URL da imagem no HTML, a fim de estilo e conteúdo separado, ou seja<div style="background-image: url('path/to/image.jpg');" class="fill"></div>
binaryfunt
background-size: cover não mantém a proporção, partes da imagem que não são proporcionais ao elemento são cortadas. Consulte aqui
Alex_Zhong 30/01
@Alex_Zhong, você entende mal a proporção. A proporção da imagem significa que a imagem não é esticada em nenhuma direção (portanto, um círculo perfeito não se tornaria oval em largura ou altura). O corte pode ser uma parte necessária da manutenção da proporção (como no caso de uso do OP).
Jeremy Moritz
70

Não é uma solução perfeita, mas esse CSS pode ajudar. O zoom é o que faz esse código funcionar e, teoricamente, o fator deve ser infinito para funcionar idealmente para imagens pequenas - mas 2, 4 ou 8 funcionam bem na maioria dos casos.

#myImage {
    zoom: 2;  //increase if you have very small images

    display: block;
    margin: auto;

    height: auto;
    max-height: 100%;

    width: auto;
    max-width: 100%;
}
Prouda
fonte
1
Eu gostaria que isso funcionasse no Firefox. Por que nenhum zoomamor do Firefox !?
matty
1
O Firefox ainda não foi zoomimplementado, mas aqui está o link do bug para referência futura: bugzilla.mozilla.org/show_bug.cgi?id=390936 #
Adam Taylor
31

Se puder, use imagens de fundo e defina background-size: cover . Isso fará com que o plano de fundo cubra todo o elemento.

CSS

div {
  background-image: url(path/to/your/image.png);
  background-repeat: no-repeat;
  background-position: 50% 50%;
  background-size: cover;
}

Se você está preso ao uso de imagens embutidas, existem algumas opções. Primeiro, existe

ajuste de objeto

Esta propriedade atua em imagens, vídeos e outros objetos semelhantes a background-size: cover.

CSS

img {
  object-fit: cover;
}

Infelizmente, o suporte ao navegador não é tão bom com o IE até a versão 11, não suportando nada. A próxima opção usa jQuery

CSS + jQuery

HTML

<div>
  <img src="image.png" class="cover-image">
</div>

CSS

div {
  height: 8em;
  width: 15em;
}

Plug-in jQuery personalizado

(function ($) {
  $.fn.coverImage = function(contain) {
    this.each(function() {
      var $this = $(this),
        src = $this.get(0).src,
        $wrapper = $this.parent();

      if (contain) {
        $wrapper.css({
          'background': 'url(' + src + ') 50% 50%/contain no-repeat'
        });
      } else {
        $wrapper.css({
          'background': 'url(' + src + ') 50% 50%/cover no-repeat'
        });
      }

      $this.remove();
    });

    return this;
  };
})(jQuery);

Use o plugin como este

jQuery('.cover-image').coverImage();

Ele pega uma imagem, define-a como uma imagem de plano de fundo no elemento wrapper da imagem e remove a imgtag do documento. Por fim, você poderia usar

CSS puro

Você pode usar isso como um substituto. A imagem será ampliada para cobrir seu contêiner, mas não será reduzida.

CSS

div {
  height: 8em;
  width: 15em;
  overflow: hidden;
}

div img {
  min-height: 100%;
  min-width: 100%;
  width: auto;
  height: auto;
  max-width: none;
  max-height: none;
  display: block;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Espero que isso ajude alguém, codificação feliz!

daniels
fonte
Eu estava procurando por uma solução CSS pura para que as imagens preenchessem um determinado contêiner sem usar a imagem de fundo e o tamanho do plano de fundo, e o código CSS aqui funciona muito bem para> = IE9 e navegadores modernos. Demonstração do CodePen aqui
FLOQ Design
No CSS puro , eu removi min-e mudei para width: 100%; height: 100%;e trabalhei! solução incrível! +1 Obrigado!
Guilherme Nascimento
1
background-size: containtambém é útil se você deseja que nenhuma imagem seja cortada.
Ponkadoodle
Você pode adicionar zoom:0.001à solução Pure CSS para reduzir.
Ivor Zhou
12

Atualização 2019.

Agora você pode usar a object-fitpropriedade css que aceita os seguintes valores:fill | contain | cover | none | scale-down

https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit

Como exemplo, você pode ter um contêiner que contém uma imagem.

<div class="container">
    <img src="" class="container_img" />
</div>

.container {
    height: 50px;
    width: 50%;

.container_img {
    height: 100%;
    width: 100%;
    object-fit: cover;
Ed Stennett
fonte
7

Isso é impossível com apenas HTML e CSS, ou pelo menos exótico e complicado. Se você deseja adicionar algum javascript, aqui está uma solução usando o jQuery:

$(function() {
    $(window).resize(function() {
        var $i = $('img#image_to_resize');
        var $c = $img.parent();
        var i_ar = $i.width() / $i.height(), c_ar = $c.width() / $c.height();            
        $i.width(i_ar > c_ar ? $c.width() : $c.height() * (i_ar));
    });
    $(window).resize();
});

Isso redimensionará a imagem para que ela caiba sempre dentro do elemento pai, independentemente do tamanho. E como está ligado ao$(window).resize() evento, quando o usuário redimensiona a janela, a imagem é ajustada.

Isso não tenta centralizar a imagem no contêiner, isso seria possível, mas acho que não é isso que você procura.

Tatu Ulmanen
fonte
4
Eu assumo $ img.parent (); realmente deve ser $ i.parent ();
precisa saber é o seguinte
5

Defina a largura e a altura da containerdiv externa . Em seguida, use o estilo abaixo em img:

.container img{
    width:100%;
    height:auto;
    max-height:100%;
}

Isso ajudará você a manter uma proporção do seu img

Chintan Bhatt
fonte
6
não preencherá a div.
Sven van den Boogaart
5

Se você deseja definir uma largura ou altura máxima (para que não seja muito grande) enquanto mantém a proporção das imagens, você pode fazer o seguinte:

img{
   object-fit: contain;
   max-height: 70px;
}
Bohao LI
fonte
4

Me deparei com essa pergunta procurando um problema semelhante. Estou criando uma página da Web com design responsivo e a largura dos elementos colocados na página é definida como uma porcentagem da largura da tela. A altura é definida com um valor vw.

Como estou adicionando postagens com PHP e um back-end de banco de dados, o CSS puro estava fora de questão. No entanto, eu achei a solução jQuery / javascript um pouco problemática, então eu vim com uma solução elegante (então eu me acho pelo menos).

HTML (ou php)

div.imgfill {
  float: left;
  position: relative;
  background-repeat: no-repeat;
  background-position: 50%  50%;
  background-size: cover;
  width: 33.333%;
  height: 18vw;
  border: 1px solid black; /*frame of the image*/
  margin: -1px;
}
<div class="imgfill" style="background-image:url(source/image.jpg);">
  This might be some info
</div>
<div class="imgfill" style="background-image:url(source/image2.jpg);">
  This might be some info
</div>
<div class="imgfill" style="background-image:url(source/image3.jpg);">
  This might be some info
</div>

Usando style = "", é possível que o PHP atualize minha página dinamicamente e o estilo CSS, juntamente com style = "", acabe em uma imagem perfeitamente coberta, dimensionada para cobrir a div-tag dinâmica.

Christian Jensen
fonte
4

Para esticar a imagem até o tamanho máximo possível sem transbordar nem distorcer a imagem.

Aplique...

img {
  object-fit: cover;
  height: -webkit-fill-available;
}

estilos para a imagem.

ianbeans
fonte
3

Usando esse método, você pode preencher sua div com a proporção variável da imagem de divs e imagens.

jQuery:

$(window).load(function(){
   $('body').find(.fillme).each(function(){
      var fillmeval = $(this).width()/$(this).height();
      var imgval = $this.children('img').width()/$this.children('img').height();
      var imgClass;
      if(imgval > fillmeval){
          imgClass = "stretchy";
      }else{
          imgClass = "stretchx";
      }
      $(this).children('img').addClass(imgClass);
   });
});

HTML:

<div class="fillme">
   <img src="../images/myimg.jpg" />
</div>

CSS:

.fillme{
  overflow:hidden;
}
.fillme img.stretchx{
  height:auto;
  width:100%;
}
.fillme img.stretchy{
  height:100%;
  width:auto;
}
user1994142
fonte
3

Isso fez o truque para mim

div img {
    width: 100%;
    min-height: 500px;
    width: 100vw;
    height: 100vh;
    object-fit: cover;
}
Developer_D
fonte
2

se você trabalha com tag IMG, é fácil.

Eu fiz isso:

<style>
        #pic{
            height: 400px;
            width: 400px;
        }
        #pic img{
            height: 225px;               
            position: relative;
            margin: 0 auto;
        }
</style>

<div id="pic"><img src="images/menu.png"></div>

$(document).ready(function(){
            $('#pic img').attr({ 'style':'height:25%; display:none; left:100px; top:100px;' })
)}

mas não achei como fazê-lo funcionar com Enicone #pic {background: url (img / menu.png)}? obrigado

aleXela
fonte
fez uma alteração e encontrou uma resposta para o meu problema! Não, isso ajudará a alguém. background-image: url (images / menu.png); repetição em segundo plano: sem repetição; posição: absoluta; tamanho do plano de fundo: 300 px; altura: 100%; largura: 100%; e você pode alterar o valor do fundo de tamanho usando javascript ou jquery (.attr ({ 'estilo': 'background-size: 150px auto; esquerda: 50px; top: 50px;'}))
aleXela
2

Eu tive um problema semelhante. Eu resolvi com apenas CSS .

Basicamente, Object-fit: coverajuda você a realizar a tarefa de manter a proporção enquanto posiciona uma imagem dentro de uma div.

Mas o problema era Object-fit: cover não estava funcionando no IE e estava usando 100% de largura e 100% de altura e proporção e distorção. Em outras palavras, o efeito de zoom da imagem não estava lá no que eu estava vendo no chrome.

A abordagem adotada foi posicionar a imagem dentro do contêiner com absoluta e, em seguida, colocá-la no centro usando a combinação:

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

Uma vez no centro, dou a imagem,

// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;

// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;

Isso faz com que a imagem obtenha o efeito de Object-fit: cover.


Aqui está uma demonstração da lógica acima.

https://jsfiddle.net/furqan_694/s3xLe1gp/

Essa lógica funciona em todos os navegadores.

Furqan Rahamath
fonte
1

HTML:

<style>
#foo, #bar{
    width: 50px; /* use any width or height */
    height: 50px;
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
}
</style>

<div id="foo" style="background-image: url('path/to/image1.png');">
<div id="bar" style="background-image: url('path/to/image2.png');">

JSFiddle

... E se você deseja definir ou alterar a imagem (usando #foo como exemplo):

jQuery:

$("#foo").css("background-image", "url('path/to/image.png')");

JavaScript:

document.getElementById("foo").style.backgroundImage = "url('path/to/image.png')";
Patch92
fonte
1

Muitas das soluções encontradas aqui têm algumas limitações: algumas não funcionam no IE (ajuste de objeto) ou em navegadores antigos, outras soluções não aumentam a escala das imagens (apenas diminuem), muitas soluções não suportam o redimensionamento da janela e muitas são não genérico, espere resolução ou layout de correção (retrato ou paisagem)

Se o uso de javascript e jquery não for um problema, tenho esta solução com base no código do @Tatu Ulmanen. Corrigi alguns problemas e adicionei algum código caso a imagem fosse carregada dinamicamente e não estivesse disponível no início. Basicamente, a idéia é ter duas regras css diferentes e aplicá-las quando necessário: uma quando a limitação é a altura; portanto, precisamos mostrar barras pretas nas laterais e a outra regra css quando a limitação é a largura; mostre barras pretas na parte superior / inferior.

function applyResizeCSS(){
    var $i = $('img#imageToResize');
    var $c = $i.parent();
    var i_ar = Oriwidth / Oriheight, c_ar = $c.width() / $c.height();  
    if(i_ar > c_ar){
        $i.css( "width","100%");
        $i.css( "height","auto");          
    }else{
        $i.css( "height","100%");
        $i.css( "width","auto");
    }
}   
var Oriwidth,Oriheight;
$(function() {
    $(window).resize(function() {
        applyResizeCSS();
    });

    $("#slide").load(function(){
        Oriwidth  = this.width,
        Oriheight = this.height; 
        applyResizeCSS();
    }); 

    $(window).resize();
}); 

Para um elemento HTML como:

<img src="images/loading.gif" name="imageToResize" id="imageToResize"/> 
jolumg
fonte