📜 ⬆️ ⬇️

Pure CSS parallax

This article shows how to make a parallax effect on a website using pure CSS using CSS transformations and frauds with 3d.

Parallax is almost always created using JavaScript and, more often, it turns out to be resource-intensive, due to hanging listeners to the scroll event, modifying the DOM directly and triggering unnecessary redrawing and permutations. All this happens asynchronously with the flow, in which the browser renders the page, because of what the scroll starts to slow down, and the picture breaks into pieces. More accurate parallax implementations track the scroll and use pending DOM updates using requestAnimationFrame . It turns out a qualitatively different result, but why not get rid of JavaScript at all?

The transfer of the parallax effect in CSS saves you from performance problems and unnecessary manipulations, allowing the browser to adjust everything itself through hardware acceleration. As a result, almost all resource-intensive processes are processed directly by the browser engine. The frame rate (FPS) remains stable, and the picture becomes smooth. Plus, you can immediately combine parallax with other CSS chips — media queries or supports. Responsive parallax - what?

Watch the demo
')

Theory


Before diving into the understanding of the work of this mechanism, we will create the necessary markup:

 <div class="parallax"> <div class="parallax__group"> <div class="parallax__layer parallax__layer--back"> ... </div> <div class="parallax__layer parallax__layer--base"> ... </div> </div> <div class="parallax__group"> ... </div> </div> 

And basic styles:

 .parallax { perspective: 1px; height: 100vh; overflow-x: hidden; overflow-y: auto; } .parallax__layer { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } .parallax__layer--base { transform: translateZ(0); } .parallax__layer--back { transform: translateZ(-1px); } 

All magic happens in the parallax class. Defining the properties of the height and perspective styles will set the perspective of the element at its center, creating a fixed 3D viewport. overflow-y: auto will allow the content inside the element to scroll normally, while the descendants of the element will be drawn relative to a fixed perspective. This is the key to creating a parallax effect.

Next, the parallax__layer class. As the name implies, it defines the content layer to which the parallax effect will be applied. An element with this class is torn out of the general flow of content and positioned to fill its container.

Finally, we have the parallax__layer--base and parallax__layer--back modifier classes. They are needed to adjust the speed of scrolling the parallax of elements, shifting them along the Z axis (removing or approaching the viewport). For brevity, I made only two scrolling speeds - later we will add a few more.

Watch the demo

Depth correction


Since the parallax effect is created due to 3D transformations, the displacement of an element along the Z axis has a side effect - the dimensions of the element change, depending on whether it is closer or further to the viewport. To fix this, we need to apply a scale() transformation so that the element is drawn in its original size:

 .parallax__layer--back { transform: translateZ(-1px) scale(2); } 

The scale factor can be calculated using the formula 1 + (translateZ * -1) / perspective) . For example, if the perspective of the viewport is set as 1px and we shift the element by -2px along the Z axis, then the coefficient will be scale(3) .

 .parallax__layer--deep { transform: translateZ(-2px) scale(3); } 

Watch the demo with adjusted depth

Bed speed regulation


Layer speed is controlled by a combination of perspective and Z offset values. Elements with negative Z values ​​will scroll more slowly than elements with positive values. The greater the difference in value from 0, the clearer the parallax effect.
(i.e. translateZ(-10px) will scroll slower than translateZ(-1px) ).

Creating different sections of the parallax effect


The previous examples showed the basic technique of using simple content, but after all, most parallax sites divide a page into different sections with different effects. Here's how to implement this in our method.

First, we need the parallax__group element to group our layers together:

 <div class="parallax"> <div class="parallax__group"> <div class="parallax__layer parallax__layer--back"> ... </div> <div class="parallax__layer parallax__layer--base"> ... </div> </div> <div class="parallax__group"> ... </div> </div> 

for it the CSS will look like this:

 .parallax__group { position: relative; height: 100vh; transform-style: preserve-3d; } 

In this example, I want each group to fill in the viewport, so I set height: 100vh , although, if necessary, the number for each group may be different. transform-style: preserve-3d does not allow the browser to flatten elements with parallax__layer , and position: relative allows child parallax__layer elements to be positioned relative to their group.

An important rule to remember is that when grouping elements we cannot trim content within the group, the overflow: hidden element of the parallax__group element will break the entire parallax effect. Uncircumcised content will cause child elements to go beyond. Therefore, you need to poshamanit with the group's z-index value in order to be sure that the content will be correctly hidden and displayed as the user scrolls the site.

There are no hard or fast rules about working with layers and different methods imply different implementations. But, to simplify debugging of positioning layers, you can use a simple transformation of group elements:

 .parallax__group { transform: translate3d(700px, 0, -800px) rotateY(30deg); } 

Take a look at the following example and notice the tick debug !

Watch demos with groups .

Browser support




Article - translation (original on blog.keithclark.co.uk - “Pure CSS parallax scrolling websites” )

Source: https://habr.com/ru/post/235531/


All Articles