CSS Scroll Snap

Há algum tempo eu escrevi um post falando sobre o IntersectionObserver e como utilizá-lo para enriquecer um carrossel de fotos. Mas ficou faltando uma funcionalidade muito utilizada em carrosséis: o scroll que ajusta as imagens na tela, mostrando ao usuário sempre a imagem centralizada certinha.

Para conseguir esse efeito existe um módulo em CSS chamado CSS Scroll Snap que facilita e muito a implementação, deixando a transição de imagens bem fluída e bonita.

Nesse post eu vou mostrar um caso de uso complementando o carrossel ;)

Apenas duas propriedades são necessárias para o funcionamento básico e que já são o suficiente para o exemplo.

scroll-snap-type

Utilizada no container das imagens, essa propriedade é responsável por configurar o comportamento do scroll.

Possíveis valores chave:

  • scroll-snap-type: none;
  • scroll-snap-type: x;
  • scroll-snap-type: y;
  • scroll-snap-type: block;
  • scroll-snap-type: inline;
  • scroll-snap-type: both;

No exemplo abaixo eu mostro as combinações mais utilizadas dessa propriedade, o scroll em linha ou coluna (x ou y), atrelado ao mandatory ou proximity, que são propriedades opcionais.

Observe que, no caso em que foi utilizado o mandatory, a imagem sempre fica alinhada com as bordas do carrossel e que, no caso do proximity, apenas quando a imagem for arrastada e liberada próxima das bordas ela vai se deslocar automaticamente, possibilitando que o carrossel mostre duas imagens ao mesmo tempo.

No nosso caso como o scroll é no eixo X e o comportamento desejado é que as margens das imagens fiquem sempre presas às margens da tela, utilizaremos o scroll-snap-type: x mandatory;.

scroll-snap-align

Propriedade usada nos itens e determina o alinhamento relativo ao container scrollado.

O valores são parecidos com um alinhamento simples:

  • scroll-snap-align: none;
  • scroll-snap-align: start end;
  • scroll-snap-align: center;
  • scroll-snap-align: inherit;
  • scroll-snap-align: initial;
  • scroll-snap-align: unset;

Quando o container é menor que seus filhos e o alinhamento é o start end, as imagens vão se alinhar dependendo da proximidade com o início e o fim.

Neste caso vamos utilizar a propriedade scroll-snap-align: center, como podemos ver no CSS:

.carousel {
  display: flex;
  overflow: auto;
  max-width: 400px;
  margin-left: auto;
  margin-right: auto;
  border: solid 1px #dad5d5;
  border-radius: 3px;
  padding: 0;

  scroll-snap-type: x mandatory;
}

.carousel li {
  display: flex;
  min-width: 400px;
  background-color: #e5e5e5;
  justify-content: center;

  scroll-snap-align: center;
}

scroll-padding

Caso o efeito desejado seja que as imagens scrolladas não colem nas bordas, é possível utilizar o scroll-padding, de maneira muito similar ao padding para delimitar um espaço entre a borda e o conteúdo.

scroll-snap-stop

É possível observar nos exemplos anteriores que a funcionalidade só se faz presente quando se para de scrollar, mas até esse momento é possível passar por vários snap points.

Caso algum desses pontos seja muito importante e não deva ser pulado, é possível utilizar a propriedade scroll-snap-stop: always, deste modo esta será uma parada obrigatória. Entretanto a compatibilidade dessa propriedade até o momento é bem baixa…

Alt “Compatibilidade atual da propriedade scroll-snap-stop”

E apesar de a tabela de compatibilidade incluir o Chrome, nos meus testes não funcionou =(.

Compatibilidade

Infelizmente, como acontece com outras implementações de specs CSS, CSS Scroll Snap é a nova versão do que já foi chamado de Scroll Snap Points.

Fora a confusão que fica com os nomes, é preciso ter cuidado com browsers que ainda não são compativeis com a nova versão. A situação atual é essa:

Alt “Compatibilidade Atual”

Esse artigo da MDN pode te ajudar a lidar com as duas versões caso seja necessário ;)

Conclusão

O scroll da página é algo básico mas extremamente importante, quando mal implementado ele pode estragar totalmente a experiência do usuário.

Utilizar o CSS Scroll Snap garante uma solução simples e nativa, que evita malabarismos no código e proporciona uma experiência muito fluida para o usuário.

Para se aprofundar mais no assunto você pode consultar a documentação completa.

Se você ficou com alguma dúvida ou quer compartilhar a sua experiência fique à vontade para utilizar a caixa de comentários. Obrigada e até a próxima!