Dimensione a imagem para caber em uma caixa delimitadora

117

Existe uma solução somente CSS para dimensionar uma imagem em uma caixa delimitadora (mantendo a proporção de aspecto)? Isso funciona se a imagem for maior que o contêiner:

img {
  max-width: 100%;
  max-height: 100%;
}

Exemplo:

Mas eu quero aumentar a imagem até que uma dimensão seja 100% do contêiner.

Thomas Guillory
fonte
Você quer dizer altura: 100% e largura: 100%? você tem uma dimensão desejada que deseja alcançar? caso contrário, você também pode esticar a imagem e forçá-la a atingir essas dimensões também.
mikevoermans
@mikevoermans Veja meus dois primeiros exemplos: Quero esticar a imagem até que uma das dimensões seja 100% e a outra seja <= 100%
Thomas Guillory
@jacktheripper Conservando a proporção de aspecto, é claro ...
Thomas Guillory,
@gryzzly Os exemplos falam por si! Se eles tivessem olhado para os exemplos, isso seria óbvio.
Thomas Guillory,
@Artimuz discordo totalmente. Três das respostas às suas perguntas (incluindo a minha) sugerem que NÃO era óbvio.
Khan,

Respostas:

94

Observação: embora esta seja a resposta aceita, a resposta abaixo é mais precisa e atualmente é compatível com todos os navegadores se você tiver a opção de usar uma imagem de fundo.

Não, não existe uma maneira CSS única de fazer isso nas duas direções. Você poderia adicionar

.fillwidth {
    min-width: 100%;
    height: auto;
}

Para que um elemento sempre tenha 100% de largura e dimensione automaticamente a altura para a proporção, ou o inverso:

.fillheight {
    min-height: 100%; 
    width: auto;
}

para sempre dimensionar para altura máxima e largura relativa. Para fazer ambos, você precisará determinar se a proporção é maior ou menor do que o contêiner, e CSS não pode fazer isso.

O motivo é que o CSS não sabe a aparência da página. Ele define regras de antemão, mas só depois disso é que os elementos são renderizados e você sabe exatamente com quais tamanhos e proporções está lidando. A única maneira de detectar isso é com JavaScript.


Embora você não esteja procurando uma solução JS, vou adicionar uma de qualquer maneira, se alguém precisar. A maneira mais fácil de lidar com isso com JavaScript é adicionar uma classe com base na diferença de proporção. Se a proporção largura-altura da caixa for maior do que a da imagem, adicione a classe "largura de preenchimento", caso contrário, adicione a classe "altura de preenchimento".

Stephan Muller
fonte
7
Na verdade, há uma solução: definir o tamanho do fundo do CSS3 para conter. Veja minha resposta.
Thomas Guillory
Você está totalmente certo. Mesmo que seja um ano e meio depois agora, eu editei minha postagem.
Stephan Muller
4
Eu diria que esta é a resposta correta para a pergunta feita, que é o CSS para a tag img. Isso é relevante porque semanticamente a tag img é conteúdo, a imagem como plano de fundo para um div não. Embora algumas circunstâncias tornem isso impraticável (se você não souber a proporção de imagem x contêiner), para outras é o correto. Obrigado.
duncanwilcox
173

Graças ao CSS3 existe uma solução!

A solução é colocar a imagem como background-imagee definir background-sizecomocontain .

HTML

<div class='bounding-box'>
</div>

CSS

.bounding-box {
  background-image: url(...);
  background-repeat: no-repeat;
  background-size: contain;
}

Teste aqui: http://www.w3schools.com/cssref/playit.asp?filename=playcss_background-size&preval=contain

Compatibilidade total com os navegadores mais recentes: http://caniuse.com/background-img-opts

Para alinhar o div no centro, você pode usar esta variação:

.bounding-box {
  background-image: url(...);
  background-size: contain;
  position: absolute;
  background-position: center;
  background-repeat: no-repeat;
  height: 100%;
  width: 100%;
}
Thomas Guillory
fonte
1
Boa, embora minha resposta não esteja incorreta (você estava perguntando sobre o img especificamente), esta é uma ótima solução e eu deveria ter pensado nisso. O único problema é que o Internet Explorer 8 ainda é tão amplamente usado que eu não gostaria de confiar nele ainda, mas é uma boa captura mesmo assim.
Stephan Muller,
6
Defina-o para "cobrir" se não quiser nenhuma caixa de correio: background-size: contain;
arxpoetica
3
Note-se que você pode injetar URLs de imagem com HTML: <div class=image style="background-image: url('/images/foo.jpg');"></div>. Todos os outros estilos devem ser aplicados com CSS.
Andrey Mikhaylov - lolmaus
14
Eu diria que esta é uma abordagem terrível. Ao alterá-la para uma imagem de fundo, você está removendo o significado semântico da imagem no HTML.
animuson
14
@animuson: Ainda me ajudou, pois estou usando HTML / CSS para relatórios impressos e não pude me
importar
37

Esta é uma solução hackeada que descobri:

