Pré-carregando imagens CSS

118

Tenho um formulário de contato oculto que é implantado clicando em um botão. Seus campos são definidos como imagens de plano de fundo CSS e sempre aparecem um pouco depois do div que foi alternado.

Eu estava usando este snippet na <head>seção, mas sem sorte (depois de limpar o cache):

<script>
$(document).ready(function() {
        pic = new Image();
        pic2 = new Image();
        pic3 = new Image();
        pic.src="<?php bloginfo('template_directory'); ?>/images/inputs/input1.png";
        pic2.src="<?php bloginfo('template_directory'); ?>/images/inputs/input2.png";
        pic3.src="<?php bloginfo('template_directory'); ?>/images/inputs/input3.png";
});
</script>

Estou usando o jQuery como minha biblioteca e seria legal se eu pudesse usá-lo também para resolver esse problema.

Obrigado por seus pensamentos.

Amendoim
fonte
Por favor, mostre seu código. Como você alterna este formulário?
n1313
1
n1313, eu uso a maneira mais simples possível: $ ('# toggle'). click (function () {$ ('# contact'). slideToggle ();});
Peanuts,

Respostas:

257

Pré-carregando imagens usando apenas CSS

No código a seguir, estou escolhendo aleatoriamente o bodyelemento, uma vez que é um dos únicos elementos com garantia de existência na página.

Para que o "truque" funcione, devemos usar a contentpropriedade que confortavelmente permite definir vários URLs a serem carregados, mas como mostrado, o ::afterpseudo elemento é mantido escondido para que as imagens não sejam renderizadas:

body::after{
   position:absolute; width:0; height:0; overflow:hidden; z-index:-1; // hide images
   content:url(img1.png) url(img2.png) url(img3.gif) url(img4.jpg);   // load images
}

Demo


é melhor usar uma imagem sprite para reduzir as solicitações de http ... (se houver muitas imagens de tamanho relativamente pequeno) e ter certeza de que as imagens estão hospedadas onde HTTP2 é usado.

vsync
fonte
27
Isso é incrível!
Hengjie
4
A melhor técnica até agora por sua simplicidade e abordagem CSS pura! A única desvantagem é que essas imagens são carregadas ao mesmo tempo que o conteúdo imediatamente visível e não são atrasadas até que o conteúdo principal seja carregado, o que exigiria Javascript. Mas, a menos que você esteja pré-carregando dezenas de imagens, isso não deve ser um obstáculo.
Benjamin
2
isso é fantástico para pré-carregar ativos de foco para botões CSS e outros - dessa forma, você não terá nenhuma oscilação ao passar por cima do botão enquanto os ativos carregam
Robert Petz
16
Boa solução. Eu recomendaria não aplicar isso body, pois essas imagens serão carregadas em todas as páginas que fazem referência à folha de estilo. Em vez disso, você deve usar .contact_form:after {...}ou alguma outra classe que seja menos global. A menos, é claro, que seu formulário de contato esteja em todas as páginas;)
CloudMagick
3
@vsync, isso faz sentido, especialmente para gifs e pequenos reutilizáveis. A situação que encontrei recentemente foi para grandes imagens bg para um carrossel de conteúdo rico, e eu certamente não queria esses arquivos grandes carregados em todos os lugares :)
CloudMagick
30

Posso confirmar que meu código original parece funcionar. Eu estava casualmente aderindo a uma imagem com um caminho errado.

Aqui está um teste: http://paragraphe.org/slidetoggletest/test.html

<script>
    var pic = new Image();
    var pic2 = new Image();
    var pic3 = new Image();
    pic.src="images/inputs/input1.png";
    pic2.src="images/inputs/input2.png";
    pic3.src="images/inputs/input3.png";
</script>
Amendoim
fonte
Depois de alguns testes APENAS com CSS e esta solução, no meu caso especificamente, esta é a melhor.
zequinha-bsb 13/11/11
Obrigado, é o mais fácil de todos :)
BetaCoder
4
O URL na resposta não é mais válido.
Brandon Buck
Olá, enviei novamente o conteúdo desse URL ( paragraphe.org/slidetoggletest/test.html ), desculpe por ter perdido isso. Saúde,
Peanuts
25

Pré-carregando imagens usando tag HTML <link>

Acredito que a maioria dos visitantes desta pergunta está procurando a resposta de "Como posso pré-carregar uma imagem antes que a renderização da página comece?" e a melhor solução para esse problema é usar <link>tag, pois <link>tag é capaz de bloquear a renderização posterior da página. Veja preemptiva

