SW Core
SW Core / Animações / Pin (prende na tela)

Pin (prende na tela) Animações

A seção fica grudada na tela enquanto a pessoa continua rolando — e, presa ali, as peças de dentro podem se mexer junto com a rolagem.

O que é

É o efeito de "a página para por um instante": a pessoa rola, mas aquela seção fica parada no lugar por um trecho, e depois solta e a página segue. Serve para segurar a atenção numa mensagem importante ou para contar algo em etapas: com a seção parada, o título pode sair de lado, a foto crescer, um selo girar — tudo comandado pela rolagem.

Você marca a seção com sw-ani="pin". Ela prende quando o topo dela encosta no topo da tela (ou onde você mandar com sw-ani-start) e fica presa pelo tanto de rolagem de sw-ani-end — 100% é uma tela de rolagem, o padrão é 300% (três telas). Filhos com sw-ani="move" andam até os valores que você der (sw-ani-x, -y, -scale, -rot, -opacity) enquanto ela está presa; com a palavra scrub eles seguem a rolagem para frente e para trás. Precisa do pacote de animação.

Quando usar

  • Mensagem principal que não pode passar batida (lançamento, promoção).
  • "Como funciona" em etapas: seção parada enquanto as peças se mexem.
  • Produto em destaque: a foto cresce enquanto a pessoa rola.
  • Se você só quer que um título/menu acompanhe a rolagem sem parar a página, o certo é o Fixed.
  • Para várias telas cheias trocando uma pela outra, o certo é o Sections.

Comece aqui

  1. 1

    Coloque o SW Core e o pacote de animação. O JS da animação vai antes do swcore.min.js.

    <link rel="stylesheet" href="swcore/swcore.min.css">
    <link rel="stylesheet" href="swcore/swcore.motion.min.css">
    
    <!-- fim do <body> -->
    <script src="swcore/swcore.motion.min.js"></script>
    <script src="swcore/swcore.min.js"></script>
  2. 2

    Marque a seção e diga por quanto tempo ela fica presa (100% = uma tela de rolagem). Os exemplos ao vivo estão logo abaixo — eles prendem de verdade enquanto você rola.

    <section sw-ani="pin" sw-ani-end="100%">
      <h2>Lançamento: o novo cardápio de verão</h2>
    </section>

Todas as variações

Cada quadro abaixo é o componente de verdade, rodando. O código embaixo é exatamente o que está no quadro: copie e cole.

1. Prende e solta

Estes quadros prendem de verdade: ao chegar neles, a caixa gruda na tela e se solta da moldura enquanto você rola; depois volta ao lugar. Role devagar.

Fico preso enquanto você rola
sw-ani-end="60%" — presa por pouco mais de meia tela de rolagem <div sw-ani="pin" sw-ani-end="60%" class="bg-g-pri p-xg r-m t-ct t-g fw6">Fico preso enquanto você rola</div>
Prendo no terço de cima da tela
sw-ani-start="top 30%" — prende mais para baixo na tela (30% do topo) <div sw-ani="pin" sw-ani-start="top 30%" sw-ani-end="60%" class="bg-g-sec p-xg r-m t-ct t-g fw6">Prendo no terço de cima da tela</div>
Prendo lá embaixo
sw-ani-start="late" — apelido de "top 70%": prende perto do pé da tela <div sw-ani="pin" sw-ani-start="late" sw-ani-end="60%" class="bg-g-drk p-xg r-m t-ct t-g fw6">Prendo lá embaixo</div>

2. Peças que se mexem enquanto está preso

Cada filho com sw-ani="move" anda até os valores que você der, enquanto a seção está presa. Com a palavra scrub no pin, eles seguem a rolagem (vão e voltam com ela); sem scrub, fazem o movimento sozinhos, rapidinho, quando o pin começa.

