Jeffrey Y.
Jeffrey Y.

Reputation: 107

How to implement continuous parallax like this?

I've been playing around with HTML, CSS, and jQuery, and I can't figure out how to implement the parallax functionality on this website: http://quinntonharris.strikingly.com/

Each slide manages to seamlessly "cover up" the previous slide while being able to be covered up by the following slide, while all managing to relatively move at the same speed.

I've tried doing this in CSS alone by just creating different layers, but then the slides don't move at the same speed. I've also looked at examples like on this: https://keithclark.co.uk/articles/pure-css-parallax-websites/demo3/ but they don't simulate the same effect.

What's the essential concept in emulating this effect using vanilla CSS or with jQuery/some other JS library?

Upvotes: 1

Views: 91

Answers (1)

Gershom Maes
Gershom Maes

Reputation: 8170

We'll scroll a series of overflow: hidden divs (call these "parallaxParents"). Scrolls will cause the children ("parallaxChildren") of these "parallaxParents" to animate in the inverse direction of the scroll.

This technique looks especially great when parallaxParents take up the full size of their scrolling viewport.

let initialChildMarginTop = -125; // parallaxChild's margin-top

let scroller = document.getElementsByClassName('scroller')[0];
let doParallax = () => {
  
  // An Array of all parallaxParents
  let pars = Array.from(scroller.getElementsByClassName('parallaxParent'));
  
  // The height of a parallaxParent
  let parHeight = pars[0].getBoundingClientRect().height;
  pars.forEach((par, ind) => {
    
    // Get the parallaxChild...
    let child = par.getElementsByClassName('parallaxChild')[0];
    
    // Represents how close `par` is to the center of the scroller viewport
    // 0 means centered; < 0 is above, > 0 is below
    let focusedAmt = (ind * parHeight) - scroller.scrollTop;
    
    // Shift each child by a fraction of `focusedAmt`
    // Children exactly in the middle of the viewport will be unchanged
    child.style.marginTop = `${initialChildMarginTop - Math.round(focusedAmt * 0.5)}px`;
    
  });
  
};

// May need to add the event listener in more places
scroller.addEventListener('scroll', doParallax);
window.addEventListener('resize', doParallax);

// Make sure everything is initially translated correctly
doParallax();
html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  padding: 0;
}

.scroller {
  width: 100%; height: 100%;
  overflow-x: hidden;
  overflow-y: scroll;
  font-size: 0;
}
.parallaxParent {
  position: relative;
  overflow: hidden;
  width: 100%; height: 100%;
}
.parallaxParent:nth-child(2n) { background-color: rgba(100, 100, 0, 0.2); }
.parallaxParent:nth-child(2n + 1) { background-color: rgba(0, 0, 100, 0.2); }
.parallaxChild {
  position: absolute;
  width: 250px; height: 250px;
  left: 50%; top: 50%; margin-left: -125px; margin-top: -125px;
  transform: rotate(45deg);
  background-color: rgba(0, 150, 100, 0.4);
}
<div class="scroller">
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>https://stackoverflow.com/questions/54775562/how-to-implement-continuous-parallax-like-this#
  <div class="parallaxParent">
    <div class="parallaxChild"></div>
  </div>
</div>

Upvotes: 1

Related Questions