Te guste o no, el paralaje llegó para quedarse. Cuando se usa con cuidado, puede agregar profundidad y sutileza a una aplicación web. Sin embargo, el problema es que implementar usar paralaje de forma eficaz puede ser un desafío. En este artículo, analizaremos una solución que sea eficaz y, igualmente importante, que funcione en varios navegadores.
Resumen
- No uses eventos de desplazamiento ni
background-position
para crear animaciones de paralaje. - Usa transformaciones 3D en CSS para crear un efecto de paralaje más preciso.
- En Mobile Safari, utiliza
position: sticky
para garantizar que el efecto de paralaje se propaga.
Si quieres la solución directa, dirígete al repositorio de GitHub de muestras de elementos de la IU y toma el JS del asistente de Paralaje. Puedes ver una demostración en vivo del desplazador paralaje en la Repositorio de GitHub.
Paralajeres de problemas
Para comenzar, veamos dos formas comunes de lograr un paralaje. efecto y, en particular, por qué no son adecuadas para nuestros fines.
Malo: uso de eventos de desplazamiento
El requisito clave del paralaje es que debe tener acoplamiento de desplazamiento. para cada cambio en la posición de desplazamiento de la página, la capa de la posición debe actualizarse. Si bien eso suena simple, es un mecanismo importante para navegadores modernos es su capacidad de funcionar de forma asíncrona. Esto se aplica, en nuestra un caso particular, para desplazar eventos. En la mayoría de los navegadores, los eventos de desplazamiento se entregan como “mejor esfuerzo” y no se garantiza que se entreguen en cada fotograma de la animación de desplazamiento.
Esta información importante nos dice por qué debemos evitar un Solución basada en JavaScript que mueve elementos en función de eventos de desplazamiento: JavaScript no garantiza que el paralaje siga el mismo la posición de desplazamiento de la página. En las versiones anteriores de Mobile Safari, los eventos de desplazamiento eran entregado al final del manuscrito, lo que impedía hacer una Efecto de desplazamiento basado en JavaScript Las versiones más recientes sí incluyen eventos de desplazamiento durante la animación, pero, al igual que en Chrome, en un "mejor esfuerzo" base. Si el botón el subproceso principal está ocupado con otro trabajo, no se entregarán los eventos de desplazamiento de inmediato, lo que significa que se perderá el efecto de paralaje.
Incorrecto: actualizando background-position
Otra situación que nos gustaría evitar es pintar en cada marco. Muchas soluciones
intenta cambiar background-position
para proporcionar el aspecto de paralaje, que
hace que el navegador vuelva a pintar las partes afectadas de la página durante el desplazamiento
puede ser lo suficientemente costoso como para bloquear significativamente la animación.
Si queremos cumplir con la promesa del movimiento con paralaje, queremos algo se puede aplicar como una propiedad acelerada (lo que hoy significa que mantener transformaciones y opacidad), y que no se basa en eventos de desplazamiento.
CSS en 3D
Tanto Scott Kellum como Keith Clark tienen realicé un trabajo importante en el uso de CSS 3D para lograr movimientos con paralaje, y la técnica que utilizan es efectivamente la siguiente:
- Configura un elemento contenedor para desplazarte con
overflow-y: scroll
(y probablementeoverflow-x: hidden
). - A ese mismo elemento, aplica un valor
perspective
y unperspective-origin
se establece entop left
o0 0
. - Aplica una traslación en Z a los elementos secundarios de ese elemento y reduce su escala para proporcionar movimiento con paralaje sin afectar su tamaño en pantalla.
El CSS para este enfoque se ve así:
.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);
}
Lo que supone un fragmento de HTML como el siguiente:
<div class="container">
<div class="parallax-child"></div>
</div>
Ajustar la escala para la perspectiva
Si se vuelve a enviar el elemento secundario, este se reducirá en proporción al del valor de la perspectiva. Puedes calcular cuánto necesitarás escalar verticalmente con esta ecuación: (perspectiva - distancia) / perspectiva. Dado que probablemente queremos que el elemento de paralaje paralaje, pero que aparezca en el tamaño que creamos, debería escalarse verticalmente de esta manera, en lugar de quedar tal como está.
En el caso del código anterior, la perspectiva es 1 px, y la
La distancia Z de parallax-child
es de -2 px. Esto significa que el elemento deberá
se escale verticalmente en 3x, que puedes ver es el valor conectado al código:
scale(3)
Puedes hacer lo siguiente con el contenido que no tenga aplicado un valor de translateZ
sustituirá un valor de cero. Esto significa que la escala es (perspective - 0) /
, que da un valor de 1, lo que significa que se escaló
ni hacia arriba ni hacia abajo. Bastante útil, de verdad.
Cómo funciona este enfoque
Es importante que quede claro por qué esto funciona, ya que lo usaremos
tu conocimiento en breve. El desplazamiento es efectivamente una transformación, por eso se puede
accelerated; sobre todo implica cambiar las capas con la GPU. En una
un desplazamiento común, que no tiene noción de perspectiva, se desvía
se produce de manera 1:1 cuando se compara el elemento de desplazamiento con sus elementos secundarios.
Si te desplazas un elemento hacia abajo por 300px
, sus elementos secundarios se transforman hacia arriba
por la misma cantidad: 300px
.
Sin embargo, aplicar un valor de perspectiva al elemento de desplazamiento es un desorden
en este proceso; cambia las matrices que respaldan la transformación de desplazamiento.
Ahora, un desplazamiento de 300 px solo puede mover a los elementos secundarios 150 px, dependiendo del
Los valores de perspective
y translateZ
que elijas. Si un elemento tiene un valor
translateZ
tiene un valor 0, se desplazará a la par de 1:1 (como antes), pero un elemento secundario
empujadas en Z desde el origen de la perspectiva se desplazará en un diferente
de conversiones. Resultado neto: movimiento con paralaje. Y, muy importante, esto se maneja como
parte de la maquinaria de desplazamiento interno del navegador automáticamente, lo que significa que hay
No es necesario escuchar eventos de scroll
ni cambiar background-position
.
Una mosca en el ungüento: Mobile Safari
Hay advertencias para cada efecto, y una importante para las transformaciones es sobre la conservación de efectos 3D en elementos secundarios. Si hay elementos en las la jerarquía entre el elemento con una perspectiva y sus elementos secundarios con paralaje, la perspectiva 3D es "aplanada", lo que significa que el efecto se pierde.
<div class="container">
<div class="parallax-container">
<div class="parallax-child"></div>
</div>
</div>
En el código HTML anterior, el elemento .parallax-container
es nuevo y efectivamente
aplanar el valor perspective
y perderemos el efecto de paralaje. La solución,
en la mayoría de los casos, es bastante sencillo: agregas transform-style: preserve-3d
.
al elemento, lo que provoca que se propague cualquier efecto 3D (como nuestra perspectiva
valor) que se aplicaron más arriba en el árbol.
.parallax-container {
transform-style: preserve-3d;
}
Sin embargo, en el caso de Mobile Safari, la situación es un poco más complicada.
Técnicamente, la aplicación de overflow-y: scroll
al elemento contenedor funciona, pero en
el costo de poder desplazar el elemento de desplazamiento. La solución es agregar
-webkit-overflow-scrolling: touch
, pero también compactará el perspective
y no tenemos paralaje.
Desde el punto de vista de la mejora progresiva, es probable que no sea un punto problema. Si no podemos usar paralaje en todas las situaciones, nuestra app seguirá funcionando, pero estaría bueno encontrar una solución alternativa.
¡position: sticky
al rescate!
De hecho, hay ayuda en forma de position: sticky
, que existe para
permiten que los elementos se “estén” a la parte superior del viewport o a un elemento superior determinado
durante el desplazamiento. Las especificaciones, como la mayoría, son bastante pesadas, pero contiene
pequeña gema útil en:
Esto puede no parecer mucho a primera vista, pero es un punto clave esa oración se refiere a cómo, exactamente, el grado de interés de un elemento calculado: "el desplazamiento se calcula con respecto al principal más cercano con un cuadro de desplazamiento". En otras palabras, la distancia para mover el elemento fijo (para que aparezca unido a otro elemento o al viewport) se se calculan antes de que se apliquen otras transformaciones, no después. Esto significa que, al igual que en el ejemplo de desplazamiento anterior, si el desplazamiento se calculó a los 300 píxeles, hay una nueva oportunidad de usar perspectivas (o cualquier otra transformación). para manipular ese valor de desplazamiento de 300 px antes de que se aplique a cualquier o de terceros.
Si aplicamos position: -webkit-sticky
al elemento de paralaje, podemos
“revertir” eficazmente el efecto de compactación de -webkit-overflow-scrolling:
touch
Esto garantiza que el elemento de paralaje haga referencia a la
principal con un cuadro de desplazamiento, que en este caso es .container
. Luego,
Al igual que antes, .parallax-container
aplica un valor perspective
.
que cambia el desplazamiento calculado
y crea un efecto de paralaje.
<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);
}
Esto restaura el efecto de paralaje de Mobile Safari, lo cual es una excelente noticia redondo.
Advertencias sobre el posicionamiento fijo
Sin embargo, hay una diferencia: position: sticky
sí altera la
la mecánica del paralaje. El posicionamiento fijo intenta
apegar el elemento al
de desplazamiento, mientras que las versiones no fijas no. Esto significa que el
paralaje con pegajoso termina siendo lo contrario a aquel que no tiene:
- Con
position: sticky
, cuanto más cerca se encuentra el elemento a z=0, menos se encuentra. se mueve. - Sin
position: sticky
, cuanto más cerca se encuentre el elemento de z=0, más se mueve.
Si todo te parece un poco abstracto, mira esta demostración de Robert Flack, que demuestra cómo los elementos se comportan de manera diferente con y sin elementos fijos y el posicionamiento de los datos. Para ver la diferencia, necesitas Chrome Canary (versión 56) al momento de escribir) o Safari.
Una demostración de Robert Flack en la que se muestra cómo
position: sticky
afecta el desplazamiento con paralaje.
Diversos errores y soluciones alternativas
Sin embargo, como con todo, todavía hay bultos y protuberancias que deben suavizado:
- La compatibilidad fija no es coherente. La compatibilidad se sigue implementando
Chrome, Edge no es compatible por completo, y Firefox tiene errores de pintura cuando lo fijo se combina con transformaciones de perspectiva. De tal forma
vale la pena agregar un poco de código para agregar únicamente
position: sticky
(el versión con el prefijo-webkit-
) cuando sea necesario, por ejemplo, para Mobile Safari solamente. - El efecto no funciona solo. en Edge. Edge intenta controlar el desplazamiento en el nivel de SO, lo cual suele ser bueno, pero, en este caso, evita la detección de los cambios de perspectiva durante el desplazamiento. Para solucionar este problema, puedes agregar Un elemento de posición fija, ya que parece cambiar Edge a un método de desplazamiento sin SO y garantiza que tenga en cuenta los cambios de perspectiva.
- “El contenido de la página se ha hecho enorme”. Muchos navegadores tienen en cuenta la escala
para decidir el tamaño del contenido
de la página, pero Chrome y Safari
no tengan en cuenta la perspectiva. De esta manera,
si se aplica una escala de 3x a un elemento, se puede
verás las barras de desplazamiento y otros similares, incluso si el elemento está en 1x después de
Se aplicó
perspective
. Es posible solucionar este problema elementos escalando desde la esquina inferior derecha (contransform-origin: bottom right
), lo cual funciona porque hará que los elementos de gran tamaño crezcan dentro de “región negativa” (por lo general, en la parte superior izquierda) del área desplazable; desplazable regiones nunca te permiten ver contenido en la región negativa ni desplazarte hasta ellos.
Conclusión
El paralaje es un efecto divertido cuando se usa cuidadosamente. Como pueden ver, es posible para implementarlo de manera eficaz, con desplazamiento y en varios navegadores. Dado que requiere un poco de giro matemático y una pequeña cantidad de código estándar para lograr el efecto deseado, empaquetamos una pequeña biblioteca auxiliar y muestra, que puedes encontrar en nuestro repositorio de GitHub de muestras de elementos de la IU.
Diviértete y cuéntanos cómo te va.