Existe um equivalente ao tamanho do plano de fundo: cobrir e conter os elementos da imagem?

241

Eu tenho um site com muitas páginas e diferentes imagens de plano de fundo, e as exibo em CSS como:

body.page-8 {
    background: url("../img/pic.jpg") no-repeat scroll center top #000;
    background-size: cover;
}

No entanto, quero mostrar imagens diferentes (em tela cheia) em uma página usando <img>elementos e quero que elas tenham as mesmas propriedades da background-image: cover;propriedade acima (as imagens não podem ser exibidas em CSS, devem ser exibidas no documento HTML).

Normalmente eu uso:

div.mydiv img {
    width: 100%;
}

Ou:

div.mydiv img {
    width: auto;
}

para tornar a imagem completa e responsiva. No entanto, a imagem encolhe muito ( width: 100%) quando a tela fica muito estreita e mostra a cor de fundo do corpo na tela inferior. O outro método, width: auto;apenas aumenta a imagem em tamanho real e não responde ao tamanho da tela.

Existe uma maneira de exibir a imagem da mesma maneira que background-size: coverfaz?

stormpat
fonte
Ótima pergunta.
wonsuc

Respostas:

380

Solução 1 - A propriedade de ajuste do objeto ( Falta suporte ao IE )

Basta definir object-fit: cover;no img.

body {
  margin: 0;
}
img {
  display: block;
  width: 100vw;
  height: 100vh;
  object-fit: cover;
}
<img src="http://lorempixel.com/1500/1000" />

Consulte MDN - sobre object-fit: cover:

O conteúdo substituído é dimensionado para manter sua proporção e preencher a caixa de conteúdo inteira do elemento. Se a proporção do objeto não corresponder à proporção da sua caixa, o objeto será cortado para caber.

Além disso, consulte esta demonstração do Codepen, que compara object-fit: coveraplicado a uma imagem e background-size: coveraplicado a uma imagem de plano de fundo


Solução 2 - Substitua o img por uma imagem de fundo por css

