Rolagem bem controlada com o ajuste de rolagem do CSS

Crie experiências de rolagem bem controladas declarando posições de ajuste de rolagem.

Robert Flack
Robert Flack
Majid Valipour
Majid Valipour

O recurso CSS Scroll Snap permite que os desenvolvedores da Web criem experiências de rolagem bem controladas ao declarar posições de ajuste de rolagem. Artigos paginados e carrosséis de imagens são dois exemplos comuns disso. O CSS Scroll Snap fornece uma API consistente e fácil de usar para criar esses padrões de UX conhecidos.

Contexto

O caso do ajuste de rolagem

Rolar a tela é uma forma comum e natural de interagir com o conteúdo na Web. Esse é o meio nativo da plataforma de fornecer acesso a mais informações do que é visível na tela de uma vez, tornando-se especialmente vital em plataformas móveis com espaço de tela limitado. Por isso, não é de se surpreender que autores da Web preferem organizar o conteúdo em listas simples roláveis em vez de hierarquias profundas.

A principal desvantagem do rolagem é a falta de precisão. Raramente uma rolagem acaba alinhada a um parágrafo ou frase. Isso é ainda mais pronunciado para conteúdo paginado ou detalhado com limites significativos quando a rolagem termina no meio da página ou da imagem, deixando-a parcialmente visível. Esses casos de uso se beneficiam de uma experiência de rolagem bem controlada.

Há muito tempo, os desenvolvedores Web contam com soluções baseadas em JavaScript para controlar a rolagem e solucionar esse problema. No entanto, as soluções baseadas em JavaScript não oferecem uma fidelidade total devido à falta de primitivos de personalização de rolagem ou acesso à rolagem composta. O CSS Scroll Snap garante uma solução rápida, de alta fidelidade e fácil de usar que funciona de maneira consistente em todos os navegadores.

O ajuste de rolagem do CSS permite que autores da Web marquem cada contêiner de rolagem com limites para concluir as operações de rolagem. Em seguida, os navegadores escolhem a posição final mais adequada dependendo das características da operação de rolagem, do layout e da visibilidade do contêiner de rolagem e dos detalhes das posições de ajuste. Em seguida, fazem a animação suave para ela. Voltando ao exemplo anterior, conforme o usuário termina de rolar o carrossel, a imagem visível se encaixa no lugar. Não são necessários ajustes de rolagem pelo JavaScript.

Exemplo de uso do ajuste de rolagem do CSS com um carrossel de imagens.
Exemplo de uso do ajuste de rolagem do CSS com um carrossel de imagens. Aqui, o ajuste de rolagem garante que, no final da rolagem, um centro horizontal da imagem fique alinhado ao centro horizontal do contêiner de rolagem.

Quebra de rolagem do CSS

A quebra de rolagem é o ato de ajustar o deslocamento de rolagem de um contêiner de rolagem para que ele fique em uma posição de quebra preferida quando a operação de rolagem terminar.

Um contêiner de rolagem pode ativar o ajuste de rolagem usando a propriedade scroll-snap-type. Isso informa ao navegador que ele precisa considerar encaixar esse contêiner de rolagem nas posições de ajuste produzidas pelos descendentes. scroll-snap-type determina o eixo em que a rolagem ocorre: x, y ou both, e o grau de precisão do ajuste: mandatory, proximity. Falaremos mais sobre isso depois.

Uma posição de ajuste pode ser produzida declarando um alinhamento desejado em um elemento. Essa posição é o deslocamento de rolagem em que o elemento e o contêiner de rolagem do ancestral mais próximo estão alinhados conforme especificado para o eixo especificado. Os seguintes alinhamentos são possíveis em cada eixo: start, end, center.

Um alinhamento start significa que a borda inicial do snapport do contêiner de rolagem precisa ser alinhada com a borda inicial da área de snap do elemento. Da mesma forma, os alinhamentos end e center significam que a borda ou o centro do alinhamento do contêiner de rolagem precisa ser liberado com o centro ou a borda final da área de ajuste do elemento.

Exemplo de vários alinhamentos no eixo de rolagem horizontal.

Os exemplos a seguir ilustram como usar esses conceitos.

Um caso de uso comum para o ajuste de rolagem é um carrossel de imagens. Por exemplo, para criar um carrossel de imagens horizontal que se ajusta a cada imagem conforme você rola, podemos especificar o contêiner de rolagem para ter um scroll-snap-type obrigatório no eixo horizontal. Defina cada imagem como scroll-snap-align: center para garantir que o ajuste centralize a imagem dentro do carrossel.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