Essas duas opções de valor do atributo rel( relação entre o documento atual e o documento vinculado ) são mais relevantes com o problema:

  • pré - busca : carrega o recurso fornecido durante a renderização da página
  • preload : carregue o recurso fornecido antes do início da renderização da página

Portanto, se você deseja carregar um recurso ( neste caso, é uma imagem ) antes de iniciar o processo de renderização da <body>tag, use:

<link rel="preload" as="image" href="IMAGE_URL">

e se você deseja carregar um recurso durante a <body>renderização, mas planeja usá-lo mais tarde dinamicamente e não quer incomodar o usuário com o tempo de carregamento, use:

<link rel="prefetch" href="RESOURCE_URL">
mertyildiran
fonte
É importante notar que o mecanismo do navegador Mozilla só carrega prefetchquando o navegador está ocioso, o que é determinado pela nsIWebProgressListenerAPI. Veja isso para mais informações.
Matthew Beckman
1
Não acho que isso realmente bloqueie a renderização: w3c.github.io/preload "Por exemplo, o aplicativo pode usar a palavra-chave preload para iniciar a busca antecipada, de alta prioridade e sem bloqueio de renderização de um recurso CSS que pode então ser aplicado pelo aplicativo no momento apropriado "
Michael Crenshaw
1
@MichaelCrenshaw está correto, <link rel="preload">não não bloquear renderização, acredito que o autor entendeu mal a definição. De MDN Preloading content with rel = "preload" , "... que você deseja iniciar o carregamento no início do ciclo de vida da página, antes que o mecanismo de renderização principal do navegador seja acionado." A ideia é que os recursos sejam buscados o mais rápido possível, tornando mais provável que o recurso esteja disponível quando necessário, por exemplo, quando um <img>elemento está sendo renderizado.
MDMower
14

http://css-tricks.com/snippets/css/css-only-image-preloading/

Técnica # 1

Carregue a imagem no estado regular do elemento, apenas desloque-a com a posição de fundo. Em seguida, mova a posição de fundo para exibi-la ao pairar.

#grass { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background-position: bottom left; }

Técnica # 2

Se o elemento em questão já tiver uma imagem de fundo aplicada e você precisar alterar essa imagem, o procedimento acima não funcionará. Normalmente, você escolheria um sprite aqui (uma imagem de fundo combinada) e apenas mudaria a posição do fundo. Mas se isso não for possível, tente isso. Aplique a imagem de plano de fundo a outro elemento da página que já está em uso, mas não tem uma imagem de plano de fundo.

#random-unsuspecting-element { background: url(images/grass.png) no-repeat -9999px -9999px; }
#grass:hover { background: url(images/grass.png) no-repeat; }
Fatih Hayrioğlu
fonte
4
Sempre forneça conteúdo de links externos. Caso contrário, sua resposta não terá valor se o link quebrar!
sra
@Fatih +1 para link muito bom. A versão mais atual do artigo vinculado com 3 maneiras diferentes está aqui perishablepress.com/3-ways-preload-images-css-javascript-ajax
xmojmr
@xmojmr Não há soluções somente CSS em seu link.
Máx.
10

tente com isto:

var c=new Image("Path to the background image");
c.onload=function(){
   //render the form
}

Com este código, você pré-carrega a imagem de fundo e renderiza o formulário quando é carregado

mck89
fonte
mck89, obrigado, parece muito bom. Mas, devo usar esse código dentro do 'cabeçalho' ou embutido? Quer dizer, devo preenchê-lo com html?
Peanuts,
Você deve usar na cabeça. Acho que você pode usá-lo dentro do $ (document) .ready
mck89
6

Para pré-carregar imagens de fundo definidas com CSS, a resposta mais eficiente que encontrei foi uma versão modificada de algum código que descobri que não funcionava:

$(':hidden').each(function() {
  var backgroundImage = $(this).css("background-image");
  if (backgroundImage != 'none') {
    tempImage = new Image();
    tempImage.src = backgroundImage;
  }
});

O grande benefício disso é que você não precisa atualizá-lo ao trazer novas imagens de fundo no futuro; ele encontrará as novas e as pré-carregará!

Deminetix
fonte
Eu entendi corretamente que você adiciona um elemento oculto para cada imagem? Não é que ele consegue escanear seu arquivo CSS em busca de imagens, certo? :)
bvdb
5

