37
头图

This article will introduce a small trick to achieve scrolling parallax effect with CSS, and use this trick to make some interesting interactive effects.

Regarding the use of CSS to achieve scrolling parallax effect, there is a previous article that describes the specific scheme in detail - CSS to achieve parallax effect . Interested students can read this article first.

Here, such a pure CSS parallax trick will be used:

Use transform: translate3d for scrolling parallax

CSS 3D is used here to achieve scrolling parallax effect.

The principle is:

  1. We set the container transform-style: preserve-3d and perspective: xpx , then the child elements in this container will be located in 3D space,
  2. Then set a different transform: translateZ() for the child elements. At this time, the distance between different elements in the 3D Z-axis direction from the screen (our eyes) is also different.
  3. Scrolling the scroll bar, because the child elements are set to different transform: translateZ() , then the upper and lower distance of their scrolling translateY relative to the screen (our eyes), is also different, which achieves scrolling Parallax effect.
About transform-style: preserve-3d and perspective This article will not be expanded in many pages, the default readers have some understanding, it is not particularly clear, you can first understand CSS 3D.

The core code representation is:

 <div class="g-container">
    <div class="section-one">translateZ(-1)</div>
    <div class="section-two">translateZ(-2)</div>
    <div class="section-three">translateZ(-3)</div>
</div>
 html {
    height: 100%;
    overflow: hidden;
}

body {
    perspective: 1px;
    transform-style: preserve-3d;
    height: 100%;
    overflow-y: scroll;
    overflow-x: hidden;
}

.g-container {
    height: 150%;

    .section-one {
        transform: translateZ(-1px);
    }
    .section-two {
        transform: translateZ(-2px);
    }
    .section-three {
        transform: translateZ(-3px);
    }
}

The summary is that the parent element settings transform-style: preserve-3d and perspective: 1px , and the child element settings are different transform: translateZ , scrolling the scroll bar, the effect is as follows:

css3dparallax

CodePen Demo -- CSS 3D parallax

Obviously, when the scroll bar is scrolled, the degree of displacement of different sub-elements is visually different, and the so-called scroll parallax effect is achieved.

Cool interactive animations with CSS parallax

OK, with the above foreshadowing, let's take a look at these two interesting interactive effects. Provided by the Japanese server in the group, all Tuzi wheatup.

Let's take a look at the first effect:

The effect is that the text is displayed alternately in layers of different heights, and during the scrolling process, there will be an obvious 3D parallax effect.

This effect is not difficult, the core is:

  1. Using transform-style: preserve-3d and perspective to construct different layered effects and make parallax effects
  2. Using the elements ::before , ::after to build a 3D effect

Let's look at a minimized DEMO:

 <div class="g-container">
    <div class="g-box"></div>
    <div class="g-box"></div>
    <div class="g-box"></div>
</div>
 .g-container {
    height: 150vh;
    perspective: 600px;
}

.g-box {
    width: 200px;
    height: 200px;
    background: #999;
    transform-style: preserve-3d;

    &::before,
    &::after {
        content: "";
        position: absolute;
        right: 0;
        left: 0;
        transform-style: preserve-3d;
        height: 200px;
        background-color: #ccc;
    }
    &::before {
        transform-origin: top center;
        top: 0;
        transform: rotateX(-90deg);
    }
    &::after {
        transform-origin: bottom center;
        bottom: 0;
        transform: rotateX(90deg);
    }
}

Scroll g-container container to get a 3D effect:

Since the parallax effect is also needed, we need to give different layers translateZ() , we slightly modify the code, give each g-box in the middle, and add another layer of normal div , then add a translateZ() to each g-box ec156eb9dbbf809df4803146466a2b17---.

 <div class="g-container">
    <div class="g-box"></div>
    <div class="g-normal"></div>
    <div class="g-box"></div>
    <div class="g-normal"></div>
    <div class="g-box"></div>
</div>
 .g-container {
    width: 400px;
    height: 150vh;
    perspective: 800px;
}

.g-normal {
    width: 200px;
    height: 200px;
    background: #666;
    transform-style: preserve-3d;
}

.g-box {
    width: 200px;
    height: 200px;
    background: #999;
    transform-style: preserve-3d;
    transform: translate3d(0, 0, 200px);

    &::before,
    &::after {
        // ... 保持不变
    }
}
  1. Since the translateZ values of g-box and g-normal are different, a parallax effect will appear during scrolling
  2. Since g-box a translateZ value translateZ(200px) , two dummy elements rotateX plus or minus 90deg , and height 200px , so g-box and g-normal just by g-box two dummy elements link up

In the end, the effect is as shown above:

Full code for DEMO: CodePen Demo - 3D Parallax Scroll

CSS scroll parallax animation 2

OK, the second scrolling parallax animation below is also very interesting. I want to see the original version, which is also from CodePen of wheatup:

CodePen Demo -- 3D Chat Viewer

The core here still relies on the ability of CSS 3D, but because of the scroll-triggered animation effect, and there is a certain fade-in effect from blurred to clear, there is still a certain amount of JavaScript code.

If you are interested, you can take a look at the above source code.

This article will try to restore the JavaScript part of the effect using CSS @Property and the latest CSS feature @scroll-timeline.

Of course, the core 3D part uses CSS in the first place, with or without JavaScript.

