Guilherme Müller | Freelance Front-end Developer - Artigos e tutoriais sobre Front-end Design, HTML, CSS e Javascript

Como Fazer uma Imagem de Fundo Preencher a Tela Inteira

Recentemente em um projeto, houve a necessidade de fazer com que o plano de fundo do site (uma foto ou série de fotos, nesse caso) ocupasse toda a tela, não importando a resolução.

Faça o download dos arquivos de exemplo clicando aqui.

Sempre fui fã to site da agência August, um dos sites pioneiros a utilizarem fotos grandes como fundo. Porém, neste site foi utilizado Flash para o efeito de preenchimento de tela (originalmente; agora percebi que já trocaram para HTML/CSS). Hoje, com o avanço das bibliotecas javascript, procurei encontrar uma forma de fazer isso apenas com jQuery e um pouco de CSS (é claro que isso também pode ser feito com javascript “puro”). Neste tutorial mostrarei a solução que desenvolvi (veja o site do cliente).

HTML e CSS Básico

Antes de mais nada, temos que pensar como esta técnica funciona (mesmo que de forma mais simples) sem javascript. Não há uma forma confiável de fazer o efeito desejado apenas com HTML e CSS2, mas conseguimos uma funcionalidade básica. Não há muita flexibilidade com a utilização da propriedade CSS background, a não ser que seja utilizado CSS3 (cada vez mais uma alternativa viável, ver o Postscript), portanto iremos utilizar uma tag <img> e manipular seus atributos com CSS e Javascript.

Primeiramente, vamos analisar o HTML deste exemplo:

<!doctype html>
<html lang="pt-br">
<head>
<meta charset="UTF-8" />
<title>Imagem de Fundo Preenchendo Toda a Tela</title>
<style>
/* Estilos (em um site real colocar em arquivo externo) */
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>
//Javascript (em um site real colocar em arquivo externo)
</script>
</head>
<body>

<div id="fundo">
<img src="http://flickholdr.com/1600/1200/sunset" alt="" />
</div>
<div id="site">
<h1>Site Exemplo</h1>
<p>
Lorem ipsum...
</p>
</div>

</body>
</html>

Estou colocando os estilos e o javascript dentro do documento, mas é recomendável em um projeto real utilizar arquivos externos. Quanto ao HTML, nada muito diferente do normal, apenas a questão de haver duas divs, uma chamada #fundo-externo, para criar um contexto de posicionamento e outra chamada #fundo que será o nosso container para as imagens que irão preencher a tela. A razão de utilizar uma div é que podemos colocar várias imagens dentro dela e até criar um slideshow (como foi o caso no projeto do meu cliente).

A ideia de ter uma div com a imagem antes do site é poder posicionar o fundo e o site de forma absoluta, para que possamos sobrepor os dois. Vejamos o CSS:

/* reset de margens */
* {
margin: 0;
padding:0;
}

/* para garantir que estes elementos ocuparão toda a tela */
body, html {
width: 100%;
height: 100%;
font-family: Arial, Tahoma, sans-serif;
}

#fundo-externo {
overflow: hidden; /* para que não tenha rolagem se a imagem de fundo for maior que a tela */
width: 100%;
height: 100%;
position: relative; /* criamos um contexto para posicionamento */
}

#fundo {
position: fixed; /* posição fixa para que a possível rolagem da tela não revele espaços em branco */
width: 100%;
height: 100%;
}

#fundo img {
width: 100%; /* com isso imagem ocupará toda a largura da tela. Se colocarmos height: 100% também, a imagem irá distorcer */
position: absolute;
}

#site {
position: absolute;
top: 40px;
left: 50%;
width: 560px;
padding: 20px;
margin-left: -300px; /* por causa do posicionamento absoluto temos que usar margem negativa para centralizar o site */
background: #FFF; /* fundo branco para navegadores que não suportam rgba */
background: rgba(255,255,255,0.8); /* fundo branco com um pouco de transparência */
}

