Como fazer com que a altura da div se ajuste automaticamente ao tamanho do plano de fundo?

270

Como faço para que uma div se ajuste automaticamente ao tamanho do plano de fundo que defini para ela sem definir uma altura específica (ou uma altura mínima)?

JohnIdol
fonte

Respostas:

255

Outra solução, talvez ineficiente, seria incluir a imagem em um imgelemento definido como visibility: hidden;. Em seguida, faça background-imageda div circundante o mesmo que a imagem.

Isso definirá a div circundante para o tamanho da imagem no imgelemento, mas a exibirá como plano de fundo.

<div style="background-image: url(http://your-image.jpg);">
 <img src="http://your-image.jpg" style="visibility: hidden;" />
</div>
Tmac
fonte
16
não é exatamente útil, pois a imagem usará o 'espaço' e o conteúdo parecerá ter uma excelente margem superior.
Bart Calixto
35
Talvez eu esteja sentindo falta de alguma coisa, mas se você quiser colocar uma imgmarcação de qualquer maneira, por que simplesmente não esconder o real <img>e não se preocupar com um background-image? Que vantagem há em fazer as coisas dessa maneira?
Mark Amery
3
Boa resposta, mas o navegador não precisa carregá-lo duas vezes?
www139 17/10/2015
8
@ www139 Quando você diz carregar, o que exatamente você quer dizer? Depois que a imagem é baixada, ela é presumivelmente armazenada em cache. A partir desse ponto, quaisquer outras solicitações são baseadas em uma cópia local. Então não. Não é baixado duas vezes. Mas, ele é carregado duas vezes.
Tmac
2
@ MarkAmery Uma das coisas mais legais background-imageé que ele pode usar modos de mesclagem CSS , enquanto imgnão pode.
Aaron Gray
539

Existe uma maneira muito legal e legal de fazer uma imagem de plano de fundo funcionar como um imgelemento, para que ela se ajuste heightautomaticamente. Você precisa conhecer a imagem widthe a heightproporção. Defina o heightcontêiner como 0 e defina padding-topcomo porcentagem com base na proporção da imagem.

Será semelhante ao seguinte:

div {
    background-image: url('http://www.pets4homes.co.uk/images/articles/1111/large/feline-influenza-all-about-cat-flu-5239fffd61ddf.jpg');
    background-size: contain;
    background-repeat: no-repeat;
    width: 100%;
    height: 0;
    padding-top: 66.64%; /* (img-height / img-width * container-width) */
                /* (853 / 1280 * 100) */
}

Você acabou de obter uma imagem de fundo com altura automática, que funcionará como um elemento img. Aqui está um protótipo funcional (você pode redimensionar e verificar a altura da div): http://jsfiddle.net/TPEFn/2/

Hasanavi
fonte
23
Realmente incrível! Apenas para as gerações futuras assistindo esta resposta, se você estiver usando bússola (SCSS), eu criei um mixin a partir deste utilizando suas funções auxiliares para fazer os cálculos para você: @mixin div-same-size-as-background-img($url) { background-image: url($url); background-size: contain; background-repeat: no-repeat; width: 100%; height: 0; padding-top: percentage(image-height($url) / image-width($url)); }
Benjamin K.
20
Para quem está se perguntando, a parte superior do estofamento não cria um espaço em branco porque apenas adiciona altura ao elemento. A imagem é uma imagem de plano de fundo e é exibida com posicionamento e espaçamento adequados. É muito estúpido, temos que criar truques como estes para CSS.
Ahnbizcad
9
Infelizmente, o padding-top não permite que você coloque mais nada na div, como elementos de formulário sobre o plano de fundo.
Gary Hayes
14
@GaryHayes você pode definir position:relativea div e colocar outro no interior div com position:absolute; top:0; bottom:0; left:0; right:0;set
lexith
17
Embora esse método funcione para mostrar uma imagem de plano de fundo, ele torna a div menos útil, preenchendo-a com preenchimento. Kryptik sugeriu adicionar uma div absolutamente posicionada dentro do contêiner, mas então por que se preocupar com uma imagem de fundo? Você pode usar apenas uma imagem real na divisão de conteúdo, se quiser posicionar tudo sobre ela. Isso anula o propósito de usar uma imagem de fundo em primeiro lugar.
paulmz
35