Se você estiver reutilizando essas imagens bg em qualquer outro lugar do seu site para entradas de formulário, provavelmente desejará usar um sprite de imagem. Dessa forma, você pode gerenciar suas imagens de forma centralizada (em vez de ter pic1, pic2, pic3, etc ...).

Sprites geralmente são mais rápidos para o cliente, pois eles estão solicitando apenas um arquivo (embora um pouco maior) do servidor em vez de vários arquivos. Veja o artigo SO para mais benefícios:

Sprites de imagem CSS

Então, novamente, isso pode não ser útil se você estiver usando apenas para um formulário e você realmente só deseja carregá-los se o usuário solicitar o formulário de contato ... pode fazer sentido.

http://www.alistapart.com/articles/sprites

ajhit406
fonte
Sim, CSS Sprites são o caminho a percorrer. Apenas certifique-se de que uma das imagens naquele sprite apareça antes que o formulário oculto seja iniciado (como no carregamento da página).
Steve
1

que tal carregar aquela imagem de fundo em algum lugar escondido. Dessa forma, ele será carregado quando a página for aberta e não demorará mais depois que o formulário for criado usando ajax:

body {
background: #ffffff url('img_tree.png') no-repeat -100px -100px;
}
Santi
fonte
1

Você pode usar este plugin jQuery waitForImage ou pode colocar suas imagens em um div oculto ou (largura: 0 e altura: 0) e usar o evento onload nas imagens.

Se você tiver apenas 2-3 imagens, poderá vincular eventos e acioná-los em uma cadeia para que, após cada imagem, você possa fazer algum código.

user1236048
fonte
1

A única maneira é codificar a imagem em Base64 e colocá-la dentro do código HTML para que não precise entrar em contato com o servidor para fazer o download da imagem.

Isso irá codificar uma imagem do url para que você possa copiar o código do arquivo de imagem e inseri-lo em sua página, assim ...

body {
  background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIA...);
}
maior
fonte
2
se você quiser usar a mesma imagem novamente em seu CSS ... ela não será armazenada em cache e você terá que carregá-la novamente.
vsync
1

Quando não há como modificar o código CSS e pré-carregar imagens com regras CSS :beforeou :afterpseudoelementos, pode ser usada outra abordagem com o código JavaScript que atravessa as regras CSS das folhas de estilo carregadas. Para fazê-lo funcionar, os scripts devem ser incluídos após as folhas de estilo em HTML, por exemplo, antes de fechar a bodytag ou logo após as folhas de estilo.

getUrls() {
    const urlRegExp = /url\(('|")?([^'"()]+)('|")\)?/;

    let urls = [];
    for (let i = 0; i < document.styleSheets.length; i++) {
        let cssRules = document.styleSheets[i].cssRules;
        for (let j = 0; j < cssRules.length; j++) {
            let cssRule = cssRules[j];
            if (!cssRule.selectorText) {
                continue;
            }

            for (let k = 0; k < cssRule.style.length; k++) {
                let property = cssRule.style[k],
                    urlMatch = cssRule.style[property].match(urlRegExp);
                if (urlMatch !== null) {
                    urls.push(urlMatch[2]);
                }
            }
        }
    }
    return urls;
}

preloadImages() {
    return new Promise(resolve => {
        let urls = getUrls(),
            loadedCount = 0;

        const onImageLoad = () => {
            loadedCount++;
            if (urls.length === loadedCount) {
                resolve();
            }
        };

        for (var i = 0; i < urls.length; i++) {
            let image = new Image();
            image.src = urls[i];
            image.onload = onImageLoad;
        }
    });
}

document.addEventListener('DOMContentLoaded', () => {
    preloadImages().then(() => {
        // CSS images are loaded here
    });
});
Ezze
fonte
0

Se os elementos da página e suas imagens de fundo já estiverem no DOM (ou seja, você não os está criando / alterando dinamicamente), suas imagens de fundo já estarão carregadas. Nesse ponto, você pode querer examinar os métodos de compressão :)


fonte
mmmm ... bom ponto cpharmston, e isso explica por que o problema persiste mesmo com as imagens em cache. Então, isso significa que não há solução alternativa?
Peanuts,
Crie imagens menores! JPEGs são facilmente compactados, existem ferramentas de linha de comando para reduzir o tamanho dos PNGs ( pmt.sourceforge.net/pngcrush ) e você pode reduzir o número de cores na imagem para reduzir o tamanho dos GIFs. Claro, você também pode