#image {
    max-width: 10%;
    max-height: 10%;
    transform: scale(10);
}

Isso aumentará a imagem dez vezes, mas a restringirá a 10% de seu tamanho final - limitando-a ao contêiner.

Ao contrário da background-imagesolução, isso também funcionará com <video>elementos.

Exemplo interativo:

Vladimir Panteleev
fonte
1
Eu amo essa solução. Ele não apenas responde à pergunta (eu sei, que pensamento), mas funciona perfeitamente em todos os navegadores modernos sem ter que recorrer a Javascript!
ndm13
2
Eu adoraria ver um violino disso. Em meu teste de colocar um img em um contêiner de 400x400, o img é cortado no canto
cyberwombat
3
Boa resposta! @Yashua Você precisa adicionar transform-origin: top leftpara interromper o corte. / Zombie
XwipeoutX de
Brilhante. Minha única preocupação seria uma possível perda de qualidade de imagem em um navegador mal codificado, mas em teoria deveria funcionar bem!
Codemonkey de
Interessante, mas não funciona no Chrome. Resulta em uma linha recortada da imagem.
MattK
23

Hoje, basta dizer objeto-ajuste: conter. O suporte é tudo menos o IE: http://caniuse.com/#feat=object-fit

Glenn Maynard
fonte
3
O IE tem apenas cerca de 16% de participação de mercado no momento em que este artigo foi escrito (12/09/2016 10:56) e continua diminuindo, então esta é a melhor resposta para mim: D
Zhang
8
Não edite as respostas de outras pessoas para corrigir coisas que não sejam erros de digitação ou links corrompidos. Eu não diria algo infantil como "Há um polyfill para navegadores de merda" em uma resposta SO, e não aprecio minha resposta ser editada para parecer que disse isso. se quiser usar suas palavras, coloque-as em sua própria resposta.
Glenn Maynard
Eu diria que o problema não é o IE, mas sim o Edge. Segundo caniuse, object-fitainda está em desenvolvimento para isso.
BairDev
Esta deve ser uma das respostas mais votadas de 2017 em diante ... De acordo com o link caniuse acima, 90% de todos os usuários globalmente agora usam um navegador que suporta isso
fgblomqvist
Acabei de postar uma resposta que funciona com e sem object-fit: stackoverflow.com/a/46456673/474031
gabrielmaldi
8

html:

    <div class="container">
      <img class="flowerImg" src="flower.jpg">
    </div>

css:

.container{
  width: 100px;
  height: 100px;
}


.flowerImg{
  width: 100px;
  height: 100px;
  object-fit: cover;
  /*object-fit: contain;
  object-fit: scale-down;
  object-position: -10% 0;
  object-fit: none;
  object-fit: fill;*/
}
Deke
fonte
5

Você pode fazer isso com CSS puro e suporte a navegador completo, tanto para imagens longas quanto horizontais ao mesmo tempo.

Aqui está um snippet que funciona no Chrome, Firefox e Safari (usando object-fit: scale-downe sem usar):

figure {
  margin: 0;
}

.container {
  display: table-cell;
  vertical-align: middle;
  width: 80px;
  height: 80px;
  border: 1px solid #aaa;
}

.container_image {
  display: block;
  max-width: 100%;
  max-height: 100%;
  margin-left: auto;
  margin-right: auto;
}

.container2_image2 {
  width: 80px;
  height: 80px;
  object-fit: scale-down;
  border: 1px solid #aaa;
}
Without `object-fit: scale-down`:

<br>
<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure class="container">
  <img class="container_image" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>

<br> Using `object-fit: scale-down`:

<br>
<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/EQgexUd.jpg">
</figure>

<br>

<figure>
  <img class="container2_image2" src="https://i.imgur.com/ptO8pGi.jpg">
</figure>

Gabrielmaldi
fonte
2

Outra solução sem imagem de fundo e sem a necessidade de um contêiner (embora os tamanhos máximos da caixa delimitadora devam ser conhecidos):

img{
  max-height: 100px;
  max-width: 100px;
  width: auto;    /* These two are added only for clarity, */
  height: auto;   /* as the default is auto anyway */
}


Se o uso de um contêiner for necessário, a largura máxima e a altura máxima podem ser definidas para 100%:

img {
    max-height: 100%;
    max-width: 100%;
    width: auto; /* These two are added only for clarity, */
    height: auto; /* as the default is auto anyway */
}

div.container {
    width: 100px;
    height: 100px;
}

Para isso, você teria algo como:

<table>
    <tr>
        <td>Lorem</td>
        <td>Ipsum<br />dolor</td>
        <td>
            <div class="container"><img src="image5.png" /></div>
        </td>
    </tr>
</table>
xerxeArt
fonte
1

Este exemplo para esticar a imagem proporcionalmente para caber na janela inteira. Uma improvisação para o código correto acima é adicionar$( window ).resize(function(){});