Não há como ajustar automaticamente o tamanho da imagem de fundo usando CSS.

Você pode contornar isso medindo a imagem de plano de fundo no servidor e aplicando esses atributos à div, como outros mencionaram.

Você também pode hackear algum javascript para redimensionar a div com base no tamanho da imagem (após o download da imagem) - isso é basicamente a mesma coisa.

Se você precisar que seu div se ajuste automaticamente à imagem, eu poderia perguntar por que você não coloca uma <img>tag dentro de seu div?

Orion Edwards
fonte
Obrigado - mas eu preciso dele como plano de fundo para que o truque da imagem não funcione. Eu acho que vou hackear alguns javascript como você diz no pior cenário, mas provavelmente não vale a pena.
31909 JohnIdol
3
^^ Isso provavelmente não é uma boa ideia. O navegador pode levar alguns segundos para que sua imagem seja baixada e você não pode medi-la até então; portanto, sua div ficará com o tamanho errado por um bom tempo!
Orion Edwards
1
Ele poderia simplesmente executar o JavaScript quando o documento estiver pronto.
Scott Tesler 02/02
1
Você não pode alterar o srcde um imgcom consultas de mídia, mas pode alterar o arquivo usado como imagem de segundo plano com as consultas de mídia.
Scott Marcus
21

Essa resposta é semelhante a outras, mas geralmente é a melhor para a maioria dos aplicativos. Você precisa conhecer o tamanho da imagem antes da mão, o que normalmente faz. Isso permitirá que você adicione texto sobreposto, títulos etc., sem preenchimento negativo ou posicionamento absoluto da imagem. A chave é definir o% de preenchimento para corresponder à proporção da imagem, como visto no exemplo abaixo. Eu usei essa resposta e, essencialmente, apenas adicionei um fundo de imagem.

.wrapper {
  width: 100%;
  /* whatever width you want */
  display: inline-block;
  position: relative;
  background-size: contain;
  background: url('https://upload.wikimedia.org/wikipedia/en/thumb/6/67/Wiki-llama.jpg/1600px-Wiki-llama.jpg') top center no-repeat;
  margin: 0 auto;
}
.wrapper:after {
  padding-top: 75%;
  /* this llama image is 800x600 so set the padding top % to match 600/800 = .75 */
  display: block;
  content: '';
}
.main {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  color: black;
  text-align: center;
  margin-top: 5%;
}
<div class="wrapper">
  <div class="main">
    This is where your overlay content goes, titles, text, buttons, etc.
  </div>
</div>

hipismo
fonte
2
-1 para usar! Important - e vincular a outra resposta. Por favor, considere copiar o código relevante da outra resposta (com atribuição) i, para que este seja mais completo e em caso de roteamento de link.
totallyNotLizards
@jammypeach é melhor assim?
horsejockey
1
@horsejockey, a menos que eu esteja perdendo algo que não escala a imagem. Apenas mascara.
Dwkns 09/12/19
@dwkns Estranhamente, todas as chamadas em segundo plano precisam estar no único elemento. Eu descobri que estava cortando quando especifiquei "background: url ()" em um ID específico e "background-size: contains" em uma classe geral.
Nathan Williams
@dwkns Update: Consegui corrigir esse problema usando "background-image: url ()" em vez de "background: url ()".
Nathan Williams
15

Talvez isso possa ajudar, não é exatamente um pano de fundo, mas você entendeu:

<style>
div {
    float: left;
    position: relative;
}
div img {
    position: relative;
}

div div {
    position: absolute;
    top:0;
    left:0;
}
</style>

<div>
    <img src="http://antwrp.gsfc.nasa.gov/apod/image/0903/omegacen_davis.jpg" />
    <div>Hi there</div>
</div>
Luca Matteis
fonte
explique por que você manteve a posição de img como relativa?
Divyanshu Jimmy
1
Provavelmente porque float: left;quebrou o seu posicionamento
Isaac
12

Tenho certeza de que isso nunca foi visto até aqui. Mas se o seu problema era o mesmo que o meu, esta foi a minha solução:

