26 outubro, 2015

Cortina (overlay) de Loading usando apenas CSS

Neste momento estou trabalhando em um projeto migrando para HTML a parte em Silverlight de um dos produtos da empresa onde trabalho. Esse designer se comunica com a aplicação por meio de web apis, que podem demorar um pouco para responder dependendo do volume de dados e carga do servidor.

Depois de ter trabalhado alguns anos em uma agência eu aderi à filosofia de que código HTML deve ter relevância semântica sempre que for possível, evitando a inclusão de atributos e tags desnecessários ao máximo. Com isso você acaba com um código mais limpo, menor, mais fácil de dar manutenção, mais fácil de alterar visualmente no futuro via css e mais leve de processar no browser.

Quando a aplicação fizer uma chamada para a api que demorar um pouco, eu precisava exibir uma tela de “loading”, mas eu queria fazer isso da forma mais limpa possível. Graças ao pseudo-seletor de css ::after, que eu adoro, eu fui capaz de criar essa tela usando apenas CSS, sem acrescentar nenhuma tag no HTML.

Exemplo da cortina de loading com animação

Como funciona:

Parte 1 - O pseudo-seletor ::after (e seu irmão ::before) permite incluir conteúdo, via css, “depois” ou “antes” do conteúdo do elemento que você está selecionando. Eu escrevi “depois” e “antes” entre aspas pois não é exatamente o que muitas pessoas pensam. O conteúdo será incluído ainda dentro do elemento selecionado, mas antes ou depois do conteúdo normal do mesmo. O conteúdo desse pseudo seletor deve ser definido pela propriedade “content” do css, e pode ser qualquer texto. Exemplo: você pode colocar uma citação na sua página escrevendo <cite>sua citação</cite> e fazer com que ela seja exibida entre aspas usando o css cite::after, cite::before{content:’”’; font-size:1.5em;}.

Adicionei a seguinte chamada na minha folha de estilo: body.loading:after{content:””; cursor:wait; position:fixed;left:0;right:0;top:0;bottom:0;background:rgba(0,0,0,.7);}. A partir de agora, se eu adicionar o class “loading” no body da página, vai aparecer um overlay preto com 70% opacidade sobre toda a página. O truque aqui foi que deixei o content vazio, mudei o cursor para espera e o position para fixed, para que esse pseudo elemento que acabei de criar ficasse com sua posição absoluta em relação à janela do browser. Definindo top, left, right e bottom para 0 eu deixei o elemento do tamanho da janela. Até aqui tudo bem, tudo o que temos é uma cortina cobrindo a página. Eu poderia ter colocado a palavra “carregando…” no content e teria ficado bom, mas eu quiz algo mais, o que nos leva à parte 2.

Parte 2 – Imagem em Data URI. Todos os browsers modernos suportam a definição inline de elementos que normalmente são externos (imagens, css, js, etc…). Você pode definir a propriedade “src” de uma tag “img” usando esse recurso e isso é inclusive recomendado se a imagem for pequena, para reduzir o número de requests feitos pelo browser. Para representar imanges assim você deve convertê-la para uma string em formato base64. Isso também pode ser usado em CSS, ou seja, você pode definir imagens de background dessa forma e ter um layout, com imagens, que não depende de nenhum arquivo externos exceto o .css. Se você trabalho com Visual Studio e tem a extensão Web Essentials instalada, basta clicar em qualquer imagem no Solution Explorer que você encontra uma opção que cria a string base64 da imagem selecionada.

opção para gerar o código base64 a partir do Visual Studio com extensão Web Essentials

O que eu fiz foi gerar um gif com a animação de loading que eu queria usar e acrescentar no css que já havia criado. No final da linha eu acrescentei um “no-repeat center center”, para que essa imagem de fundo fique exatamente no meio da janela do browser, independente da resolução ou tamanho da janela. O código ficou mais ou menos assim (não cabe o código base64 inteiro dessa imagem no print abaixo):

CSS final com o gif animado de loading aplicado

Parte 3 – Eu só precisei utilizar javascript nessa solução para aplicar o class “loading” no body da página, sempre que fosse necessário. No próximo post eu mostro a solução javascript que usei para simplificar o uso da tela de loading de forma inteligente e exibindo a animação apenas nas operações demoradas.

PS.: os pseudo-seletores ::before e ::after e o uso de Data URIs são suportados apenas a partir do Internet Explorer 8 e em todos os outros browsers modernos, porém no IE8 os pseudo-seletores devem ser escritos com apenas 1 “:” (notação do CSS2.1). A notação mais correta atualmente (CSS3) utiliza é “::” é suportada a partir do IE9 e em todos os outros browsers, mas se usar a notação do CSS 2.1 também vai funcionar em todos os browsers.

Abaixo tem um Codepen que fiz mostrando o resultado final de forma interativa. Clique no botão “load” para ver a cortina de loading.

See the Pen qOoKaM by Kelps Leite de Sousa (@kelps) on CodePen.

Nenhum comentário: