"Display: none" impede o carregamento de uma imagem?

336

Todo tutorial de desenvolvimento de site responsivo recomenda o uso da display:nonepropriedade CSS para ocultar o carregamento do conteúdo nos navegadores móveis, para que o site seja carregado mais rapidamente. É verdade? Não display:nonecarrega as imagens ou ainda carrega o conteúdo no navegador móvel? Existe alguma maneira de impedir o carregamento de conteúdo desnecessário em navegadores móveis?

desagradável
fonte
6
Parece há algumas maneiras de prevenir o download com display: none, apenas não a maneira de baunilha: timkadlec.com/2012/04/media-query-asset-downloading-results
mrwweb
11
O W3C está testando ativamente: w3.org/2009/03/image-display-none/test.php
Pino

Respostas:

191

Os navegadores estão ficando mais inteligentes. Hoje, seu navegador (dependendo da versão) pode pular o carregamento da imagem, se puder determinar que não é útil.

A imagem tem um display:noneestilo, mas seu tamanho pode ser lido pelo script. O Chrome v68.0 não carrega imagens se o pai estiver oculto.

Você pode vê-lo lá: http://jsfiddle.net/tnk3j08s/

Você também pode ter verificado isso na guia "rede" das ferramentas de desenvolvedor do seu navegador.

Observe que, se o navegador estiver em um pequeno computador com CPU, não precisar renderizar a imagem (e fazer o layout da página) agilizará toda a operação de renderização, mas duvido que isso seja algo que realmente faça sentido hoje.

Se você deseja impedir que a imagem seja carregada, você simplesmente não pode adicionar o elemento IMG ao seu documento (ou definir o srcatributo IMG como "data:"ou "about:blank").

Denys Séguret
fonte
50
uma imagem vazia src é perigosa. Ele envia uma solicitação extra para o servidor. Uma boa leitura sobre este tema nczonline.net/blog/2009/11/30/...
Srinivas
2
@SrinivasYedhuri Sim, você está certo. Eu editei com uma solução melhor.
Denys Séguret
8
Esta resposta está apenas parcialmente correta. Acabei de testar isso no Google Chrome (v35) e posso confirmar que as imagens com exibição definida como nenhuma não foram baixadas. Provavelmente, isso facilita o design responsivo para o desenvolvedor.
Shawn Whinnery
15
Esta resposta não está mais correta. Veja abaixo os resultados atualizados de como vários navegadores, incluindo a versão mais recente do FF, lidam com essa situação de maneira diferente.
DMTintner
2
Ainda hoje (outubro de 2017), o navegador mais comum do Chrome fará o download de todas as fontes de elementos 'img', mesmo que ocultas. Não fará o download de imagens de fundo ocultas.
TKoL
130

Se você tornar a imagem uma imagem de plano de fundo de uma div em CSS, quando essa div estiver definida como "display: none", a imagem não será carregada. Quando o CSS está desativado, ele ainda não será carregado, porque, bem, o CSS está desativado.

Brent
fonte
17
Na verdade, essa é uma dica muito útil para o design responsivo.
ryandlf
3
Isso funciona em FF, Chrome, Safari, Opera, Maxthon. Eu não tentei nenhum IE.
Brent
13
Quebrando novo a partir da frente! <div hidden style="display:none;width:0;height:0;visibility:hidden;background:url('test.jpg')"></div>. Resultados: o Firefox 29 e o Opera 12 não são carregados. IE 11 e Chrome 34 de carga.
CoolCmd
3
@CoolCmd para design responsivo esta ainda é uma opção viável, como você pode em sua mídia CSS consulta conjunto background-imagepara nonepara casos em que você não quer que a imagem de carga. Não foi encontrada nenhuma alternativa melhor para este caso de uso que não usa JS.
Qtax
11
Testei um controle deslizante de imagem (que usava imagens de fundo) que tinha uma consulta de mídia com largura mínima. Abaixo dessa largura, a div pai tinha CSS display: none;. Teste de rede com janela abaixo dessa largura: Chrome 35, IE11 e Edge não carregaram as imagens
binaryfunt
57

A resposta não é tão fácil quanto um simples sim ou não. Confira os resultados de um teste que fiz recentemente:

  • No Chrome: todas as 8 capturas de tela- * imagens carregadas (img 1)
  • No Firefox: apenas a 1 captura de tela- * imagem carregada que está sendo exibida no momento (img 2)