p {
margin-bottom: 1.5em;
}

Com isso, você verá que a imagem de fundo ocupará toda a largura da tela. Uma das desvantagens desta técnica já fica aparente logo de cara: por causa do posicionamento absoluto do site, temos algumas limitações quanto ao posicionamento da div#site. Neste caso, utilizei margens negativas para centralizar o container no layout. Porém, se a tela for muito estreita, haverá corte do conteúdo do site. Também podemos trabalhar com o site alinhado à esquerda ou à direita.

Você também perceberá que, apesar da imagem de fundo ocupar toda a tela, dependendo da forma como a janela do navegador é redimensionada, fica um espaço branco na parte de baixo do site. Isso acontece porque o redimensionamento automático está apenas acontecendo de acordo com a largura da janela. Quanto menor a largura da janela, menor a largura da imagem. Dependendo das proporções da janela ou tela, a imagem ficará menor do o espaço a ser ocupado, o que não é o que queremos aqui. Queremos que a imagem ocupe toda a tela, não importando o seu tamanho ou proporção.

Para isso, iremos utilizar um pouco de javascript:

// Função adaptImage()
// Parâmetros: targetimg (objeto jquery com elementos selecionados)
function adaptImage(targetimg) {
var wheight = $(window).height(); // altura da janela do navegador
var wwidth = $(window).width(); // largura da janela do navegador

// removemos os atributos de largura e altura da imagem
targetimg.removeAttr("width")
.removeAttr("height")
.css({ width: "", height: "" }); // removemos possíveis regras css também

var imgwidth = targetimg.width(); // largura da imagem
var imgheight = targetimg.height(); // altura da imagem

var destwidth = wwidth; // largura que a imagem deve ter
var destheight = wheight; // altura que a imagem deve ter

// aqui vamos determinar o tamanho final da imagem
if(imgheight < wheight) {
// se a altura da imagem for menor que a altura da tela, fazemos um cálculo
// para redefinir a largura da imagem para bater com a altura que queremos
destwidth = (imgwidth * wheight)/imgheight;

$('#fundo img').height(destheight);
$('#fundo img').width(destwidth);
}

// aqui utilizamos um cálculo simples para determinar o posicionamento da imagem
// para que a mesma fique no meio da tela
// posição = dimensão da imagem/2 - dimensão da tela/2
destheight = $('#fundo img').height();
var posy = (destheight/2 - wheight/2);
var posx = (destwidth/2 - wwidth/2);

//se o cálculo das posições der resultado positivo, trocamos para negativo
if(posy > 0) {
posy *= -1;
}
if(posx > 0) {
posx *= -1;
}

// colocamos através da função css() do jquery o posicionamento da imagem
$('#fundo').css({'top': posy + 'px', 'left': posx + 'px'});
}

//quando a janela for redimensionada, adaptamos a imagem
$(window).resize(function() {
adaptImage($('#fundo img'));
});

//quando a página carregar, fazemos o mesmo
$(window).load(function() {
$(window).resize();
});

No código acima utilizei um pouco de jQuery (apenas para os seletores e eventos), mas não é algo necessário. Isso pode ser feito com javascript puro sem problemas. Também não sou especialista em javascript, então acredito que podem haver melhorias na função (sugestões serão bem-vindas!), mas esta foi a solução que funcionou para mim.

Com esta técnica deixamos o CSS cuidar do redimensionamento da largura da imagem. Caso a largura fique muito pequena e a altura da imagem acabe ficando menor do que a altura da janela do navegador, a script atua para redimensionar a imagem de acordo com sua altura. Assim a imagem sempre ocupa toda a tela do navegador, não importando o tamanho ou proporção da mesma.

Veja o exemplo final aqui.

Esta técnica foi útil para você? Opine nos comentários!

Postscript: Uma Técnica com CSS3

Para conseguir um efeito semelhante com CSS3, sem utilizar javascript e utilizando menos HTML, podemos nos utilizar da nova propriedade background-size. Veja o exemplo CSS3 aqui. O código CSS é bem simples:

