aguarde...

7 de julho de 2020

Construindo um simples acionador de botão Voltar ao Início com CSS e JavaScript

Construindo um simples acionador de botão Voltar ao Início com CSS e JavaScript

Eu tenho tentado dissociar meus projetos de dependências e bibliotecas o máximo que posso ultimamente. Isso não apenas me dá uma boa oportunidade de exercitar algumas habilidades que tenho negligenciado, mas também ter um controle extra sobre bugs e erros.

Minha mais recente aventura foi a necessidade de criar um botão Voltar ao topo que só aparecesse depois que um elemento específico estivesse na página e desaparecesse quando rolasse além de um contêiner de limite. Aqui estão os critérios básicos de aceitação:

  • Um contêiner superior aciona o estado de visibilidade do botão para verdadeiro quando cruza a viewport
  • Um contêiner inferior remove o estado visível do botão
  • Apenas baunilha JS
  • O botão Voltar ao Início apresenta uma transição sutil de opacidade ao alterar os estados
  • O botão Voltar ao topo não pode ser clicado quando oculto

Com essas condições básicas, vamos esticar nossos músculos de codificação e iniciar essa solução!

Compreendendo o problema

Considerando que nossa marcação é composta de um botão Voltar ao topo #back-to-top, um contêiner superior #section-tope um contêiner inferior #section-bottom, vamos começar armazenando referências de ponteiro para esses elementos DOM:

    const btn = document.querySelector("#back-to-top");
    const topSection = document.querySelector("#section-top");
    const bottomSection = document.querySelector("#section-bottom");

Nossa primeira etapa é descobrir onde os dois elementos da seção cruzarão o fluxo de rolagem da página. Parece uma tarefa simples, pois você pode indicá-la, basta encontrar o valor da posição de rolagem em relação ao espaço vertical disponível na página! . Bem, esta é a solução em si, mas o JavasScript não fornece um método específico para encontrar esses valores imediatamente. Em vez disso, fornece muitos métodos auxiliares disponíveis no nível do objeto para lidar com esses tipos de cálculos.

     const topScrollTreshold =  topSection.getBoundingClientRect().top + window.pageYOffset

Uma coisa importante a considerar é que as propriedades de posição ( toplefte assim por diante) retornadas por esse método são relativas à viewport e não estão cientes da altura total da página, o que é fundamental para entendermos quando o botão Voltar ao topo deve mostrar-se. Para contornar esse problema, adicionamos o topvalor do nosso elemento à posição atual de rolagem acessando window.PageYOffset. Os nomes de propriedades também são importantes aqui: window.pageYOffseté o mesmo que window.scrollY, mas possui suporte nativo no IE.

Usar box-sizing: border-boxé uma maneira de se livrar desse comportamento, mas, para o nosso caso, basta estar atento a essa regra.

Observando se já passamos dos contêineres

Como uma maneira de otimizar esse processo, adicionaremos uma lógica condicional à nossa, topScrollTresholdpara que ela retorne um valor booleano. Agora, estamos planejando tornar essas variáveis ​​vivas dentro de um scrollevento de janela; assim, toda vez que os usuários rolarem as variáveis ​​serão verificadas e retornarão um novo conjunto de valores:

  window.addEventListener("scroll", function (e) {
   const topScrollTreshold = topSection.getBoundingClientRect().top + window.pageYOffset < window.pageYOffset;
  }

Estamos adicionando nossa .toppropriedade de contêiner superior pageYOffsetpara encontrar sua posição em relação à rolagem da página inteira e depois verificando se esse valor é menor que a posição de rolagem da página ( pageYOffset). Para o contêiner inferior, a lógica tem uma pequena ressalva:

  const bottomScrollTreshold = btn.getBoundingClientRect().top + window.pageYOffset > bottomSection.getBoundingClientRect().top + window.pageYOffset;

De volta aos nossos requisitos:

  • Um contêiner inferior remove o estado visível do botão

Há uma chance de que nada fique abaixo do contêiner Inferior e nunca chegue ao topo da página . De acordo com a MDN:

A página de propriedade da janela somente leituraYOffset (…) retorna o número de pixels em que o documento está rolado no eixo vertical (ou seja, para cima ou para baixo) com um valor de 0,0, indicando que a borda superior do documento está alinhada com a borda superior da área de conteúdo da janela .

Esse é o problema de medir sua posição sozinho, como fizemos no contêiner Top. Verificar sua interseção com o botão Voltar ao topo é uma opção mais à prova de falhas nesse caso.

Um pouco de CSS

O CSS extra para fazer esse botão funcionar é bastante simples: em seu estado padrão (oculto), nenhum pointer-eventsserá observado e o valor opacityserá definido como zero. Também o posicionamos em fixedrelação à viewport:

.back-to-top {
  position: fixed;
  bottom: 5vh;
  right: 5vw;
  opacity: 0;
  transition: opacity 0.5s;
  pointer-events: none;
}

.back-to-top.visible {
    opacity: 1;
    pointer-events: all;
}

.visibleclasse descreve seu estado ativo quando é clicável e totalmente opaco.

Juntando tudo

As etapas finais estão adicionando uma lógica mais simples para acionar o estado do botão com base no resultado final dos verificadores de limite:

//setting visibility based on scroll pos
    if (topScrollTreshold) {
      btn.classList.add("visible");
    } else if (btn.classList.contains("visible")) {
      btn.classList.remove("visible");
    }

    if (bottomScrollTreshold) {
      btn.classList.remove("visible");
    }

Veja o código abaixo:

Posted in Blog
Write a comment