Então, depois de pesquisar mais, descobri isso , o que explica como cada navegador lida com o carregamento de ativos de img com base na exibição de css: none;

Trecho da postagem do blog:

  • Chrome e Safari (WebKit): o
    WebKit baixa o arquivo sempre, exceto quando um plano de fundo é aplicado por meio de uma consulta de mídia não correspondente.
  • Firefox: o
    Firefox não fará o download da imagem chamada com imagem de plano de fundo se os estilos estiverem ocultos, mas ainda assim baixará os recursos das tags img.
  • Opera:
    Como o Firefox, o Opera não carrega imagens de fundo inúteis.
  • Internet Explorer:
    IE, como o WebKit, baixará imagens de fundo, mesmo que elas exibam: none; Algo estranho aparece no IE6: Elementos com uma imagem de fundo e exibição: nenhum conjunto inline não será baixado ... Mas eles serão se esses estilos não forem aplicados inline.

Chrome- Todas as 8 capturas de tela- * imagens carregadas

Firefox- Apenas a 1 captura de tela- * imagem carregada que está sendo exibida no momento

DMTintner
fonte
11
Contanto que esses resultados não façam parte dos padrões, não fazem sentido. O Chrome altera o mecanismo de renderização, a ópera também muda e o IE será substituído por outra coisa. Você simplesmente não pode contar com a implementação de recursos adicionais como este para permanecer estável ao longo do tempo. A solução será uma maneira de sugerir ao navegador quando um ativo deve ser carregado preguiçosamente, se houver.
Mark Kaplun
5
@ MarkKaplun Eu não estava sugerindo que esses resultados do teste mostrassem exatamente o que você pode esperar que sempre aconteça com todos os navegadores o tempo todo. Eu só pretendia demonstrar que a resposta "não é tão simples quanto sim ou não". atualmente, cada navegador está implementando isso de maneira diferente e provavelmente continuará assim por um tempo #
DMTintner 30/11/2015
@DMTintner exatamente certo. e até hoje eu posso confirmar imagens de fundo de divs carregadas com safari do iOS que eram `display: none '. a melhor abordagem é a de não assumir nada e se você não quer uma imagem carregada, não fazer referência a ela em uma tag html
bhu Boue vidya
34

A <picture>tag HTML5 ajudará você a resolver a fonte de imagem correta, dependendo da largura da tela

Aparentemente, o comportamento dos navegadores não mudou muito nos últimos 5 anos e muitos ainda baixariam as imagens ocultas, mesmo que houvesse uma display: nonepropriedade definida nelas.

Mesmo que haja uma solução alternativa para consultas de mídia , ela só poderia ser útil quando a imagem foi definida como plano de fundo no CSS.

Enquanto eu pensava que havia apenas uma solução JS para o problema ( carregamento lento , preenchimento de fotos etc.), parecia que havia uma boa solução HTML pura que sai da caixa com o HTML5.

E essa é a <picture>etiqueta.

Veja como o MDN o descreve:

O elemento HTML<picture> é um contêiner usado para especificar vários <source>elementos para um específico <img>contido nele. O navegador escolherá a fonte mais adequada de acordo com o layout atual da página (as restrições da caixa em que a imagem aparecerá) e o dispositivo em que será exibido (por exemplo, um dispositivo normal ou hiDPI).

E aqui está como usá-lo:

<picture>
 <source srcset="mdn-logo-wide.png" media="(min-width: 600px)">
 <img src="mdn-logo-narrow.png" alt="MDN">
</picture>

A lógica por trás

O navegador carregaria a fonte da imgtag, apenas se nenhuma regra de mídia se aplicar. Quando o <picture>elemento não é suportado pelo navegador, ele volta a mostrar a imgtag.

Normalmente, você colocaria a menor imagem como fonte <img>e, portanto, não carregaria as imagens pesadas para telas maiores. Vice-versa, se uma regra de mídia se aplicar, a fonte do <img>não será baixada; em vez disso, fará o download do conteúdo do URL da <source>tag correspondente .

A única armadilha aqui é que, se o elemento não for suportado pelo navegador, ele carregará apenas a imagem pequena. Por outro lado, em 2017, devemos pensar e codificar na primeira abordagem móvel .

E antes que alguém saísse muito, aqui está o suporte atual do navegador para <picture>:

Navegadores de desktop

Suporte para navegadores de desktop

Navegadores para celular

Suporte para navegadores móveis

Mais sobre o suporte ao navegador, você pode encontrar em Posso usar .

O bom é que a frase do html5please é usá-lo com um fallback . E eu pessoalmente pretendo seguir o conselho deles.

Mais sobre a tag que você pode encontrar na especificação do W3C . Existe um aviso, que eu acho importante mencionar:

O pictureelemento é um pouco diferente dos elementos videoe aparência semelhantes audio. Embora todos eles contenham sourceelementos, o srcatributo do elemento de origem não tem significado quando o elemento está aninhado em um pictureelemento e o algoritmo de seleção de recurso é diferente. Além disso, o picturepróprio elemento não exibe nada; apenas fornece um contexto para seu imgelemento contido que permite escolher entre vários URLs.

Então, o que diz é que ele apenas ajuda a melhorar o desempenho ao carregar uma imagem, fornecendo algum contexto para ela.

E você ainda pode usar um pouco de magia CSS para ocultar a imagem em pequenos dispositivos:

<style>
  picture { display: none; }

  @media (min-width: 600px) {
    picture {
      display: block;
    }
  }
</style>

<picture>
 <source srcset="the-real-image-source" media="(min-width: 600px)">
 <img src="a-1x1-pixel-image-that-will-be-hidden-in-the-css" alt="MDN">
</picture>

Portanto, o navegador não exibirá a imagem real e fará o download apenas da 1x1imagem em pixel (que pode ser armazenada em cache se você a usar mais de uma vez). No entanto, esteja ciente de que, se a <picture>tag não for suportada pelo navegador, mesmo nas telas do descktop, a imagem real não será exibida (portanto, você definitivamente precisará de um backup de polyfill).

Evgenia Manolova
fonte
4
I tomou uma rota semelhante como você, mas use a-img dados em vez :) Aqui está um post que escrevi sobre ele swimburger.net/blog/web/...
Swimburger
10

Sim, ele renderizará mais rápido, levemente, apenas porque não precisa renderizar a imagem e é um elemento a menos para classificar na tela.

Se você não deseja que ele seja carregado, deixe um DIV vazio, onde poderá carregar o html nele posteriormente, contendo uma <img>tag.

Tente usar o firebug ou o wireshark, como mencionei antes, e você verá que os arquivos são transferidos, mesmo que display:noneestejam presentes.

O Opera é o único navegador que não carrega a imagem se a tela estiver definida como nenhuma. Agora, o Opera mudou-se para o webkit e renderizará todas as imagens, mesmo que sua exibição esteja definida como nenhuma.

Aqui está uma página de teste que provará isso:

http://www.quirksmode.org/css/displayimg.html

Dorian
fonte
9

** 2019 Resposta **

Em uma situação normal display:none, não impede que a imagem seja baixada

/*will be downloaded*/

#element1 {
    display: none;
    background-image: url('https://picsum.photos/id/237/100');
}

Mas se um elemento ancestral tiver display:none, as imagens do descendente não serão baixadas


/* Markup */

<div id="father">
    <div id="son"></div>
</div>


/* Styles */

#father {
    display: none;
}

/* #son will not be downloaded because the #father div has display:none; */

#son {
    background-image: url('https://picsum.photos/id/234/500');
}

Outras situações que impedem o download da imagem:

1- O elemento alvo não existe

/* never will be downloaded because the target element doesn't exist */

#element-dont-exist {
    background-image: url('https://picsum.photos/id/240/400');
}

2- Duas classes iguais carregando imagens diferentes

/* The first image of #element2 will never be downloaded because the other #element2 class */

#element2 {
    background-image: url('https://picsum.photos/id/238/200');
}

/* The second image of #element2 will be downloaded */

#element2 {
    background-image: url('https://picsum.photos/id/239/300');
}

Você pode assistir por si mesmo aqui: https://codepen.io/juanmamenendez15/pen/dLQPmX

Juanma Menendez
fonte
8

Modo Quirks: imagens e exibição: nenhum

Quando a imagem display: none ou está dentro de um elemento display:none, o navegador pode optar por não fazer o download da imagem até que ela display esteja definida com outro valor.

Somente o Opera baixa a imagem quando você alterna displaypara block. Todos os outros navegadores fazem o download imediatamente.

onlyurei
fonte
8

A imagem de fundo de um elemento div será carregada se a div estiver definida como 'display: none'.

De qualquer forma, se a mesma div tiver um pai e esse pai estiver definido como 'display: none', a imagem de plano de fundo do elemento filho não será carregada . :)

Exemplo usando bootstrap:

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">


<div class="col-xs-12 visible-lg">
	<div style="background-image: url('http://via.placeholder.com/300x300'); background-repeat:no-repeat; height: 300px;">lg</div>
</div>
<div class="col-xs-12 visible-md">
	<div style="background-image: url('http://via.placeholder.com/200x200'); background-repeat:no-repeat; height: 200px;">md</div>
</div>
<div class="col-xs-12 visible-sm">
	<div style="background-image: url('http://via.placeholder.com/100x100'); background-repeat:no-repeat; height: 100px">sm</div>
</div>
<div class="col-xs-12 visible-xs">
	<div style="background-image: url('http://via.placeholder.com/50x50'); background-repeat:no-repeat; height: 50px">xs</div>
</div>

ninja_corp
fonte
4

Se você tornar a imagem uma imagem de plano de fundo de uma div em CSS, quando essa div estiver definida como 'display: none', a imagem não será carregada.

Apenas expandindo a solução do Brent.

Você pode fazer o seguinte para uma solução CSS pura, mas também faz com que a caixa img se comporte como uma caixa img em uma configuração de design responsivo (é para isso que serve o png transparente), o que é especialmente útil se o seu design usa dinamicamente responsivo- redimensionando imagens.

<img style="display: none; height: auto; width:100%; background-image: 
url('img/1078x501_1.jpg'); background-size: cover;" class="center-block 
visible-lg-block" src="img/400x186_trans.png" alt="pic 1 mofo">

A imagem será carregada apenas quando a consulta de mídia vinculada ao visible-lg-block for acionada e display: none for alterado para display: block. O png transparente é usado para permitir que o navegador defina proporções apropriadas de altura: largura para o seu bloco <img> (e, portanto, a imagem de fundo) em um design fluido (altura: automático; largura: 100%).

1078/501 = ~2.15  (large screen)
400/186  = ~2.15  (small screen)

Então, você acaba com algo como o seguinte, para três viewports diferentes:

<img style="display: none; height: auto; width:100%; background-image: url('img/1078x501_1.jpg'); background-size: cover;" class="center-block visible-lg-block" src="img/400x186_trans.png" alt="pic 1">
<img style="display: none; height: auto; width:100%; background-image: url('img/517x240_1.jpg'); background-size: cover;" class="center-block visible-md-block" src="img/400x186_trans.png" alt="pic 1">
<img style="display: none; height: auto; width:100%; background-image: url('img/400x186_1.jpg'); background-size: cover;" class="center-block visible-sm-block" src="img/400x186_trans.png" alt="pic 1">

E apenas as imagens padrão do tamanho da janela de visualização de mídia são carregadas durante o carregamento inicial e, posteriormente, dependendo da sua janela de visualização, as imagens são carregadas dinamicamente.

E sem javascript!

ats
fonte
2

Oi pessoal Eu estava lutando com o mesmo problema, como não carregar uma imagem no celular.

Mas descobri uma boa solução. Primeiro, crie uma tag img e, em seguida, carregue um svg em branco no atributo src. Agora você pode definir seu URL para a imagem como um estilo embutido com conteúdo: url ('link para sua imagem') ;. Agora envolva sua tag img em um invólucro de sua escolha.

<div class="test">
  <img src="data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/‌​svg%22/%3E" style="content:url('https://blog.prepscholar.com/hubfs/body_testinprogress.gif?t=1495225010554')">
</div>

  @media only screen and (max-width: 800px) {
      .test{
       display: none;
      }
    }

Defina o wrapper para não exibir nenhum no ponto de interrupção em que você não deseja carregar a imagem. O CSS embutido da tag img agora é ignorado, já que o estilo de um elemento envolvido em um wrapper com exibição nenhum será ignorado; portanto, a imagem não será carregada até que você atinja um ponto de interrupção no qual o wrapper possui bloco de exibição.

Lá vai você, maneira muito fácil de não carregar um img no ponto de interrupção móvel :)

Confira este código, para um exemplo de trabalho: http://codepen.io/fennefoss/pen/jmXjvo

Mikkel Fennefoss
fonte
Eu amo como a web continua evoluindo, nunca tinha visto esse truque antes, usando a contentpropriedade -para alterar a imagem mostrada. Você pode dar algumas estatísticas sobre compatibilidade com isso?
Windgazer
Para o mal do Edge: /, pelo menos ele funciona nas versões mais recentes do Firefox, Chome e Safari.
Mikkel Fennefoss
2

Não. A imagem será carregada como de costume e ainda usará a largura de banda do usuário se você estiver pensando em economizar a largura de banda do usuário de celular. O que você pode fazer é usar a consulta de mídia e filtrar os dispositivos nos quais você deseja que sua imagem seja carregada. A imagem deve ser definida como imagem de plano de fundo de uma div, etc, e NÃO como uma marca, pois a imagem carregará a imagem, independentemente do tamanho da tela e da consulta de mídia definida.

IsuNas Labs
fonte
1

Outra possibilidade é usar uma <noscript>etiqueta e colocar a imagem dentro <noscript>dela. Em seguida, use o javascript para remover onoscript tag conforme a imagem. Dessa forma, você pode carregar imagens sob demanda usando aprimoramento progressivo.

Use este polyfill que escrevi para ler o conteúdo das <noscript>tags no IE8

https://github.com/jameswestgate/noscript-textcontent

James Westgate
fonte
1

Use o CSS @media query, basicamente lançamos um projeto em que tínhamos uma imagem enorme de uma árvore na área de trabalho ao lado, mas não aparecendo nas telas de tabela / móvel. Portanto, evite que a imagem carregue, é muito fácil

Aqui está um pequeno trecho:

.tree {
    background: none top left no-repeat; 
}

@media only screen and (min-width: 1200px) {
    .tree {
        background: url(enormous-tree.png) top left no-repeat;
    }
}

Você pode usar o mesmo CSS para mostrar e ocultar com exibição / visibilidade / opacidade, mas a imagem ainda estava carregando, esse foi o código mais seguro que criamos.

Joakim Ling
fonte
0

estamos falando de imagens que não carregam no celular, certo? e daí se você acabou de criar uma @media (largura mínima: 400 px) {background-image: thing.jpg}

não procuraria apenas a imagem acima de uma certa largura de tela?

Superfly5000
fonte
-2

O truque para usar a tela: nenhum com imagens é atribuir um ID a eles. Isso ocorreu, não há muito código necessário para fazê-lo funcionar. Aqui está um exemplo usando consultas de mídia e três folhas de estilo. Um para telefone, um para tablet e outro para desktop. Tenho 3 imagens, imagem de telefone, tablet e área de trabalho. Na tela do telefone, apenas uma imagem do telefone será exibida, um tablet exibirá apenas a imagem do tablet, uma área de trabalho será exibida na imagem do computador. Aqui está um exemplo de código para fazê-lo funcionar:

Código fonte:

<div id="content">
<img id="phone" src="images/phone.png" />
<img id="tablet" src="images/tablet.png" />
<img id="desktop" src="images/desktop.png" />
</div>

O CSS do telefone que não precisa de uma consulta de mídia. É o img # phone que faz funcionar:

img#phone {
    display: block;
    margin: 6em auto 0 auto;
    width: 70%;
    }

img#tablet {display: none;}
img#desktop {display: none;}

O tablet css:

@media only screen and (min-width: 641px) {
img#phone {display: none;}

img#tablet {
    display: block;
    margin: 6em auto 0 auto;
    width: 70%;
    }
}

E o CSS da área de trabalho:

@media only screen and (min-width: 1141px) {
img#tablet {display: none;}

img#desktop {
    display: block;
    margin: 6em auto 0 auto;
    width: 80%;
    }
}

Boa sorte e deixe-me saber como isso funciona para você.

Duane
fonte
4
A questão não é como definir display: noneuma imagem. É: "display: none" impede que uma imagem seja carregada?
Evgenia Manolova 14/03