.imaged-container{
  background-image:url('<%= asset_path("landing-page.png") %> ');
  background-repeat: no-repeat;
  background-size: 100%;
  height: 65vw;
}

Eu queria ter uma div no centro da imagem, e isso me permitirá isso.

Carpk
fonte
9

Existe uma solução CSS pura que as outras respostas perderam.

A propriedade "content:" é usada principalmente para inserir conteúdo de texto em um elemento, mas também pode ser usada para inserir conteúdo de imagem.

.my-div:before {
    content: url("image.png");
}

Isso fará com que a div redimensione sua altura para o tamanho real do pixel da imagem. Para redimensionar a largura também, adicione:

.my-div {
    display: inline-block;
}
Bernie Sumption
fonte
1
Eu gosto dessa solução, mas quando o navegador é menor, há muito espaço em branco deixado abaixo da imagem do cabeçalho, que é definido como responsivo.
MG1
6

Você pode fazer isso no lado do servidor: medindo a imagem e, em seguida, configurando o tamanho da div, OU carregando a imagem com JS, leia seus atributos e defina o tamanho do DIV.

E aqui está uma idéia: coloque a mesma imagem dentro da div como uma tag IMG, mas dê visibilidade: oculta + brinque com a posição relativa + dê a esta div a imagem como plano de fundo.

Itay Moav-Malimovka
fonte
lol por que exigir do lado do servidor? Ele deve poder ser implementado com CSS.
GTHell
1
@GTHell hahaha - verifique o ano em que respondi
Itay Moav -Malimovka 15/15
@ ItayMoav-Malimovka hehe, não percebeu isso.
GTHell
5

Eu tive esse problema e encontrei a resposta de Hasanavi, mas recebi um pequeno bug ao exibir a imagem de plano de fundo em uma tela ampla - A imagem de plano de fundo não se espalhou por toda a largura da tela.

Então, aqui está minha solução - baseada no código de Hasanavi, mas melhor ... e isso deve funcionar em telas móveis e extragrande.

/*WIDE SCREEN SUPPORT*/
@media screen and (min-width: 769px) { 
    div {
        background-image: url('http://www.pets4homes.co.uk/images/articles/1111/large/feline-influenza-all-about-cat-flu-5239fffd61ddf.jpg');
        background-size: cover;
        background-repeat: no-repeat;
        width: 100%;
        height: 0;
        padding-top: 66.64%; /* (img-height / img-width * container-width) */
                    /* (853 / 1280 * 100) */
    }
}

/*MOBILE SUPPORT*/
@media screen and (max-width: 768px) {
    div {
        background-image: url('http://www.pets4homes.co.uk/images/articles/1111/large/feline-influenza-all-about-cat-flu-5239fffd61ddf.jpg');
        background-size: contain;
        background-repeat: no-repeat;
        width: 100%;
        height: 0;
        padding-top: 66.64%; /* (img-height / img-width * container-width) */
                    /* (853 / 1280 * 100) */
    }
}

Como você deve ter notado, a background-size: contain;propriedade não se encaixa bem em telas extra largas e a background-size: cover;propriedade não se encaixa bem em telas móveis. Por isso, usei esse @mediaatributo para brincar com os tamanhos de tela e corrigir esse problema.

Martin Schwartz
fonte
3

Que tal agora :)

.fixed-centered-covers-entire-page{
    margin:auto;
    background-image: url('https://i.imgur.com/Ljd0YBi.jpg');
    background-repeat: no-repeat;background-size:cover;
    background-position: 50%;
    background-color: #fff;
    left:0;
    right:0;
    top:0;
    bottom:0;
    z-index:-1;
    position:fixed;
}
<div class="fixed-centered-covers-entire-page"></div>

Demonstração: http://jsfiddle.net/josephmcasey/KhPaF/

Joseph Casey
fonte
3

Se for uma única imagem de plano de fundo predeterminada e você desejar que a div seja responsiva sem distorcer a proporção da imagem de fundo, você pode primeiro calcular a proporção da imagem e criar uma div que preserva sua proporção, fazendo o seguinte :

Digamos que você queira uma proporção de 4/1 e a largura da div seja 32%:

div {
  width: 32%; 
  padding-bottom: 8%; 
}

Isso resulta do fato de que o preenchimento é calculado com base na largura do elemento que o contém.

Dor de cabeça
fonte
1

Pode ser que isso ajude, não é exatamente um pano de fundo, mas você tem a ideia simples

    <style>
div {
    float: left;
    position: relative;
}
div img {
    position: relative;
}

div div {
    position: absolute;
    top:0;
    left:0;
}
</style>

<div>
    <img src="http://www.planwallpaper.com/static/images/recycled_texture_background_by_sandeep_m-d6aeau9_PZ9chud.jpg" />
    <div>Hello</div>
</div>
Engr
fonte
1

Você pode fazer algo assim

<div style="background-image: url(http://your-image.jpg); position:relative;">
 <img src="http://your-image.jpg" style="opacity: 0;" />
<div style="position: absolute;top: 0;width: 100%;height: 100%;">my content goes here</div>
</div>
Mas
fonte
1

Se você conhece a proporção da imagem no momento da criação, deseja a altura com base na altura da janela e está bem segmentado para navegadores modernos (IE9 +) , pode usar unidades de janela de exibição para isso:

.width-ratio-of-height {
  overflow-x: scroll;
  height: 100vh;
  width: 500vh; /* width here is 5x height */
  background-image: url("http://placehold.it/5000x1000");
  background-size: cover;
}

Não é exatamente o que o OP estava perguntando, mas provavelmente era um bom ajuste para muitos dos que visualizavam essa pergunta, por isso, quis dar outra opção aqui.

Fiddle: https://jsfiddle.net/6Lkzdnge/

fredrivett
fonte
1

Eu olhei para algumas das soluções e elas são ótimas, mas acho que achei uma maneira surpreendentemente fácil.

Primeiro, precisamos obter a proporção da imagem de fundo. Simplesmente dividimos uma dimensão por outra. Então temos algo como, por exemplo, 66,4%

Quando temos uma proporção de imagem, podemos simplesmente calcular a altura da div multiplicando a proporção pela largura da janela de visualização:

height: calc(0.664 * 100vw);

Para mim, funciona, define a altura da div corretamente e a altera quando a janela é redimensionada.

Landeeyo
fonte
1

Suponha que você tenha algo assim:

<div class="content">
    ... // inner HTML
</div>

e você deseja adicionar um plano de fundo, mas não conhece a dimensão da imagem.

Eu tive um problema semelhante e resolvi usando a grade:

HTML

<div class="outer">
    <div class="content">
        ... // inner HTML
    </div>
    <img class="background" />
</div>

CSS

.outer{
    display: grid;
    grid-template: auto / auto;
    // or you can assign a name for this block
}
.content{
    grid-area: 1 / 1 / 2 / 2;
    z-index: 2;
}
.background{
    grid-area: 1 / 1 / 2 / 2;
    z-index: 1;
}

z-indexé apenas para colocar a imagem no fundo, é claro que você pode colocar img.backgroundacima da div.content.

NOTA : pode causar a div.contentmesma altura da imagem; portanto, se div.contenthouver filhos colocados de acordo com a sua altura, convém definir um número que não seja algo como 'automático'.

魏 一 元
fonte
0

Teve esse problema com o Umbraco CMS e, nesse cenário, você pode adicionar a imagem à div usando algo parecido com isto para o atributo 'style' da div:

style="background: url('@(image.mediaItem.Image.umbracoFile)') no-repeat scroll 0 0 transparent; height: @(image.mediaItem.Image.umbracoHeight)px"
Chris Halcrow
fonte
0

Estou lidando com esse problema há um tempo e decidi escrever um plugin jquery para resolver esse problema. Este plugin encontrará todos os elementos com a classe "show-bg" (ou você pode passá-lo por seu próprio seletor) e calculará as dimensões da imagem de fundo. tudo o que você precisa fazer é incluir esse código, marcar os elementos desejados com class = "show

Aproveitar!

https://bitbucket.org/tomeralmog/jquery.heightfrombg

Tomer Almog
fonte
0

A melhor solução que posso pensar é especificando sua largura e altura em porcentagem. Isso permitirá que você redimensione sua tela com base no tamanho do seu monitor. é mais layout responsivo ..

Para uma instância. Você tem

