24 agosto, 2016

Cortina (overlay) de Loading usando CSS, v2

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.

Nenhum comentário: