Navegação âncora e smooth scroll com CSS puro

Fazer rolagem suave (smooth scroll) com CSS puro já é uma realidade. Veja nesse artigo como alcançar o efeito (com um bônus especial no fim).

Ir para o artigo

Navegação por âncora em sites é algo tão velho quanto a própria Web. Mas, com os avanços de CSS, já é possível fazer navegação âncora com scroll suave (smooth scroll) usando CSS puro!

Esse tipo de navegação por âncora é comum de ser vista em sites One Page, Landing Pages e afins. Há não muito tempo atrás, para se ter esse tipo de navegação, ainda mais com rolagem suave — a famosa smooth scroll –, era preciso recorrer a JavaScript.

Na verdade, atualmente, na data de publicação deste artigo, recorrer a códigos JavaScript, incluindo bibliotecas inteiras para conseguir navegação por âncora com smooth scroll — acredite, o drama de adicionar jQuery somente para scroll suave é real –, ainda é o padrão; é o que se encontra na quase totalidade dos casos em que o recurso é implementado.

Felizmente, com o avanço de CSS e surgimento de novas possibilidades e técnicas, agora é possível conseguir o efeito sem o uso de JavaScript, ficando a tecnologia dispensada ou usada somente para dar retoques à experiência e/ou interações complementares menores.

:target

Segundo consta na documentação de :target na MDN,

A pseudo-classe CSS :target representa um único elemento (o elemento alvo) com uma id correspondente ao fragmento da URL.

Na prática, :target serve para estilizar elementos que recebeu o foco através de um fragmento de URL (sinal de #).

Por exemplo, o seguinte HTML:

Associado a este CSS:

Faz com que, ao clicar em algum link da lista, seu correspondente (mesmo #) tenha a cor de fundo alterada.

scroll-behavior com scroll-margin-top

Para atingir o resultado de scroll suave com CSS puro, é preciso comentar a existência de uma nova aliada nas folhas de estilo: a propriedade scroll-behavior.

Basicamente, ela admite 2 valores:

  • auto. O comportamento padrão de rolagem (dando “pulo” ou “tranco” até o target);
  • smooth. Rolagem suave!

O bom é que é possível determinar o comportamento de scroll (scroll-behavior) para diferentes elementos do site, mas, caso você queira e/ou seja preciso, definir que o scroll geral (o da viewport) será suave, bastante, para isso, especificar a propriedade no html:

Só fica uma pequena questão: a tela vai rolar para o exato ponto em que o título (ou o conteúdo que seja) começa, sendo bastante comum o “corte” do texto desse título — o que não é bom para a experiência de quem acessa o site.

Obviamente, a maioria dos (bons) códigos JavaScript e libs de scroll comentados anteriormente já trata da questão que, até há não muito tempo atrás, era algo insolúvel com CSS puro.

Felizmente, agora é possível contar com a propriedade scroll-margin-top.

Como é possível inferir pelo próprio nome da propriedade, scroll-margin-top adiciona espaçamento entre o target e o topo da viewport, sanando o problema de o texto do alvo ficar total ou parcialmente “fora de tela”.

Juntando tudo: navegação com smooth scroll usando CSS puro

Então, a partir do que foi mostrado até agora, usando o que já existia e novidades CSS quentíssimas, é possível sim conseguir o efeito de navegação suave com smooth scroll usando apenas CSS puro!

Independentemente de como é o layout de sua página, é possível juntar tudo o que foi visto e conseguir smooth scroll só com CSS através do seguinte snippet:

Perceba que :target pode ser usado em elementos específicos, mas, assim como muitos outros pseudo em CSS, se usado “solto”, representa a estilização em tudo o que é afetado pelo estilo em questão.

Dica bônus!

Na verdade, é possível aprimorar esse snippet para que ele atenda a mais casos e agrade a mais pessoas. Para isso, como gostamos, vamos usar de CSS moderno.

Mais especificamente, a media query prefers-reduced-motion.

Da nova fornada de media queries, prefers-reduced-motion é usado para detectar se a pessoa habilitou que o sistema minimizasse a quantidade de movimento não-essencial que será mostrado.

Se você está se perguntando porque alguém faria isso, vai desde uma mera preferência de interação até evitar passar mal — há pessoas que podem ficar com tontura/vertigem com determinados tipos de animação (distúrbios vestibulares).

prefers-reduced-motion aceita 2 valores:

  • no-preference. Nenhuma configuração específica sobre redução de motion foi especificada;
  • reduce. Foi requisitado ao sistema a redução de animações não-essenciais.

Torna-se possível, com isso, o aprimoramento do snippet, permitindo smooth scroll somente nos casos em que a pessoa não tem nenhuma configuração específica sobre redução de movimentos:

Conclusão

Na data de publicação deste artigo, o suporte cross-browser total para o snippet não é uma realidade. Entretanto, se você já quiser usá-lo dentro de uma estratégia de suporte condicional com fallback, seu código já fica preparado para o futuro — além de bem elegante.

Começar a dar atenção para outros tipos de media queries, tal como prefers-reduced-motion, e também pensar mais globalmente nas possibilidades de interação (ou falta de) na Web, adequando seu CSS a isso, é um passo importante a se dar rumo a um código mais maduro e profissional.

E aí, vale a pena trocar dezenas de KB de JavaScript por 8 linhas de código CSS puro? :)

Usamos cookies para melhorar sua experiência e para ajudar a entender como nosso site é usado. Ao utilizar este site, você aceita o uso de cookies. Consulte nossa política de privacidade para obter mais informações.