x 120
y -60
scale 1.5
rot 180
opacity 0
pin scrub + movers: sw-ani-x · sw-ani-y · sw-ani-scale · sw-ani-rot · sw-ani-opacity
<div sw-ani="pin scrub" sw-ani-end="100%">
  <div sw-ani="move" sw-ani-x="120">anda 120 px para a direita</div>
  <div sw-ani="move" sw-ani-y="-60">sobe 60 px</div>
  <div sw-ani="move" sw-ani-scale="1.5">cresce 50%</div>
  <div sw-ani="move" sw-ani-rot="180">gira meia volta</div>
  <div sw-ani="move" sw-ani-opacity="0">some</div>
</div>
gira
cresce
pin sem scrub — as peças se mexem sozinhas quando prende
<div sw-ani="pin" sw-ani-end="60%">
  <div sw-ani="move" sw-ani-rot="360">gira</div>
  <div sw-ani="move" sw-ani-scale="1.4">cresce</div>
</div>

3. Movimento preso à rolagem, sem prender a seção

Fora de um pin, sw-ani="move" vira um deslocamento que acompanha a rolagem enquanto o elemento atravessa a tela (e sw-ani="rotate" um giro). A página não para. Role devagar.

move
move — sobe enquanto você rola (80 px para cada lado) <div sw-ani="move" class="bg-g-pri p-m r-m t-ct">move</div>
160 px
move + sw-ani-distance="160" — anda mais <div sw-ani="move" sw-ani-distance="160" class="bg-g-sec p-m r-m t-ct">160 px</div>
de lado
move + sw-ani-dir="horizontal" — de lado <div sw-ani="move" sw-ani-dir="horizontal" class="bg-g-suc p-m r-m t-ct">de lado</div>
gira
rotate — dá uma volta inteira enquanto atravessa a tela <div sw-ani="rotate" class="bg-g-inf p-m r-m t-ct">gira</div>

Tabela de opções

PalavraO que fazExemplo
A seção presa
sw-ani="pin"Liga o efeito na seção.<section sw-ani="pin">
scrubPalavra junto do pin: os movers seguem a rolagem para frente e para trás.sw-ani="pin scrub"
sw-ani-scrubNúmero de segundos de "atraso macio" dos movers atrás da rolagem (em vez de colado).sw-ani-scrub="1"
sw-ani-endPor quanto de rolagem ela fica presa: % da tela, vh ou px. Padrão 300% (três telas).sw-ani-end="100%"
sw-ani-startOnde prende: padrão top top (topo da seção no topo da tela). Aceita os apelidos early (top 94%), normal (top 86%), late (top 70%) ou "parte-da-seção parte-da-tela".sw-ani-start="top 30%"
data-sw-end-sm / -md / -lgDuração diferente por tamanho de tela (menor que 768 px / até 1199 px / 1200 px ou mais). Escreva assim mesmo, com data-sw-.data-sw-end-sm="60%"
Peças dentro (movers)
sw-ani="move"Num filho da seção presa: ele anda enquanto ela está presa.<div sw-ani="move" …>
sw-ani-xPara onde anda na horizontal: número (px), %, vw, rem… Negativo = para a esquerda.sw-ani-x="-300"
sw-ani-yPara onde anda na vertical. Negativo = para cima.sw-ani-y="-80"
sw-ani-scaleTamanho final (0,1 a 5). 1 = igual.sw-ani-scale="1.4"
sw-ani-rotGiro final em graus (−1080 a 1080).sw-ani-rot="90"
sw-ani-opacityTransparência final (0 = some, 1 = inteiro).sw-ani-opacity="0"
Fora do pin
sw-ani="move"Desloca enquanto o elemento atravessa a tela.<div sw-ani="move">
sw-ani-distanceQuanto anda para cada lado, em px. Padrão 80.sw-ani-distance="160"
sw-ani-dirvertical (padrão) ou horizontal.sw-ani-dir="horizontal"
sw-ani="rotate"Dá uma volta (360°) enquanto atravessa a tela.<div sw-ani="rotate">
sw-ani-rotationRotate: quantos graus gira na travessia (-3600 a 3600; negativo gira ao contrário). Padrão 360.sw-ani-rotation="90"

Receitas prontas — usos reais

Situações que aparecem em quase todo site. Copie a que servir.

Essa seção prende a tela de verdade e se solta da moldura enquanto você rola — role bem devagar pra ver o efeito.

Chegou o verão

Cardápio novo

Açaí Sorvetes
<section sw-ani="pin scrub" sw-ani-end="150%" class="h-v flx f-cl j-ct alc gap-6 bg-g-drk t-ct p-xg">
  <p sw-ani="move" sw-ani-y="-40" sw-ani-opacity="0">Chegou o verão</p>
  <h2 sw-ani="move" sw-ani-scale="1.35">Cardápio novo</h2>
  <div class="flx gap-4">
    <span sw-ani="move" sw-ani-x="-120" sw-ani-rot="-12">Açaí</span>
    <span sw-ani="move" sw-ani-x="120" sw-ani-rot="12">Sorvetes</span>
  </div>
</section>

Essa seção prende a tela de verdade e se solta da moldura enquanto você rola — role bem devagar pra ver o efeito.

PROMOÇÃO DE INVERNO · ATÉ 40% OFF · 
SÓ ATÉ DOMINGO · FRETE GRÁTIS · 
<div sw-ani="pin" sw-ani-start="top 30%" sw-ani-end="120%" class="bg-sur bd r-m p-xg flx f-cl gap-4 ov-hi">
  <div sw-ani="marquee scrub" sw-ani-speed="90"><span>PROMOÇÃO DE INVERNO · ATÉ 40% OFF ·&nbsp;</span></div>
  <div sw-ani="marquee scrub" sw-ani-dir="right" sw-ani-speed="160"><span>SÓ ATÉ DOMINGO · FRETE GRÁTIS ·&nbsp;</span></div>
</div>

Essa seção prende a tela de verdade e se solta da moldura enquanto você rola — role bem devagar pra ver o efeito.

Como funciona em 3 passos

1. Escolha · 2. Pague · 3. Receba em casa

<section sw-ani="pin" sw-ani-end="100%" id="etapas" class="h-v flx f-cl j-ct alc gap-4">
  <h2>Como funciona em 3 passos</h2>
  <p>1. Escolha · 2. Pague · 3. Receba em casa</p>
  <progress id="barra" max="1" value="0"></progress>
</section>

<script>
  // enquanto está presa, o pin avisa o progresso (0 = acabou de prender, 1 = vai soltar)
  document.getElementById('etapas').addEventListener('sw:progress', (e) => {
    document.getElementById('barra').value = e.detail.progress;
  });
</script>

Eventos

sw:progress
Disparado na seção enquanto ela está presa e a pessoa rola. e.detail.progress vai de 0 (acabou de prender) a 1 (vai soltar).

API (JavaScript)

SWMotion.refresh()
Recalcula todos os pins (use depois de mudar a altura da página por JavaScript, ex.: abriu um acordeão grande acima).

Precisa de quê

  • swcore.min.css + swcore.motion.min.css, e swcore.motion.min.js antes do swcore.min.js.

Cuidados — erros comuns

  • A duração vem de sw-ani-end. sw-ani-dur não faz nada no pin.
  • Os movers vão até o valor, a partir de onde estão: sw-ani-x="-800" faz a peça sair para a esquerda, não entrar. Para "entrar", posicione a peça fora no seu CSS e mande-a para 0.
  • Sem a palavra scrub, os movers não acompanham a rolagem: fazem o movimento sozinhos, uma vez, quando a seção prende.
  • Um elemento em volta com transform, filter ou overflow: hidden atrapalha: a seção pode "pular" ou ficar presa dentro dele em vez de na tela.
  • Se você mudar a altura da página depois que ela carregou (conteúdo que chega por AJAX, acordeão aberto), chame SWMotion.refresh(), senão o pin prende no lugar errado.
  • Mais de três telas presas cansa: quem tem pressa sente que "a página não anda", principalmente no celular.

O que ele não faz

  • Quem ativou "reduzir movimento" no aparelho vê a seção presa, mas os movers ficam parados.