Puxar para revelar

"Puxar para revelar" é um padrão de interface em que o conteúdo (como uma barra de pesquisa ou um controle de atualização) fica oculto acima da parte de cima de uma área rolável no carregamento inicial, e o usuário pode puxar para baixo (rolar para cima) para revelá-lo. Esse padrão é usado com frequência em apps para dispositivos móveis e web apps para barras de pesquisa, filtros e outros controles secundários que precisam estar acessíveis, mas não imediatamente visíveis.

A propriedade CSS scroll-initial-target oferece uma maneira declarativa, somente CSS, de implementar esse padrão. Ao definir scroll-initial-target: nearest no elemento de conteúdo principal, o contêiner de rolagem será renderizado com o conteúdo oculto fora da visualização. Antes, os desenvolvedores dependiam de JavaScript (Element.scrollIntoView()) ou identificadores de fragmentos do URL (#content-id) para isso, mas ambos têm limitações e são difíceis de implementar.

Como implementar

Para implementar um padrão de puxar para revelar:

  1. Garanta um contêiner de rolagem: o elemento de destino precisa estar dentro de um contêiner de rolagem (um elemento com overflow que permite a rolagem, como overflow: auto). Pode ser qualquer elemento ancestral, incluindo o elemento raiz <html>.
  2. Defina o elemento oculto: coloque o conteúdo que você quer ocultar (por exemplo, uma barra de pesquisa) como o primeiro descendente dentro do contêiner de rolagem. Esse elemento será rolado para fora da visualização no carregamento inicial.
  3. Defina o conteúdo principal: coloque o elemento de conteúdo principal imediatamente após o elemento oculto. Esse é o elemento que o usuário deve ver primeiro.
  4. Segmentar o conteúdo principal: aplique scroll-initial-target: nearest ao elemento de conteúdo principal para que o contêiner de rolagem seja renderizado com ele rolado para visualização, ocultando o elemento acima dele.
  5. Adicione o ajuste de rolagem: para garantir que o elemento oculto esteja sempre totalmente visível ou totalmente oculto (e não fique em um estado parcialmente rolado), adicione scroll-snap-type: y mandatory ao contêiner de rolagem e scroll-snap-align: start ao elemento oculto e ao elemento de conteúdo principal.
/**
 * ANCESTOR: Define the scroll container.
 * Scroll snapping ensures the search bar is always
 * either fully visible or fully hidden.
 */
.scroll-container {
  height: 100vh;
  overflow-y: auto;
  scroll-snap-type: y mandatory;
}

/**
 * HIDDEN ELEMENT: The search bar hidden above the fold on load.
 * It has scroll-snap-align so it snaps into place when pulled down.
 */
.search-bar {
  height: 60px;
  scroll-snap-align: start;
}

/**
 * MAIN CONTENT + TARGET: The element the user sees first.
 * scroll-snap-align makes it a valid snap point.
 * scroll-initial-target tells the browser to scroll here on
 * initial render, hiding the search bar above it.
 */
.main-content {
  scroll-snap-align: start;
  scroll-initial-target: nearest;
}

Implementação estratégica e práticas recomendadas

  • RECOMENDAMOS usar scroll-initial-target: nearest quando você quiser chamar a atenção do usuário para uma parte específica de uma área rolável ao carregar e ocultar intencionalmente unidades de interface periféricas, como uma barra de pesquisa na parte de cima.
  • NÃO confunda isso com o foco de acessibilidade. Essa propriedade move apenas a janela de visualização visual, não o foco do teclado. Você precisa gerenciar manualmente o element.focus() se o destino for o ponto de partida para usuários de teclado.
  • NÃO use essa propriedade se precisar de uma animação de rolagem suave no carregamento. Ela é discreta e define a posição instantaneamente durante a fase de layout.
  • NÃO defina scroll-initial-target em vários elementos no mesmo contêiner rolável. Se vários elementos especificarem scroll-initial-target: nearest, o navegador vai selecionar o que aparecer primeiro na ordem da árvore do DOM.
  • CONSIDERE a hierarquia de precedência: um fragmento do URL (por exemplo, example.com/#top) e a propriedade scroll-start no nível do contêiner têm precedência sobre scroll-initial-target.

Estratégia de fallback

Para navegadores que ainda não são compatíveis com a API, use um substituto de JavaScript. Para puxar o conteúdo e revelar, o conteúdo principal precisa estar vinculado ao start (parte de cima) do contêiner.

/**
 * Progressive Enhancement Fallback
 */
document.addEventListener("DOMContentLoaded", () => {
  // Check for native CSS support
  if (!CSS.supports("scroll-initial-target", "nearest")) {
    const targetContent = document.querySelector('.main-content.target');
    if (targetContent) {
      // Use behavior: "instant" to mimic the native CSS behavior
      // 'block: start' should match your CSS 'scroll-snap-align' (or expected top position)
      targetContent.scrollIntoView({ behavior: 'instant', block: 'start' });
    }
  }
});