body {
  margin: 0;
}
img {
  position: fixed;
  width: 0;
  height: 0;
  padding: 50vh 50vw;
  background: url(http://lorempixel.com/1500/1000/city/Dummy-Text) no-repeat;
  background-size: cover;
}
<img src="http://placehold.it/1500x1000" />

Danield
fonte
3
No momento deste comentário, o ajuste de objeto ainda não é suportado por nenhuma versão do Internet Explorer (mesmo Edge). Está no entanto em consideração .
Mike Kormendy
3
o ajuste de objeto ainda não é suportado no IE. Eu ficaria longe se estivesse no local de produção e você se preocupasse com os usuários do IE.
Travis Michael Heller
2
Você também pode adicionar polyfill para # 1 para IE e velhos Safari: github.com/bfred-it/object-fit-images
Valera Tumash
1
Cuidado com a segunda solução. É melhor não confiar no vh em navegadores móveis: nicolas-hoizey.com/2015/02/…
sudokai
1
@RoCk, você pode encontrar coisas assim no caniuse: caniuse.com/#search=background-att :) PS Acho que todos podemos ter certeza de que o IE nunca obterá suporte para esse recurso e, como também não há polifill, nós ' é ferrado ou preso com hacks JS / CSS até que a MS decida que é hora de (finalmente) "assassinar" o IE removendo-o do Windows.
SidOfc 7/08/19
31

Na verdade, existe uma solução css bastante simples que até funciona no IE8:

.container {
  position: relative;
  overflow: hidden;
  /* Width and height can be anything. */
  width: 50vw;
  height: 50vh;
}

img {
  position: absolute;
  /* Position the image in the middle of its container. */
  top: -9999px;
  right: -9999px;
  bottom: -9999px;
  left: -9999px;
  margin: auto;
  /* The following values determine the exact image behaviour. */
  /* You can simulate background-size: cover/contain/etc.
     by changing between min/max/standard width/height values.
     These values simulate background-size: cover
  */
  min-width: 100%;
  min-height: 100%;
}
<div class="container">
    <img src="http://placehold.it/200x200" alt="" />
</div>

Simon
fonte
9
Isso não replica o comportamento da cobertura, mas corta uma seção centralizada do src img. Veja jsfiddle.net/sjt71j99/4 - o primeiro img é a sua colheita, o próximo é via tamanho de fundo: capa, ou seja, o que queremos, o terceiro é o img original. Encontrei para imagens da paisagem substituir min-height e min-width por max-height: 100%; para retrato, use largura máxima: 100%. Seria bom se houvesse uma solução que funcionasse para paisagem ou retrato. Alguma ideia? Esta é a melhor solução entre navegadores que eu já vi até agora.
terraling
1
Você está certo, ele não faz exatamente a mesma coisa, eu tentei algumas coisas, mas parece que você realmente não consegue replicar a capa 100%, funciona desde que a imagem seja menor que o contêiner em uma dimensão Apesar.
Simon
@terraling, eu sei que é um comentário antigo, mas verifique minha resposta . Ele usa transform para posicionar o img no centro.
Thiago Barcala
30

Supondo que você possa ter um elemento de contêiner que deseja preencher, isso parece funcionar, mas parece um pouco imprudente. Em essência, eu apenas uso min/max-width/heightem uma área maior e, em seguida, redimensiono essa área para as dimensões originais.

.container {
  width: 800px;
  height: 300px;
  border: 1px solid black;
  overflow:hidden;
  position:relative;
}
.container.contain img {
  position: absolute;
  left:-10000%; right: -10000%; 
  top: -10000%; bottom: -10000%;
  margin: auto auto;
  max-width: 10%;
  max-height: 10%;
  -webkit-transform:scale(10);
  transform: scale(10);
}
.container.cover img {
  position: absolute;
  left:-10000%; right: -10000%; 
  top: -10000%; bottom: -10000%;
  margin: auto auto;
  min-width: 1000%;
  min-height: 1000%;
  -webkit-transform:scale(0.1);
  transform: scale(0.1);
}
<h1>contain</h1>
  <div class="container contain">
    <img 
       src="https://www.google.de/logos/doodles/2014/european-parliament-election-2014-day-4-5483168891142144-hp.jpg" 
       />
    <!-- 366x200 -->
  </div>
  <h1>cover</h1>
  <div class="container cover">
    <img 
       src="https://www.google.de/logos/doodles/2014/european-parliament-election-2014-day-4-5483168891142144-hp.jpg" 
       />
    <!-- 366x200 -->
  </div>

Ulrich Schwarz
fonte
1
Totalmente de acordo. Esta é a melhor solução de todas as opções acima para uso geral.
Varis Vītols
É ótimo. Isso me ajudou. Obrigado
Raman Nikitsenka
14

Encontrei uma solução simples para emular a cobertura e a contenção, que é CSS puro, e funciona para contêineres com dimensões dinâmicas e também não faz nenhuma restrição na proporção da imagem.

Observe que, se você não precisar oferecer suporte ao IE ou Edge antes dos 16 anos, é melhor usar o ajuste de objeto.

tamanho de fundo: capa

.img-container {
  position: relative;
  overflow: hidden;
}

.background-image {
  position: absolute;
  min-width: 1000%;
  min-height: 1000%;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%) scale(0.1);
  z-index: -1;
}
<div class="img-container">
  <img class="background-image" src="https://picsum.photos/1024/768/?random">
  <p style="padding: 20px; color: white; text-shadow: 0 0 10px black">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
</div>

Os 1000% são usados ​​aqui, caso o tamanho natural da imagem seja maior que o tamanho que está sendo exibido. Por exemplo, se a imagem for 500x500, mas o contêiner for apenas 200x200. Com esta solução, a imagem será redimensionada para 2000x2000 (devido à largura mínima / altura mínima) e, em seguida, reduzida a 200x200 (devido a transform: scale(0.1)).

O fator x10 pode ser substituído por x100 ou x1000, mas geralmente não é ideal ter uma imagem de 2000x2000 sendo renderizada em uma div de 20x20. :)

tamanho do plano de fundo: contém

Seguindo o mesmo princípio, você também pode usá-lo para emular background-size: contain:

.img-container {
  position: relative;
  overflow: hidden;
  z-index: 0;
}

.background-image {
  position: absolute;
  max-width: 10%;
  max-height: 10%;
  left: 50%;
  top: 50%;
  transform: translateX(-50%) translateY(-50%) scale(10);
  z-index: -1;
}
<div style="background-color: black">
  <div class="img-container">
    <img class="background-image" src="https://picsum.photos/1024/768/?random">
    <p style="padding: 20px; color: white; text-shadow: 0 0 10px black">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
  </div>
</div>