body {
background: url(http://flickholdr.com/1600/1200/sunset);

-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}

Redimensione a janela do seu navegador para ver o efeito em ação. Neste caso, podemos apagar as divs #fundo-externo e #fundo, pois não são mais necessárias.

Para mais informações sobre background-size e outras novas propriedades CSS3, visite este artigo do Sitepoint.

45 Comentários

  1. Thiago Hilpert disse:

    Caramba Parabéns, achei seu site pesquisando na web e tive que comentar, PQP que artigo animal velho vc está de parabéns vou acompanhar seu site, já adicionei nos favoritos rsrs!!! Posso manter contato e dar dicas para posts?

    Valeu e parabéns novamente

  2. Carlos Jr disse:

    muito útil, obrigado.

  3. Juscelino Cavalcante disse:

    Cara vc tá de parabens, tou começando agora na area de web e tava precisando justamente fazer esse esquema no site do criente, valeu pelo post, muito bom mesmo…

  4. Bruno Prado disse:

    cara, fantástico
    manja muito
    parabéns

  5. Luciano Pessoa disse:

    Cara parabens me deu um help aqui do tamanho de um trem valeu mesmo.

  6. Hugo Santiago disse:

    Olá amigo tem como fazer isso com um backgroud-color, por exemplo no css defino pra ele ter 100% da tela, mais quando fecho o navegador ao ponto de surgi uma barra de rolagem horizontal, o mesmo rodapé não preenche de cor o 100%.

  7. Gunner disse:

    olá eu utilizei exatamente como esta ai, porem quando altero o tamanho de width: alinha tudo para a direita. estou usando width:900px;
    Se puder me ajudar eu agradeço e agradeceria mais ainda se pudesse me enviar um E-mail.
    Obrigado.

    • Olá Gunner,
      Esta técnica foi desenvolvida para ser utilizada na área da tela inteira. Caso você queira trabalhar com uma largura fixa, talvez nem precise de tudo isso. Depende de cada caso, pode até ser mais fácil de fazer.

      Qualquer coisa me mande um e-mail que eu posso dar uma olhada. Apenas peço desculpas se eu demorar para responder pois estou com bastante projetos no momento.

  8. pepe disse:

    cara nao entendi to fazendu um blog dai eu peguei uma imagem mais eu boto ela e sempre fica pequena
    ajuda

  9. Ed de Souza disse:

    Cara, que dica excelente!! E parabéns pelo seu trabalho, muito bom gosto!
    Com certeza estarei visitando mais vezes aqui, obrigado!

  10. felipe disse:

    Cara, Parabéns pelo script foi muito util, continue assim vlw!!!

  11. Olá Guilherme,

    Ficou muito legal! Parabéns!

    Você encontrou algum problema com o IE 8 no comando abaixo?

    $(window).resize(function() {
    adaptImage($(‘#fundo img’));
    });

    Abraços,
    Isaias

  12. Ed de Souza disse:

    Olá, Guilherme
    Qual foi recurso q vc usou para fazer o slideshow do bg?
    Teria mostrar a aplicação dele no código?
    Estou com um projeto q precisa ter algo parecido.

    Muito grato,
    Ed

    • Olá Ed,

      Para fazer um slideshow, basta adaptar um pouco a técnica. No site da Berlim Ambientes (veja no meu portfolio) utilizei várias imagens dentro da mesma div e o plugin cycle para jquery. Pode ver o código do site do cliente para ter uma ideia.

  13. Lee Oliveira Samson disse:

    Muuuuuuuuuuuuuuuuito Obrigado amigo .!
    estava com essa duvida, pra fazer um serviço pra um cliente.

    Mt obg msm salvou minha vida

    SUCESSO !

  14. Amanda disse:

    Olá Guilherme,

    Adorei o artigo, mas estou tendo problemas no IE 9. No final do site ele está aparecendo uma barra branca, como se o fundo da imagem terminasse ali e ele complementasse sem a imagem, fica sem fundo.

    A imagem não está sendo aplicada no browser todo, vc sabe o porque disso, estou tentando catar aqui no código, mas não consigo achar nada.

    Fico no aguardo.

    Obrigada.

    • Olá Amanda,

      Que bom que gostou do artigo.
      Problemas como esse precisam de bastante análise, pois inconsistências de HTML ou CSS são parte do nosso trabalho. Eu teria que ver um exemplo para tentar diagnosticar o que está acontecendo. Tente fazer modificações no código (salve uma cópia antes) pois esta é a única maneira para se chegar a uma solução.

  15. Cleber Colantoni disse:

    Cara, independente de ter mais alternativas que funcione ou não, você esta de parabéns, realmente funciona, mas o que eu gostaria muito de comentar, é que muita gente acha que sabe tudo e fica escondendo o peixe (informação), mas você é dos meus, informação gratuita para todos, muito bom mesmo!

  16. Azziz Vicentini disse:

    Quer uma forma muuuiito mais facil?
    aqui vai:
    mude essa linha:
    #fundoFoto img {min-width: 100%;min-height: 100%;position: absolute;}
    e remova todo javascript que voce fez pois com isso o navegador ja faz tudo sozinho e nem precisa de css3 !

    testado no IE 7,8,9 FF e Chrome, só não testei no IE6

  17. Azziz Vicentini disse:

    só corrigindo não é #fundoFoto é só #fundo

    #fundo img {min-width: 100%;min-height: 100%;position: absolute;}

    • Obrigado pela dica Azziz! Não tinha pensado nisso.
      O funcionamento deste código pode ser satisfatório para alguns casos, mas não é igual à técnica que estou passando. Com a técnica javascript (ou CSS3), perceba que o redimensionamento da imagem funciona de forma diferente. Mesmo assim, obirgado pelo ponto de vista alternativo.

  18. Edvaldo Rocha disse:

    Opa, obrigado pelo belo post.
    Estava procurando algo assim pra um site meu mesmo que quero implantar aqui.
    Nao manjo nada de html nem javascript nem css, mas comecei estudar tudo isso e espero logo estar sabendo algo sobre.

    Uma duvida no dreamwaver quando clico em ver a compatibilidade do browser ele diz que nao é compativel com alguns browsers, posso ter problemas com isso ?

    Sendo que só testei no I.E 8, Chrome, e Firefox 9.

    Abraços e obrigado novamente.

    • Que bom que o post foi útil para você.
      Quanto a compatibilidade, não sei sobre a confiabilidade do Dreamweaver em relação a isso. Portanto é mais importante testar nos próprios navegadores e, se possível, em outros computadores também e com outros usuários.

  19. Vinicius disse:

    Não estou conseguindo deixar a div em 100% da tela alguem pode me ajudar

    HTML

    conteudo

    CSS

    html, body, #wrap {height: 100%;}
    body > #wrap {height: auto; min-height: 100%; background:#966;}
    #main {padding-bottom: 40px; background:#F00;} /* deve ser a mesma altura do rodapé */
    #footer {
    width:100%;
    background:#333;
    position: relative;
    margin-top: -40px; /* A mesma altura do rodapé, o valor deve ser negativo */
    height: 40px;
    clear:both
    }

  20. Edvaldo Rocha disse:

    Guilherme, descuido meu, se eu tivesse lido o codigo teria visto que nele proprio diz:

    background: #FFF; /* fundo branco para navegadores que não suportam rgba */

    Testei em mais aguns navegadores e tudo tranquilho.

    Obrigado novamente.

  21. Bruno Serejo disse:

    Parabéns pela iniciativa Guilherme. Todos pela democratização do conhecimento. Perfeito.

    Me tira só uma dúvida. Qual o tamanho padrão das imagens que você usou, pois acho que se a imagem for muito pequena irá distorcer quando visualizada em um monitor com resolução muito alta. E vice-versa.

    Ou estou errado?

    Mais uma vez. Parabéns.

    • Obrigado Bruno!

      Neste exemplo não lembro que tamanho de imagem que utilizei, pois usei um serviço para servir a imagem.
      Mas o que eu sugiro é utilizar um tamanho que ofereça suficiente qualidade, pois os navegadores hoje lidam bem com a redução e espansão de imagens.
      Sim, se for muito pequena, vai distorcer em telas maiores. Se a imagem for muito grande, não acho que vai distorcer tanto em telas menores, mas estas pessoas terão que baixar uma imagem enorme para vê-la “pequena”. Ainda não existe solução definitiva para isso, mas existem serviços que servem a imagem de acordo com o tamanho da tela, para economizar largura de banda. Se você pesquisar encontra (não lembro agora o nome dos sites).

  22. Bruno Serejo disse:

    Olá Guilherme. Cara não estou conseguindo rotacionar as imagens. Acredito que esteja faltando algum plugin para a jQuery. Quando direciono para o endereço do plugin do site da Berlim que você fez por exemplo, dá certo. Onde encontro esse plugin para salvar na pasta local?

    Fico no aguardo, até mais.

  23. Bruno Serejo disse:

    Blz. Guilherme consegui fazer aqui ficou lindo hehe. Percebi que a barra de rolagem não aparece mesmo redimencionando a janela do navegador, neste caso, tenho que fazer com que meu conteúdo sempre caiba na janela. Ou seja, não poderei utilizar textos grandes que necessitem de rolagem.

    É mais ou menos isso?

    • Fazer um site que sempre fique inteiro na tela apresenta vários desafios. Você pode navegar no site da Berlim para ver como que eu resolvi o problema de texto. O site acessa bem até em telas bem menores, apenas para celulares que teria que fazer alguns ajustes. Você consegue trabalhar com uma quantidade de conteúdo maior desde que saiba como resolver os problemas das resoluções menores e maiores (os extremos).

  24. diego Xavier disse:

    Boa tarde guilherme, eu nao tenho conhecimento em css, mas estou tentando. Meu problema e o seguinte:
    Nao estou conseguindo fixar um arquivo flash para que ele fique no meio da tela na raiz site da div, a resolucao do mesmo e de 1000 x 600, mas quando adiciono o mesmo fica para o lado direito da tela. Sera que pode me ajudar passando o codigo do mesmo.
    Obrigado e parabens pelo tutorial.

    • Olá Diego,

      Teria que realmente ver o código do site que você está fazendo e também como você está inserindo o arquivo flash na página. De qualquer forma, há vários tutoriais na internet (nenhum aqui no blog por enquanto) que explicam como se centraliza um elemento no documento. Eu, pessoalmente, uso position: absolute; quando isso realmente é necessário, mas esta técnica também tem seus problemas.
      Mas continue estudando CSS, pois é uma linguagem muito interessante e essencial para construir websites!

    • Olá Diego.

      Tente fazer da seguinte forma:
      – No html

      ARQUIVO EM FLASH

      – Na CSS

      .flash{
      width: 1000px /* Neste caso coloquei o tamanho do seu flash*/
      margin: 0 auto;
      }

      Acho que desta forma pode funcionar, qualquer coisa posta aqui de novo!

      Abraços.

  25. Muito boa a dica, parabéns! Era o que estava precisando para finalizar um projeto! Muito obrigado.

  26. Postei um código em HTML para auxiliar o Diego na dúvida dele mas não apareceu no post…

    era

    div class=flash

    ARQUIVO EM FLASH

    /div

    Coloquei sem os para ver se passa no blog.

    Abs e desculpa o flood.

    • Olá Marcus,

      Tudo bem. O blog ainda está na configuração inicial e ainda não tive muito tempo para ver isso. Acho que as tags realmente não sairão no comentário. Mas acho que dá para ter uma ideia (por enquanto usemos a imaginação).

Comente