How to create image scrolling parallax effect with CSS?

前端 未结 1 1933
猫巷女王i
猫巷女王i 2020-12-05 08:27

I saw this cool scrolling effect online...

Where the image blends with the next image when scrolling through sections. I\'ve been trying to reproduce it, bu

相关标签:
1条回答
  • 2020-12-05 08:55

    This can be done using background-attachement:fixed and two similar images.

    Here is a simple example:

    body {
      min-height:200vh;
      margin:0;
      background:url(https://picsum.photos/id/1069/150/150?grayscale) 20px 20px no-repeat;
      background-attachment:fixed;
    }
    
    .box {
      margin-top:220px;
      height:200px;
      background:url(https://picsum.photos/id/1069/150/150) 20px 20px no-repeat,
      grey;
      background-attachment:fixed;
    }
    <div class="box">
    
    </div>

    That you can easily scale with many images:

    body {
      min-height:250vh;
      margin:0;
      background:url(https://picsum.photos/id/1069/150/150?grayscale) 50px 50px/auto no-repeat;
      background-attachment:fixed;
    }
    
    .box {
      height:200px;
      background:url(https://picsum.photos/id/1069/150/150) 50px 50px/auto no-repeat,
      grey;
      background-attachment:fixed;
    }
    .box:first-child {
      margin-top:200px;
    }
    <div class="box">
    </div>
    <div class="box" style="background-image:url(https://picsum.photos/id/11/150/150);background-color:yellow">
    </div>
    <div class="box" style="background-image:url(https://picsum.photos/id/106/150/150);background-color:pink">
    </div>

    You can also consider the use of img and position:fixed but you will need some trick to hide the overflow using clip-path

    body {
      min-height: 250vh;
      margin: 0;
      padding-top: 100px;
    }
    
    img {
      position: fixed;
      top: 50px;
      left: 50px;
    }
    
    .box {
      height: 200px;
      background: grey;
      clip-path:polygon(0 0,100% 0,100% 100%,0 100%);
    }
    <div class="box">
      <img src="https://picsum.photos/id/1074/200/120?grayscale">
    </div>
    <div class="box" style="background-color:red;">
      <img src="https://picsum.photos/id/1074/200/120">
    </div>
    <div class="box" style="background-color:yellow;">
      <img  src="https://picsum.photos/id/1024/200/120?grayscale">
    </div>
    <div class="box" style="background-color:pink;">
      <img src="https://picsum.photos/id/1024/200/120">
    </div>

    Or using mask

    body {
      min-height: 250vh;
      margin: 0;
      padding-top: 100px;
    }
    
    img {
      position: fixed;
      top: 50px;
      left: 50px;
    }
    
    .box {
      height: 200px;
      background: grey;
      -webkit-mask:linear-gradient(#fff,#fff);
              mask:linear-gradient(#fff,#fff);
    }
    <div class="box">
      <img src="https://picsum.photos/id/1074/200/120?grayscale">
    </div>
    <div class="box" style="background-color:red;">
      <img src="https://picsum.photos/id/1074/200/120">
    </div>
    <div class="box" style="background-color:yellow;">
      <img  src="https://picsum.photos/id/1024/200/120?grayscale">
    </div>
    <div class="box" style="background-color:pink;">
      <img src="https://picsum.photos/id/1024/200/120">
    </div>


    For better support, here is a similar idea with some JS to avoid the use of clip-path or mask

    I will update the position of the image using a CSS variables but you can easily do without:

    window.onscroll = function() {
      var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
      document.documentElement.style.setProperty('--scroll-var', scroll+"px");
    }
    :root {
      --scroll-var: 0px;
    }
    
    body {
      min-height: 150vh;
      margin: 0;
    }
    
    img {
      position: fixed;
      top: 20px;
      left: 20px;
    }
    
    .box {
      margin-top: 220px;
      height: 200px;
      background: grey;
      position: relative;
      overflow: hidden;
    }
    
    .box img {
      top: calc(-220px + 20px + var(--scroll-var));
      /* margin of box + top of the other image + scroll*/
      position: absolute;
    }
    <img src="https://picsum.photos/id/1069/150/150?grayscale">
    <div class="box">
      <img src="https://picsum.photos/id/1069/150/150">
    </div>

    With many images:

    window.onscroll = function() {
      var scroll = window.scrollY || window.scrollTop || document.getElementsByTagName("html")[0].scrollTop;
      document.documentElement.style.setProperty('--scroll-var', scroll+"px");
    }
    :root {
      --scroll-var: 0px;
    }
    
    body {
      min-height: 250vh;
      margin: 0;
      padding-top:200px;
    }
    
    img {
      position: fixed;
      top: 50px;
      left: 50px;
    }
    
    .box {
      height: 200px;
      background: grey;
      position: relative;
      overflow: hidden;
    }
    img.f1 {
      top: calc(-200px + 50px + var(--scroll-var));
      position: absolute;
    }
    img.f2 {
      top: calc(-400px + 50px + var(--scroll-var));
      position: absolute;
    }
    img.f3 {
      top: calc(-600px + 50px + var(--scroll-var));
      position: absolute;
    }
    <img src="https://picsum.photos/id/1069/100/100?grayscale">
    <div class="box">
      <img class="f1" src="https://picsum.photos/id/1069/100/100">
    </div>
    <div class="box" style="background-color:yellow;">
      <img class="f2" src="https://picsum.photos/id/107/100/100">
    </div>
    <div class="box" style="background-color:pink;">
      <img class="f3" src="https://picsum.photos/id/1072/100/100">
    </div>

    0 讨论(0)
提交回复
热议问题