Thiago Barcala
fonte
O truque escala é dado já aqui https://stackoverflow.com/a/28771894/2827823 , então eu não posso ver o ponto em postagem ainda mais um, e assim é transformem muitas das respostas
Ason
Se você deseja expandir com uma explicação, atualizar essa resposta em vez disso, como não há nenhuma necessidade para 2 com a mesma solução
Ason
1
Obrigado pelo seu comentário @LGSon. Eu não tinha visto essa resposta antes, mas ainda acho que minha resposta tem seu valor aqui. A abordagem é praticamente a mesma, mas na minha opinião a minha é apresentada de uma maneira um pouco mais limpa. Muitas outras respostas aqui apresentam a mesma solução e todas estão incompletas (exceto a que você vinculou). Portanto, se minha resposta não deveria estar aqui, as outras não deveriam.
Thiago Barcala
1
Achei que ela encolhia a imagem no navegador móvel Chrome no Android (testado no LG G3 e no Samsung S9), não a testei com o Chrome no iOS, o Firefox móvel no Android a exibiu corretamente.
Jecko 5/03
10

Não , você não consegue entender como background-size:cover ...

Essa abordagem é bem próxima: ela usa JavaScript para determinar se a imagem é paisagem ou retrato e aplica estilos de acordo.

JS

 $('.myImages img').load(function(){
        var height = $(this).height();
        var width = $(this).width();
        console.log('widthandheight:',width,height);
        if(width>height){
            $(this).addClass('wide-img');
        }else{
            $(this).addClass('tall-img');
        }
    });

CSS

.tall-img{
    margin-top:-50%;
    width:100%;
}
.wide-img{
    margin-left:-50%;
    height:100%;
}

http://jsfiddle.net/b3PbT/

roo2
fonte
3

Eu precisava emular background-size: contain, mas não consegui usar object-fitdevido à falta de suporte. Minhas imagens tinham contêineres com dimensões definidas e isso acabou funcionando para mim:

.image-container {
  height: 200px;
  width: 200px;
  overflow: hidden;
  background-color: rebeccapurple;
  border: 1px solid yellow;
  position: relative;
}

.image {
  max-height: 100%;
  max-width: 100%;
  margin: auto;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
}
<!-- wide -->
<div class="image-container">
  <img class="image" src="http://placehold.it/300x100">
</div>

<!-- tall -->
<div class="image-container">
  <img class="image" src="http://placehold.it/100x300">
</div>

Gus
fonte
Você pode usar min-height: 100%; max-height:100%;e obter o equivalente ao tamanho do plano de fundo: capa;
Chris Seufert
min-height: 100%; max-height:100%;não preservaria a proporção, portanto não exatamente equivalente.
Reedyn
2

Tente definir ambos min-height e min-width, com display:block:

img {
    display:block;
    min-height:100%;
    min-width:100%;
}

( violino )

Desde que o elemento que contém sua imagem seja position:relativeou position:absolute, a imagem cobrirá o contêiner. No entanto, não será centralizado.

Você pode centralizar facilmente a imagem se souber se ela transbordará horizontalmente (definido margin-left:-50%) ou verticalmente (definido margin-top:-50%). Pode ser possível usar consultas de mídia CSS (e algumas matemáticas) para descobrir isso.

Jeremy
fonte
2

Com CSS você pode simular object-fit: [cover|contain];. É uso transforme [max|min]-[width|height]. Não é perfeito. Isso não funciona em um caso: se a imagem for mais larga e mais curta que o contêiner.