function stretchImg(){
    $('div').each(function() {
      ($(this).height() > $(this).find('img').height()) 
        ? $(this).find('img').removeClass('fillwidth').addClass('fillheight')
        : '';
      ($(this).width() > $(this).find('img').width()) 
        ? $(this).find('img').removeClass('fillheight').addClass('fillwidth')
        : '';
    });
}
stretchImg();

$( window ).resize(function() {
    strechImg();
});

Existem duas condições if. O primeiro continua verificando se a altura da imagem é menor que a div e aplica a .fillheightclasse, enquanto o próximo verifica a largura e aplica a .fillwidthclasse. Em ambos os casos, a outra classe é removida usando.removeClass()

Aqui está o CSS

.fillwidth { 
   width: 100%;
   max-width: none;
   height: auto; 
}
.fillheight { 
   height: 100vh;
   max-width: none;
   width: auto; 
}

Você pode substituir 100vhpor 100%se quiser esticar a imagem em um div. Este exemplo para esticar a imagem proporcionalmente para caber na janela inteira.

Sr. JCRP
fonte
O OP solicitou especificamente uma abordagem somente css.
Colt McCormack de
0

Você está procurando uma escala para cima, mas não para baixo?

div {
    border: solid 1px green;
    width: 60px;
    height: 70px;
}

div img {
    width: 100%;
    height: 100%;
    min-height: 500px;
    min-width: 500px;
    outline: solid 1px red;
}

Isso, entretanto, não bloqueia a proporção de aspecto.

Ericosg
fonte
5
Tente ser um pouco mais claro com suas expectativas antes de votar contra a resposta de alguém. Especialmente quando eles responderam à sua pergunta antes de você esclarecê-la com as edições.
Khan,
2
Além disso, tente ser mais educado. Ninguém vai te ajudar se você falar assim.
Misha Reyzlin
@Artimuz Minhas desculpas se eu errar a orientação de você, mas não parecia claro para mim que você desejava manter a proporção de aspecto, e é por isso que comentei isso especificamente. Além disso, você notará que colei um trecho de seu código dos exemplos. Eu acredito em manter a altura: automático; fará isso por você se você especificar uma largura.
ericosg
0

Usei a mesa para centralizar a imagem dentro da caixa. Ele mantém a relação de aspecto e dimensiona a imagem de uma forma totalmente dentro da caixa. Se a imagem for menor do que a caixa, ela é mostrada como está no centro. O código abaixo usa uma caixa de 40px de largura e 40px de altura. (Não tenho certeza se funciona bem porque removi de outro código mais complexo e simplifiquei um pouco)

CSS:

.SmallThumbnailContainer
{
    display: inline-block; position: relative;
    float: left;    
    width: 40px;
    height: 40px;
    border: 1px solid #ccc;
    margin: 0px; padding: 0px;
}
.SmallThumbnailContainer { width: 40px; margin: 0px 10px 0px 0px; } 
.SmallThumbnailContainer tr { height: 40px; text-align: center; }
.SmallThumbnailContainer tr td { vertical-align: middle; position: relative; width: 40px;  }
.SmallThumbnailContainer tr td img { overflow: hidden; max-height: 40px; max-width: 40px; vertical-align: middle; margin: -1px -1px 1px -1px; }

HTML:

<table class="SmallThumbnailContainer" cellpadding="0" cellspacing="0">
    <tr><td>
        <img src="thumbnail.jpg" alt="alternative text"/>
    </td></tr>
    </table>
Antti
fonte
0

A maneira mais limpa e simples de fazer isso:

Primeiro, algum CSS:

div.image-wrapper {
    height: 230px; /* Suggestive number; pick your own height as desired */
    position: relative;
    overflow: hidden; /* This will do the magic */
    width: 300px; /* Pick an appropriate width as desired, unless you already use a grid, in that case use 100% */
}
img {
    width: 100%;
    position: absolute;
    left: 0;
    top: 0;
    height: auto;
}

O HTML:

<div class="image-wrapper">
  <img src="yourSource.jpg">
</div>

Isso deve funcionar!

Robert Eetheart
fonte
0

Isso me ajudou:

.img-class {
  width: <img width>;
  height: <img height>;
  content: url('/path/to/img.png');
}

Em seguida, no elemento (você pode usar javascript ou consultas de mídia para adicionar capacidade de resposta):

<div class='img-class' style='transform: scale(X);'></div>

Espero que isto ajude!

bman93
fonte
-3
.boundingbox {
    width: 400px;
    height: 500px;
    border: 2px solid #F63;
}
img{
    width:400px;
    max-height: 500px;
    height:auto;
}

Estou editando minha resposta para explicar melhor minha solução, pois tenho um voto negativo.

Com os estilos definidos como mostrado acima em css, agora o seguinte div html mostrará a imagem sempre ajustada na largura e ajustará a proporção de aspecto alta à largura. Assim, a imagem será dimensionada para caber em uma caixa delimitadora, conforme perguntado na pergunta.

<div class="boundingbox"><img src="image.jpg"/></div>
Zeeawan
fonte
Essa resposta só funciona quando a caixa é mais alta do que larga.
XwipeoutX de