<br/>
<div> . //This you set the width percent to %100
    <div> //This you set the width percent to any amount . if you put it by 50% , it will be half
    </div>
 </div>

Esta é a melhor opção se você quiser um layout responsivo, eu não recomendaria o float, em certos casos o float pode ser usado. mas na maioria dos casos, evitamos o uso de flutuação, pois isso afetará várias coisas quando você estiver testando em vários navegadores.

Espero que isto ajude :)

FaridAvesko
fonte
-1

na verdade, é bastante fácil quando você sabe como fazê-lo:

<section data-speed='.618' data-type='background' style='background: url(someUrl) 
top center no-repeat fixed;  width: 100%; height: 40vw;'>
<div style='width: 100%; height: 40vw;'>
</div>
</section>

o truque é apenas definir a div fechada como uma div normal com valores dimensionais iguais aos valores dimensionais de fundo (neste exemplo, 100% e 40vw).

c. schaefer
fonte
Você está configurando a altura para ser uma proporção da largura da janela. Isso não funcionará em todos os casos - e parte do seu conteúdo, como a velocidade dos dados, não tem nada a ver com a sua resposta.
Polyducks
A maioria das coisas não é "muito fácil quando você sabe como fazê-lo"?
Scott Marcus
-2

Eu resolvi isso usando jQuery. Até que novas regras CSS permitam esse tipo de comportamento nativamente, acho que é a melhor maneira de fazê-lo.

Configure seus divs

Abaixo, você tem sua div na qual deseja que o plano de fundo apareça ("herói") e, em seguida, o conteúdo / texto interno que deseja sobrepor na parte superior da sua imagem de plano de fundo ("interna"). Você pode (e deve) mover os estilos embutidos para sua classe de herói. Deixei-os aqui, para que seja rápido e fácil ver quais estilos são aplicados a ele.

<div class="hero" style="background-image: url('your-image.png'); background-size: 100%; background-repeat: no-repeat; width: 100%;">
    <div class="inner">overlay content</div>
</div>

Calcular a proporção da imagem

Em seguida, calcule a proporção da imagem dividindo a altura da imagem pela largura. Por exemplo, se a altura da imagem é 660 e a largura é 1280, a proporção é de 0,5156.

Configurar um evento de redimensionamento da janela jQuery para ajustar a altura

Por fim, adicione um ouvinte de evento jQuery para redimensionar janelas e calcule a altura do seu div herói baseado na proporção e atualize-a. Essa solução geralmente deixa um pixel extra na parte inferior devido a cálculos imperfeitos usando a proporção, então adicionamos -1 ao tamanho resultante.

$(window).on("resize", function ()
{
    var aspect_ratio = .5156; /* or whatever yours is */
    var new_hero_height = ($(window).width()*aspect_ratio) - 1;
    $(".hero").height(new_hero_height);
}

Verifique se ele funciona no carregamento da página

Você deve executar a chamada de redimensionamento acima quando a página for carregada para que os tamanhos de imagem sejam calculados desde o início. Caso contrário, a divisão hero não será ajustada até que você redimensione a janela. Eu configurei uma função separada para fazer os ajustes de redimensionamento. Aqui está o código completo que eu uso.

function updateHeroDiv()
{
    var aspect_ratio = .5156; /* or whatever yours is */
    var new_hero_height = ($(window).width()*aspect_ratio) - 1;
    $(".hero").height(new_hero_height);
}

$(document).ready(function() 
{       
    // calls the function on page load
    updateHeroDiv(); 

    // calls the function on window resize
    $(window).on("resize", function ()
    {
        updateHeroDiv();        
    }
});
Art Geigel
fonte
-2

Se você puder criar uma imagem no Photoshop em que a camada principal tenha uma opacidade igual ou superior a 1 e seja basicamente transparente, coloque esse img na div e faça da imagem real a imagem de fundo. ENTÃO, defina a opacidade do img como 1 e adicione as dimensões de tamanho desejadas.

Essa imagem é feita dessa maneira e você não pode nem arrastar a imagem invisível para fora da página, o que é legal.

Tommy Nicholas
fonte
-4

basta adicionar a div

style="overflow:hidden;"
Tevfik Aktaş
fonte