.img-ctr{
  background: red;/*visible only in contain mode*/
  border: 1px solid black;
  height: 300px;
  width: 600px;
  overflow: hidden;
  position: relative;
  display: block;
}
.img{
  display: block;

  /*contain:*/
  /*max-height: 100%;
  max-width: 100%;*/
  /*--*/

  /*cover (not work for images wider and shorter than the container):*/
  min-height: 100%;
  width: 100%;
  /*--*/

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
<p>Large square:
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x1000"></span>
</p>
<p>Small square:
<span class="img-ctr"><img class="img" src="http://placehold.it/100x100"></span>
</p>
<p>Large landscape:
<span class="img-ctr"><img class="img" src="http://placehold.it/2000x1000"></span>
</p>
<p>Small landscape:
<span class="img-ctr"><img class="img" src="http://placehold.it/200x100"></span>
</p>
<p>Large portrait:
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x2000"></span>
</p>
<p>Small portrait:
<span class="img-ctr"><img class="img" src="http://placehold.it/100x200"></span>
</p>
<p>Ultra thin portrait:
<span class="img-ctr"><img class="img" src="http://placehold.it/200x1000"></span>
</p>
<p>Ultra wide landscape (images wider and shorter than the container):
<span class="img-ctr"><img class="img" src="http://placehold.it/1000x200"></span>
</p>

mems
fonte
2

O que você pode fazer é usar o atributo 'style' para adicionar a imagem de plano de fundo ao elemento; dessa forma, você ainda estará chamando a imagem no HTML, mas ainda poderá usar o comportamento background-size: cover css:

HTML:

    <div class="image-div" style="background-image:url(yourimage.jpg)">
    </div>

CSS:

    .image-div{
    background-size: cover;
    }

É assim que adiciono o comportamento background-size: cover aos elementos que eu preciso carregar dinamicamente no HTML. Você pode usar classes css impressionantes, como background-position: center. estrondo

Charlie Tupman
fonte
1
Principalmente separação de preocupações, mas aqui estão algumas outras: programmers.stackexchange.com/a/271338
Daan
0

Para o IE, você também precisa incluir a segunda linha - largura: 100%;

.mydiv img {
    max-width: 100%;
    width: 100%;
}
фымышонок
fonte
0

Eu não tenho permissão para 'adicionar um comentário', fazendo isso, mas sim, o que Eru Penkman fez é praticamente perfeito, para que fique como uma capa de fundo, tudo o que você precisa fazer é mudar

.tall-img{
    margin-top:-50%;
    width:100%;
}
.wide-img{
    margin-left:-50%;
    height:100%;
}

PARA

.wide-img{
    margin-left:-42%;
    height:100%;
}
.tall-img{
    margin-top:-42%;
    width:100%;
}

Asim Ramay
fonte
0

Sei que isso é antigo, no entanto, muitas soluções que vejo acima têm um problema com a imagem / vídeo muito grande para o contêiner, portanto, na verdade, não age como uma capa do tamanho de plano de fundo. No entanto, decidi fazer "classes de utilidade" para que funcionasse para imagens e vídeos. Você simplesmente atribui ao contêiner a classe .media-cover-wrapper e o próprio item de mídia a classe .media-cover

Então você tem o seguinte jQuery:

function adjustDimensions(item, minW, minH, maxW, maxH) {
  item.css({
  minWidth: minW,
  minHeight: minH,
  maxWidth: maxW,
  maxHeight: maxH
  });
} // end function adjustDimensions

function mediaCoverBounds() {
  var mediaCover = $('.media-cover');

  mediaCover.each(function() {
   adjustDimensions($(this), '', '', '', '');
   var mediaWrapper = $(this).parent();
   var mediaWrapperWidth = mediaWrapper.width();
   var mediaWrapperHeight = mediaWrapper.height();
   var mediaCoverWidth = $(this).width();
   var mediaCoverHeight = $(this).height();
   var maxCoverWidth;
   var maxCoverHeight;

   if (mediaCoverWidth > mediaWrapperWidth && mediaCoverHeight > mediaWrapperHeight) {

     if (mediaWrapperHeight/mediaWrapperWidth > mediaCoverHeight/mediaCoverWidth) {
       maxCoverWidth = '';
       maxCoverHeight = '100%';
     } else {
       maxCoverWidth = '100%';
       maxCoverHeight = '';
     } // end if

     adjustDimensions($(this), '', '', maxCoverWidth, maxCoverHeight);
   } else {
     adjustDimensions($(this), '100%', '100%', '', '');
   } // end if
 }); // end mediaCover.each
} // end function mediaCoverBounds

Ao ligar, certifique-se de redimensionar a página:

mediaCoverBounds();

$(window).on('resize', function(){
  mediaCoverBounds();
});

Em seguida, o seguinte CSS:

.media-cover-wrapper {
  position: relative;
  overflow: hidden;
}

.media-cover-wrapper .media-cover {
  position: absolute;
  z-index: -1;
  top: 50%;
  left: 50%;
  -ms-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

Sim, pode exigir jQuery, mas responde muito bem e age exatamente como o tamanho do plano de fundo: capa e você pode usá-lo em imagens e / ou vídeos para obter esse valor extra de SEO.

Secular12
fonte
0

Podemos adotar a abordagem ZOOM. Podemos supor que no máximo 30% (ou mais de 100%) pode ser o efeito de zoom se a altura ou a largura da imagem for menor que a altura ou largura desejada. Podemos ocultar a área restante não necessária com estouro: oculto.

.image-container {
  width: 200px;
  height: 150px;
  overflow: hidden;
}
.stage-image-gallery a img {
  max-height: 130%;
  max-width: 130%;
  position: relative;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
}

Isso ajustará imagens com largura ou altura diferentes.

Rehmat
fonte
-1
background:url('/image/url/') right top scroll; 
background-size: auto 100%; 
min-height:100%;

encontrou os mesmos sintomas exatos. acima funcionou para mim.

user2958520
fonte