Como as posições de ajuste são associadas a um elemento, o algoritmo de ajuste pode ser inteligente em relação a quando e como ele ajusta o elemento e o tamanho do contêiner de rolagem. Por exemplo, considere o caso em que uma imagem é maior que o carrossel. Um algoritmo de ajuste simples pode impedir que o usuário gire para conseguir a imagem completa. No entanto, a especificação exige implementações para detectar esse caso e permitir que o usuário role livremente dentro dessa imagem, apenas encaixando nas bordas.

Conferir a demonstração | Origem

Exemplo: uma página de produto com jornada

Outro caso comum que pode se beneficiar do ajuste de rolagem são páginas com várias seções lógicas para rolar verticalmente, por exemplo, uma página de produto típica. O scroll-snap-type: y proximity; é mais adequado para casos como esse. Ele não interfere quando um usuário rola até o meio de uma seção especificada, mas também fixa e chama a atenção para uma nova seção quando o usuário rola até ela.

Isso pode ser feito da seguinte maneira:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Margem e padding de rolagem

A página do produto tem um cabeçalho superior de posição fixa. O design também solicitou que parte da seção superior permanecesse visível quando o contêiner de rolagem é ajustado, a fim de fornecer uma sugestão de design aos usuários sobre o conteúdo acima.

A propriedade scroll-padding é uma nova propriedade CSS que pode ser usada para ajustar a região visível efetiva do contêiner de rolagem, ou Snapport, que é usada ao calcular alinhamentos de ajuste de rolagem. A propriedade define um inseto contra a caixa de padding do contêiner de rolagem. No nosso exemplo, um inseto 15vh adicional foi adicionado à parte de cima, o que instrui o navegador a considerar uma posição mais baixa, 15vh abaixo da borda superior do contêiner de rolagem, como a borda inicial vertical para ajustar a rolagem. Ao fazer a justificação, a borda inicial do elemento de destino da justificação fica alinhada com essa nova posição, deixando espaço acima.

A propriedade scroll-margin define o valor de saída usado para ajustar a caixa efetiva de destino do ajuste de forma semelhante a como o scroll-padding funciona no contêiner de rolagem de ajuste.

Talvez você tenha notado que essas duas propriedades não têm a palavra "snap". Isso é intencional, já que elas modificam a caixa para todas as operações de rolagem relevantes e não são apenas ajustes de rolagem. Por exemplo, o Chrome os leva em consideração ao calcular o tamanho da página para operações de rolagem de paginação, como PageDown e PageUp, e também ao calcular a quantidade de rolagem para a operação Element.scrollIntoView().

Veja a demonstração | Fonte

Interação com outras APIs de rolagem

API de rolagem do DOM

O ajuste de rolagem acontece após todas as operações de rolagem, incluindo aquelas iniciadas por um script. Ao usar APIs como Element.scrollTo, o navegador calcula a posição de rolagem pretendida para a operação e, em seguida, aplica a lógica de ajuste adequada para encontrar o local final alinhado. Portanto, não é necessário que o script de usuário faça cálculos manuais para ajustes.

Rolagem suave

A rolagem suave controla o comportamento de uma operação de rolagem programática, enquanto o ajuste de rolagem determina o destino. Como eles controlam aspectos ortogonais de rolagem, eles podem ser usados juntos e se complementar.

Comportamento de rolagem

A API de comportamento de rolagem controla como a rolagem é encadeada em vários elementos e não é afetada pelo ajuste de rolagem.

Advertências e práticas recomendadas

Evite usar o ajuste obrigatório quando os elementos de destino estiverem muito separados. Isso pode fazer com que o conteúdo entre as posições de ajuste se torne inacessível.

Em muitos casos, o ajuste de rolagem pode ser adicionado como uma melhoria sem precisar detectar o recurso. Se necessário, use @supports ou CSS.supports para detectar compatibilidade com o ajuste de rolagem do CSS. Evite usar scroll-snap-type, que também está presente na especificação descontinuada.

Detecção de recursos no CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Detecção de recursos em JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Não presuma que APIs de rolagem programática, como Element.scrollTo, sempre terminam no deslocamento de rolagem solicitado. O ajuste de rolagem pode ajustar o deslocamento de rolagem depois que a rolagem programática for concluída. Essa não era uma boa suposição, mesmo antes do ajuste de rolagem, já que a rolagem pode ter sido interrompida por outros motivos, mas é especialmente o caso com o ajuste de rolagem.

Trabalhos futuros

A experiência de rolagem foi o foco de uma pesquisa recente da equipe do Chrome. Os resultados da pesquisa identificaram várias áreas que precisam de mais trabalho para reduzir a lacuna entre as bibliotecas de plug-ins e o CSS. Os próximos trabalhos vão se concentrar em scroll-snap, incluindo:

  1. Disponibilidade e compatibilidade da API em vários navegadores.
  2. Trabalhe em novas APIs CSS, como scroll-start.
  3. Trabalhe com novos eventos do JS, como snapChanged().