Como implementar rolagem suave com CSS e JavaScript

1. Comece com a marcação HTML

Para fins de demonstração, definiremos um cabeçalho agrupado em um contêiner e quatro seções. Dentro dele, especificaremos um menu de navegação e um texto introdutório.

Cada seção terá um id cujo valor corresponderá ao href valor de um link de menu. Esta associação (a que nos referimos como um identificador de fragmento) nos permitirá pular para partes específicas da nossa página.

Aqui está o HTML:

1
 class="container">
2
  ...
3
   class="page-header">
4
    
5
      
6
        
  • 7
               href="#...">...
    
    8
            
    
    9
            
    
    10
          
    
    11
        
    
    12
         class="header-text">...
    
    13
      
    
    14
    
    
    15
     class="section" id="">...
    
    16
     class="section" id="">...
    
    17
     class="section" id="">...
    
    18
     class="section" id="">...
    

    2. Defina os estilos

    A parte do CSS será bem direta, nada de extraordinário.

    Primeiro, usaremos o CSS Grid para fazer o layout do cabeçalho da página. O menu cobrirá um quarto da largura disponível, enquanto o texto os três quartos restantes (o material responsivo não é realmente importante aqui):

    1
    .page-header {
    
    2
      display: grid;
    
    3
      grid-column-gap: 30px;
    
    4
      grid-template-columns: 1fr 3fr;
    
    5
      padding: 40px 0;
    
    6
      border-top: 1px solid;
    
    7
      border-bottom: 1px solid;
    
    8
      margin-bottom: 150px;
    
    9
    }
    
    10
    
    
    11
    .header-text {
    
    12
      font-weight: bold;
    
    13
    }
    

    A seguir, aplicaremos alguns estilos às seções. Mais importante ainda, garantiremos que eles sejam altos o suficiente, para que haja rolagem adequada dentro da página para o efeito:

    1
    /*CUSTOM VARIABLES HERE*/
    
    2
    
    
    3
    .section {
    
    4
      padding: 150px 0;
    
    5
    }
    
    6
    
    
    7
    .section:nth-of-type(1),
    
    8
    .section:nth-of-type(3) {
    
    9
      background: var(--beige);
    
    10
    }
    
    11
    
    
    12
    .section-text {
    
    13
      margin: 50px 0;
    
    14
      max-width: 800px;
    
    15
    }
    
    16
    
    
    17
    .section-btn {
    
    18
      display: inline-block;
    
    19
      color: var(--beige);
    
    20
      background: var(--black);
    
    21
      min-width: 200px;
    
    22
      height: 50px;
    
    23
      padding: 9px 40px;
    
    24
      text-align: center;
    
    25
    }
    

    Isso é tudo que precisamos até agora! Se agora clicarmos em um link específico, iremos imediatamente para a seção da página relevante.

    Confira nossa demonstração inicial:

    Coisas básicas de HTML, certo? Vamos agora dar um passo adiante e aprender como navegar para as seções suavemente.

    A abordagem mais fácil e rápida para aplicar rolagem suave dentro de uma página é através da seguinte regra:

    1
    html { 
    
    2
      scroll-behavior: smooth; 
    
    3
    }
    

    Vamos explicar.

    Há uma propriedade CSS relativamente nova chamada scroll-behavior. Esta propriedade aceita dois valores: auto (padrão) e smooth. Assim que dermos scroll-behavior: smooth para o html elemento, a mágica acontecerá e poderemos navegar até a seção de destino sem problemas.

    Observação: se você definir scroll-behavior: smooth para o body elemento, a rolagem suave não funcionará.

    Como observação adicional, lembre-se de que, no momento em que este livro foi escrito, não havia speed opção definida na especificação para manipulação da velocidade da animação.

    Aqui está a demonstração associada:

    Revisão da solução

    É um ótimo e promissor recurso CSS, e seu suporte ao navegador cresce gradualmente. Dito isso, até o Safari, que não tinha suporte em suas versões anteriores, passou a apoiá-lo.

    Continuaremos com a abordagem jQuery tradicional. Dito isso, para criar uma rolagem suave com jQuery, aproveitaremos sua animate() método.

    Sempre que clicarmos em um link de navegação, faremos o seguinte:

    1. Cancele seu comportamento padrão para pular para a seção correspondente.
    2. pegue seu href Valor do atributo.
    3. Navegue suavemente até a seção associada animando o scrollTop propriedade. Observe que o animate() O método nos permite ajustar a velocidade da animação. No nosso caso, a animação terá duração de 800ms.

    Aqui está o código jQuery:

    1
    $(".page-header ul a").on("click", function (e) {
    
    2
      // 1
    
    
    3
      e.preventDefault();
    
    4
      // 2
    
    
    5
      const href = $(this).attr("href");
    
    6
      // 3
    
    
    7
      $("html, body").animate({ scrollTop: $(href).offset().top }, 800);
    
    8
    });
    

    E a demonstração relacionada:

    Revisão da solução

    A principal desvantagem desse método é que você precisa carregar uma biblioteca JavaScript extra. Pelo contrário, é uma solução confiável que funcionará bem em diferentes telas/dispositivos e você pode personalizar a velocidade de rolagem. Vá com ele apenas se o seu projeto já usa ou precisa de jQuery.

    Neste ponto, descartaremos o jQuery e nos concentraremos em duas soluções JavaScript puras. Felizmente, é muito mais simples do que você poderia esperar.

    Usando o scroll() Método

    Primeiro, usaremos o scroll() método. A lógica dessa abordagem é semelhante à implementação anterior do jQuery.

    Dentro desse método, determinaremos o comportamento de rolagem por meio do behavior propriedade de configuração. Esta propriedade é a representação JavaScript do scroll-behavior propriedade CSS e pode receber o auto (padrão), smooth e instant (veja a próxima seção 7) valores. Novamente aqui, tudo o que temos a fazer é definir o valor do behavior propriedade para smooth.

    Aqui está o código necessário:

    1
    const links = document.querySelectorAll(".page-header ul a");
    
    2
    
    
    3
    for (const link of links) {
    
    4
      link.addEventListener("click", clickHandler);
    
    5
    }
    
    6
    
    
    7
    function clickHandler(e) {
    
    8
      e.preventDefault();
    
    9
      const href = this.getAttribute("href");
    
    10
      const offsetTop = document.querySelector(href).offsetTop;
    
    11
    
    
    12
      scroll({
    
    13
        top: offsetTop,
    
    14
        behavior: "smooth"
    
    15
      });
    
    16
    }
    

    Ao invés de scroll() método, poderíamos igualmente ter usado o scrollTo() e scrollBy() métodos. O efeito deve ser o mesmo.

    Aqui está a demonstração associada:

    Usando o scrollIntoView() Método

    Além dos métodos de rolagem mencionados acima, que são anexados ao window objeto (ou seja window.scroll()), há também o scrollIntoView() método que se aplica a elementos DOM. Isso pode aceitar também o familiar behavior propriedade com o valor definido como smooth.

    Aqui está o código necessário para esta implementação:

    1
    const links = document.querySelectorAll(".page-header ul a");
    
    2
    
    
    3
    for (const link of links) {
    
    4
      link.addEventListener("click", clickHandler);
    
    5
    }
    
    6
    
    
    7
    function clickHandler(e) {
    
    8
      e.preventDefault();
    
    9
      const href = this.getAttribute("href");
    
    10
    
    
    11
      document.querySelector(href).scrollIntoView({
    
    12
        behavior: "smooth"
    
    13
      });
    
    14
    }
    

    A demonstração relacionada:

    Revisão de soluções

    A versão JavaScript nativa da rolagem suave requer mais código em comparação com a propriedade CSS nativa. Assim como a solução CSS, seu suporte cresce a cada dia. Pelo contrário, não há maneira fácil de controlar a velocidade de rolagem, a menos que escrevamos nosso código.

    6. Polyfills, por favor?

    Como já discutido, a rolagem suave nativa com CSS ou JavaScript está aumentando, mas às vezes você pode querer estender o suporte em navegadores mais antigos.

    Nesse caso, você pode usar um polyfill como o popular Smooth Scroll com mais de 3,5 mil estrelas do GitHub.

    Para incluí-lo em seus projetos, pegue-o em um CDN e insira-o como um script tag antes do seu código JavaScript.

    No nosso caso, assim que o carregarmos em um de nossos demonstrações de JavaScripta animação de rolagem funcionará em navegadores como o Safari 14 e dispositivos como o iPad Mini 4. Mas, se a adicionarmos em nosso Demonstração CSSa animação de rolagem não funcionará em navegadores/dispositivos não suportados.

    Aqui está uma de nossas demonstrações de JavaScript mencionadas anteriormente com o polyfill incorporado:

    7. Impedir a rolagem suave em HTML

    A rolagem suave é um ótimo recurso para aprimorar a experiência do usuário, mas às vezes você pode querer evitá-la para alguns elementos.

    Vamos supor que em nosso demo também haja um de volta ao topo botão. Por padrão, habilitaremos a rolagem suave via CSS, mas substituiremos esse comportamento apenas para esse botão.

    Método 1

    Para conseguir isso, ao clicar no botão, primeiro substituiremos o comportamento de rolagem da página definindo scroll-behavior: autoe depois de navegar até o topo da página, vamos defini-la de volta para smooth.

    Aqui está o código necessário:

    1
    //we have set scroll-behavior: smooth in CSS
    
    
    2
    
    
    3
    const root = document.documentElement;
    
    4
    const back = document.querySelector(".back");
    
    5
    
    
    6
    back.addEventListener("click", function (e) {
    
    7
      e.preventDefault();
    
    8
      root.style.scrollBehavior = "auto";
    
    9
      scroll({
    
    10
        top: document.body.offsetTop
    
    11
      });
    
    12
      root.style.scrollBehavior = "";
    
    13
    });
    

    E a demonstração associada:

    Método #2

    Também podemos impedir a rolagem suave em HTML passando behavior: instant para o scroll() método. No momento da redação deste artigo, esse valor não está documentado nos documentos do MDN, mas aparece como uma opção nas especificações do editor. De acordo com meus testes, funciona pelo menos nas versões mais recentes do Chrome, Firefox e Edge.

    Aqui está o exemplo anterior com esta modificação:

    Conclusão

    É isso, pessoal! Hoje abordamos algumas opções para obter uma rolagem suave com CSS e JavaScript (incluindo jQuery). Também examinamos como impedir a rolagem suave definida em CSS por meio de JavaScript.

    Espero que você tenha achado este exercício útil e tenha aprimorado um pouco seu conhecimento de front-end. Se você já construiu algo semelhante no passado, por favor, compartilhe conosco via mídia social.

    Desafio: antes de encerrar, tenho um pequeno desafio para você! Seu trabalho é estender uma de nossas demonstrações de JavaScript incluindo um botão “voltar ao topo”. A funcionalidade final deve funcionar como esta demonstração. Você aceita o desafio? Se assim for, eu ficaria feliz em ver sua solução!

    Como sempre, muito obrigado pela leitura!



    Deixe uma resposta