We first need a structure like this:

 <div class="g-wrapper">
    <div class="g-inner">
        <div class="g-item"></div>
        <div class="g-item"></div>
        // ... 重复 N 个
    </div>
</div>
 .g-wrapper {
    width: 100vw;
    height: 100vh;
}
.g-inner {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 10px;
}
.g-item {
    width: 300px;
    height: 100px;
    background: #000;
}

Probably this effect:

Then, we add some CSS 3D transforms:

 .g-wrapper {
    // ... 与上述代码保持一致
    perspective: 200px;
    transform-style: preserve-3d;
}
.g-inner {
    // ... 与上述代码保持一致
    transform-style: preserve-3d;
    transform: translateY(calc(-50% + 100px)) translateZ(0) rotateX(90deg);
    transform-origin: bottom center;
}

You can get the effect of such a perspective:

Since the container g-inner performs a 90deg flip around the X axis, that is rotateX(90deg) , so we give g-item a reverse rotation, return:

 .g-wrapper {
    // ... 与上述代码保持一致
    perspective: 200px;
    transform-style: preserve-3d;
}
.g-inner {
    // ... 与上述代码保持一致
    transform-style: preserve-3d;
    transform: translateY(calc(-50% + 100px)) translateZ(0) rotateX(90deg);
    transform-origin: bottom center;
}
.g-item {
    // ... 与上述代码保持一致
    transform: rotateX(-90deg);
}

You can get the effect of such a perspective:

At this point, we give the container an animation that assigns a translateZ:

 .g-inner {
    animation: move 10s infinite linear;
}
@keyframes move {
    100% {
        transform: translateY(calc(-50% + 100px)) translateZ(calc(100vh + 120px)) rotateX(90deg);
    }
}

In this way, the prototype of the entire animation is completed. By controlling the size of the parent element perspective and the translateZ of the container, an animation effect that continuously moves in front of the viewing angle is obtained:

CodePen Demo -- CSS 3D Effect Demo

Combined with CSS @scroll-timeline, use CSS to control scrolling and animation

So how to use CSS to combine this animation and scrolling operation?

Not long ago, I introduced a major feature of CSS . It is finally here. The animation killer @scroll-timeline can be used to combine CSS animation and scrolling operations. Let’s use it to transform the code:

 <div class="g-scroll" id="g-scroll"></div>
<div class="g-wrapper">
    <div class="g-inner">
        <div class="g-item">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
        // ... 重复 N 个
    </div>
</div>
 @property --phase {
  syntax: '<length>';
  inherits: false;
  initial-value: 15px;
}
.g-scroll {
    width: 100%;
    height: 1000vh;
}
.g-wrapper {
    position: fixed;
    width: 100vw;
    height: 100vh;
    perspective: 200px;
    transform-style: preserve-3d;
}
.g-inner {
    position: relative;
    height: 100%;
    // 省略一些 flex 布局代码,与上文一致
    transform-style: preserve-3d;
    transform: translateY(calc(-50% + 100px)) translateZ(var(--phase)) rotateX(90deg);
    transform-origin: bottom center;
    animation-name: move;
    animation-duration: 1s;
    animation-timeline: box-move;
}
.g-item {
    width: 300px;
    height: 200px;
    color: #fff;
    background: #000;
    transform: rotateX(-90deg);
}
@scroll-timeline box-move {
    source: selector("#g-scroll");
    orientation: "vertical";
}
@keyframes move {
    0% {
        --phase: 0;
    }
    100% {
        --phase: calc(100vh + 100px);
    }
}

Compared with the above DEMO, we mainly add the code of @scroll-timeline , we add a super long container .g-scroll , and use its scroll action @scroll-timeline box-move {} rule It is bound to animation-timeline: box-move so that we can use scrolling to trigger @keyframes move {} CSS animation.

The effect is as follows:

In the original effect, there are some fuzzy changes using JavaScript combined with scroll distance control. This, we use backdrop-filter: blur() can also be easily simulated. We simply add another layer g-mask :

 <div class="g-scroll" id="g-scroll"></div>
<div class="g-wrapper">
    <div class="g-mask"></div>
    <div class="g-inner">
        <div class="g-item">Lorem ipsum dolor sit amet consectetur adipisicing elit.</div>
        // ... 重复 N 个
    </div>
</div>
 // 其他保持一致
.g-mask {
    position: fixed;
    width: 100vw;
    height: 100vh;
    backdrop-filter: blur(5px);
    transform: translateZ(0);
}

In this way, the original effect is basically restored, and we use and only use CSS:

CodePen Demo -- Pure CSS Scroll Animation 2 (Chrome Only && Support ScrollTimeline)

in conclusion

Of course, in the latter effect of this article, a lot of CSS properties that are currently very poorly compatible are used, especially @scroll-timeline, which is still in a very early stage, and the compatibility is red. But it does not prevent us from learning and feeling the beauty of CSS.

To fully understand this article, there may be some prerequisite knowledge that you need to understand. You can extend the reading as needed:

Well, this is the end of this article, I hope it helps you :)

If you want to get the most interesting CSS information, don't miss my official account -- iCSS front-end anecdotes 😄

More wonderful CSS technical articles are summarized in my Github -- iCSS , which will be updated continuously. Welcome to click star to subscribe to the collection.

If you have any questions or suggestions, you can communicate more. Original articles are limited in writing and knowledge. If there are any inaccuracies in the article, please let me know.


chokcoco
12.2k 声望18.5k 粉丝