Em outubro eu fiz um post mostrando como criar e usar uma cortina de loading usando CSS. Uma coisa muito boa daquela abordagem é que sua implementação não depende de nenhum markup html extra nas páginas. O visual é criado 100% em CSS e para usar basta acrescentar o class “loading” no body da página usando um javascript bem simples.
Desde então o projeto onde usei esse loading evoluiu e eu fiz algumas melhorias naquela implementação:
- O loading antes funcionava apenas no body da página, agora funciona em elementos individuais também (div, por exemplo)
- O loading não é mais imediato, passando a aparecer de forma gradual apenas após 1.2s da solicitação, assim se o processamento for muito rápido o overlay não aparece. Além disso a apresentação gradual do loading é mais agradável visualmente.
- O loading agora protege a página/elemento contra cliques, assim o usuário não conseguirá clicar novamente em botões ou elementos da página enquanto o loading estiver definido, mesmo dentro do período de 1.2s descrito acima.
Comecei mudando o CSS body.loading:after para .loading:after e trocando seu position de fixed para absolute. Isso faz com que ele passe a funcionar em qualquer elemento. Depois disso eu acrescentei uma série de outros estilos no CSS. Para facilitar a compreensão eu coloquei comentários explicativos a seguir:
/*animações que serão usadas para exibir o overlay de loading. Estão repetidas 3 vezes mudando apenas o prefixo para oferecer suporte no maior número possível de browsers.*/
/*A animação vai durar 2s, sendo que nos primeiros 60% o overlay estará invisível e a partir daí aparecerá gradualmente até atingir 60% de opacidade*/
@-moz-keyframes loading-anim {
0%,
60% {
opacity: 0;
}
100% {
opacity: 0.6;
}
}
@-webkit-keyframes loading-anim {
0%,
60% {
opacity: 0;
}
100% {
opacity: 0.6;
}
}
@keyframes loading-anim {
0%,
60% {
opacity: 0;
}
100% {
opacity: 0.6;
}
}
/*muda o ponteiro do mouse e faz com que cliques parem de funcionar para evitar processamento duplicado*/
.loading{
cursor:wait;
pointer-events:none;
}
/*faz o loading que não for no body aparecer apenas sobre o elemento sofrendo loading (por isso foi alterado de fixed para absolute)*/
body .loading{
position:relative;
}
/*muda o loading do body de volta para fixed e limita seu tamanho para o tamanho da janela*/
body.loading:after{
position:fixed;
max-width:100vw;
max-height:100vh;
}
/*acrescentadas as chamadas à animação definindo seu tempo em 2s*/
.loading:after {
opacity: 0.6;
-moz-animation: loading-anim 2s ease-in-out;
-o-animation: loading-anim 2s ease-in-out;
-webkit-animation: loading-anim 2s ease-in-out;
animation: loading-anim 2s ease-in-out;
pointer-events:auto;
content: "";
cursor: wait;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,.7) url("data:image/gif;base64,...") no-repeat center center;
}
Abaixo tem um CodePen mostrando o código acima em funcionamento.