Che si tratti di un amore o di un'odio, la parallasse è destinata a durare. Se usata con accortezza, può aggiungono profondità e originalità a un'app web. Il problema, però, è che implementare realizzare una parallasse in modo efficace può essere difficile. In questo articolo, una soluzione che sia efficace e che funzioni cross-browser.
TL;DR
- Non utilizzare eventi di scorrimento o
background-position
per creare animazioni con parallasse. - Utilizza le trasformazioni 3D CSS per creare un effetto parallasse più accurato.
- In Safari per dispositivi mobili, utilizza
position: sticky
per assicurarti che l'effetto Parallasse vengono propagate.
Se vuoi la soluzione integrata, vai al repository GitHub di esempi di elementi UI e recupera il Assistente Parallasse JS. Puoi vedere una demo dal vivo dello scorrimento parallasse nei GitHub di ASL.
Parallasse di problemi
Per cominciare, diamo un'occhiata a due modi comuni per ottenere una parallasse e, in particolare, perché non sono adatti ai nostri scopi.
Male: vengono utilizzati gli eventi di scorrimento
Il requisito chiave della parallasse è che deve essere accoppiato con scorrimento. della ogni singola modifica nella posizione di scorrimento della pagina, l'elemento di parallasse dovrebbe aggiornarsi. Anche se sembra semplice, un meccanismo importante di browser moderni è la loro capacità di funzionare in modo asincrono. Ciò si applica, nei nostri caso particolare, per scorrere gli eventi. Nella maggior parte dei browser, gli eventi di scorrimento vengono pubblicati come "best effort" e non sono garantiti per essere pubblicati su ogni frame del animazione di scorrimento.
Questa informazione importante ci spiega perché è necessario evitare Soluzione basata su JavaScript che sposta gli elementi in base agli eventi di scorrimento: JavaScript non garantisce che la parallasse mantenga il passo con le la posizione di scorrimento della pagina. Nelle versioni precedenti di Safari per il mobile, gli eventi di scorrimento venivano effettivamente consegnato alla fine del rotolo, il che rendeva impossibile Effetto di scorrimento basato su JavaScript. Le versioni più recenti offrono eventi di scorrimento durante l'animazione, ma, come per Chrome, ha fatto il "best effort" base. Se il thread principale è occupato con qualsiasi altro lavoro, gli eventi di scorrimento non verranno consegnati il che significa che l'effetto Parallasse andrà perso.
Errore: aggiornamento di background-position
in corso...
Un'altra situazione che vogliamo evitare è dipingere su ogni fotogramma. Molte soluzioni
provare a modificare background-position
per ottenere il look parallasse, che
fa sì che il browser riproduca le parti interessate della pagina quando scorrono; e che
può essere abbastanza costoso da bloccare significativamente l'animazione.
Se vogliamo mantenere la promessa del moto parallasse, vogliamo qualcosa che può essere applicata come proprietà accelerata (che oggi richiede trasformazioni e opacità) e che non si basa su eventi di scorrimento.
CSS in 3D
Sia Scott Kellum che Keith Clark hanno ha svolto un lavoro significativo nell'utilizzo di CSS 3D per ottenere il movimento di parallasse, e la tecnica utilizzata è effettivamente questa:
- Configura un elemento contenitore per scorrere con
overflow-y: scroll
(e probabilmenteoverflow-x: hidden
). - Allo stesso elemento applica un valore
perspective
e unperspective-origin
impostato sutop left
o0 0
. - Applicare una traslazione in Z agli elementi secondari di quell'elemento e ridimensionarla per fornire un movimento con parallasse senza influenzarne le dimensioni sullo schermo.
Il CSS per questo approccio ha il seguente aspetto:
.container {
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
perspective: 1px;
perspective-origin: 0 0;
}
.parallax-child {
transform-origin: 0 0;
transform: translateZ(-2px) scale(3);
}
Il che presuppone uno snippet di codice HTML simile al seguente:
<div class="container">
<div class="parallax-child"></div>
</div>
Regolazione della scala per la prospettiva
Se spingi all'indietro l'elemento secondario, questo diventerà più piccolo proporzionale al valore di prospettiva. Puoi calcolare di quanto sarà necessario fare lo scale up con questa equazione: (prospettiva - distanza) / prospettiva. Poiché molto probabilmente vuoi che l'elemento di parallasse risulti in parallasse, ma appaia nelle dimensioni da noi create, dovrebbe essere ampliato in questo modo, piuttosto che essere lasciato così com'è.
Nel caso del codice riportato sopra, la prospettiva è 1px e
La distanza Z di parallax-child
è -2 px. Ciò significa che l'elemento dovrà
lo scale up di 3x, come puoi vedere il valore inserito nel codice:
scale(3)
.
Per tutti i contenuti a cui non è applicato un valore translateZ
, puoi:
sostituisci un valore pari a zero. Ciò significa che la scala è (prospettiva - 0) /
, che calcola il valore 1, il che significa che è stato scalato
né verso l'alto né verso il basso. Molto utile, davvero.
Come funziona questo approccio
È importante chiarire perché funziona, poiché la utilizzeremo
in poco tempo. Lo scorrimento è in pratica una trasformazione, ed è per questo che può
accelerated; comporta per lo più lo spostamento di strati all'interno della GPU. In un
scorrimento tipico, ovvero senza alcuna nozione di prospettiva, scorrimento
avviene in modo 1:1 quando si confrontano l'elemento di scorrimento e i relativi elementi secondari.
Se fai scorrere un elemento verso il basso di 300px
, i relativi elementi secondari vengono trasformati verso l'alto.
dello stesso importo: 300px
.
Tuttavia, l'applicazione di un valore di prospettiva all'elemento scorrevole
con questo processo; cambia le matrici che supportano la trasformazione di scorrimento.
Ora uno scorrimento di 300 px può spostare gli elementi secondari di 150 px solo, a seconda del
perspective
e translateZ
valori che hai scelto. Se un elemento ha un
Se il valore di translateZ
è 0, verrà fatto scorrere il dito 1:1 (come in passato), ma un asset secondario
spostato in Z lontano dalla prospettiva dell'origine verrà fatto scorrere con un
! Risultato netto: movimento di parallasse. E, cosa molto importante, viene gestito come
parte del meccanismo di scorrimento interno del browser, il che significa
non è necessario ascoltare gli eventi scroll
o modificare background-position
.
Una mosca nell'unguento: Safari mobile
Ci sono delle avvertenze per ogni effetto e una delle più importanti per le trasformazioni riguarda di conservare gli effetti 3D degli elementi secondari. Se ci sono elementi in una gerarchia tra l'elemento con una prospettiva e i suoi elementi secondari con parallasse, la prospettiva 3D è "appiattita", nel senso che l'effetto è stato perso.
<div class="container">
<div class="parallax-container">
<div class="parallax-child"></div>
</div>
</div>
Nel codice HTML riportato sopra, il .parallax-container
è nuovo e sarà efficace
piatte il valore perspective
e perdiamo l'effetto parallasse. La soluzione
nella maggior parte dei casi è piuttosto semplice: si aggiunge transform-style: preserve-3d
all'elemento, causando la propagazione di eventuali effetti 3D (come la nostra
) che sono state applicate più in alto nell'albero.
.parallax-container {
transform-style: preserve-3d;
}
Nel caso di Safari Mobile, tuttavia, la situazione è un po' più contorta.
L'applicazione di overflow-y: scroll
all'elemento contenitore funziona tecnicamente, ma in
il costo della possibilità di far scorrere l'elemento di scorrimento. La soluzione consiste nell'aggiungere
-webkit-overflow-scrolling: touch
, ma ridurrà anche perspective
senza parallasse.
Da un punto di vista del miglioramento progressivo, probabilmente non si tratta di un problema problema. Se non riusciamo a realizzare il parallasse in ogni situazione, la nostra app continuerà a funzionare, sarebbe utile trovare una soluzione.
position: sticky
in soccorso!
Esistono, infatti, alcune fonti di aiuto sotto forma di position: sticky
, che esiste per
consentire agli elementi di "essere bloccati" nella parte superiore dell'area visibile o a un determinato elemento principale
durante lo scorrimento. Le specifiche, come la maggior parte di esse, sono piuttosto pesanti, ma contengono una
una piccola gemma utile in:
A prima vista, ciò potrebbe non significare molto, ma un aspetto fondamentale quella frase è quando si riferisce a come, esattamente, la stickiness di un elemento calcolato: "l'offset viene calcolato con riferimento al predecessore più vicino con una casella di scorrimento". In altre parole, la distanza per spostare l'elemento fisso (affinché appaia attaccata a un altro elemento o all'area visibile) è calcolato prima di applicare qualsiasi altra trasformazione, non dopo. Ciò significa come nell'esempio di scorrimento precedente, se l'offset è stato calcolato a 300 px, c'è una nuova opportunità per usare le prospettive (o qualsiasi altra trasformazione) per modificare il valore di offset di 300 px prima che venga applicato a qualsiasi elementi.
Se applichi position: -webkit-sticky
all'elemento di parallasse, possiamo
"invertire" efficacemente l'effetto di appiattimento di -webkit-overflow-scrolling:
touch
. Ciò garantisce che l'elemento di parallasse faccia riferimento all'elemento più vicino
predecessore con una casella di scorrimento, che in questo caso è .container
. Poi,
come in precedenza, .parallax-container
applica un valore perspective
,
che modifica l'offset di scorrimento calcolato e crea un effetto parallasse.
<div class="container">
<div class="parallax-container">
<div class="parallax-child"></div>
</div>
</div>
.container {
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.parallax-container {
perspective: 1px;
}
.parallax-child {
position: -webkit-sticky;
top: 0px;
transform: translate(-2px) scale(3);
}
In questo modo viene ripristinato l'effetto Parallasse per Safari per dispositivi mobili, un'ottima notizia per tutti tondo!
Avvertenze sul posizionamento persistente
Tuttavia, c'è una differenza in questo caso: position: sticky
modifica il valore
le meccaniche della parallasse. Il posizionamento persistente cerca di fissare l'elemento a
a scorrimento, mentre una versione non permanente no. Ciò significa che
gli elementi parallasse con persistenti sono l'opposto di quello senza:
- Con
position: sticky
, più l'elemento è vicino a z=0 meno è che si sposta. - Senza
position: sticky
, più l'elemento è vicino a z=0, più che si sposta.
Se tutto ti sembra un po' astratto, dai un'occhiata a questa demo di Robert Flack, che dimostra come gli elementi si comportano diversamente con e senza persistenti posizionamento. Per vedere la differenza, è necessario Chrome Canary (versione 56) al momento della stesura di questo articolo) o Safari.
Una demo di Robert Flack che mostra come
position: sticky
influisce sullo scorrimento con parallasse.
Diversi bug e soluzioni alternative
Come per ogni cosa, però, ci sono ancora protuberanze e protuberanze che devono attenuato su:
- Il supporto fisso non è coerente. L'assistenza è ancora in fase di implementazione in
Chrome, Edge non sono completamente supportati e Firefox presenta bug di pittura quando gli annunci persistenti vengono combinati con le trasformazioni di prospettive. In tale
casi, vale la pena inserire un piccolo codice per aggiungere solo
position: sticky
(il versione con prefisso-webkit-
) quando è necessario (per Safari per dispositivi mobili) . - L'effetto non "funziona solo" in Edge. Edge prova a gestire lo scorrimento verso a livello di sistema operativo, il che è generalmente un aspetto positivo, ma in questo caso dal rilevare i cambiamenti di prospettiva durante lo scorrimento. Per risolvere il problema, puoi aggiungere un elemento con posizione fissa, poiché sembra passare da Edge a un metodo di scorrimento non del sistema operativo, e assicura che tenga conto dei cambiamenti di prospettiva.
- "I contenuti della pagina sono diventati davvero vasti!" Molti browser tengono conto della scala
quando decidono le dimensioni dei contenuti della pagina, ma purtroppo Chrome e Safari
non tengono conto del punto di vista. Quindi...
se a un elemento è stata applicata una scala pari a 3 volte,
le barre di scorrimento e simili, anche se l'elemento si trova a 1x dopo il
perspective
è stato applicato. È possibile aggirare il problema ridimensiona gli elementi dall'angolo in basso a destra (contransform-origin: bottom right
), perché fa crescere gli elementi di grandi dimensioni nell'elemento "regione esclusa" (in genere in alto a sinistra) dell'area scorrevole; scorrevole le regioni non ti consentono mai di visualizzare o scorrere verso i contenuti della regione esclusa.
Conclusione
Il parallasse è un effetto divertente se usato in modo intelligente. Come puoi vedere, è possibile per implementarlo in un modo performante, accoppiato con lo scorrimento e cross-browser. Poiché richiede un po' di agitazione matematica e una piccola boilerplate per ottenere l'effetto desiderato, abbiamo creato una piccola raccolta di supporto e un esempio, che puoi trovare nel nostro repository GitHub di esempi di elementi UI.
Gioca e facci sapere cosa ne pensi.