How to achieve parallax effect with grandchildren

Viewed 174

I've achieved the parallaxing background effect a few times before on codepen's and small, experimental projects.

This is my favorite tutorial on it - https://keithclark.co.uk/articles/pure-css-parallax-websites/

Here's the markup from the referenced tutorial:

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

And the vital CSS bits:

.parallax {
  ...
  perspective: 1px;
}
.parallax__layer--base {
  transform: translateZ(0);
}
.parallax__layer--back {
  transform: translateZ(-1px);
}

Basically - The .parallax element has a perspective, which essentially means it can view things in 3d space.

The .parallax__layer--base(which is the foreground layer) is placed at 0 on the z-axis. So it hasn't moved from it's origin.

The .parallax__layer--back (the background layer) is placed one pixel back on the z axis.

So now, when you scroll through the .parallax element, you can see these background and foreground layers moving in a 3d space, which gives the parallax effect.

But it only works if you are scrolling through the .parallax element - What about on a full-sized, robust page?

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

The css and markup haven't changed. But now I'm scrolling through the .home element, and not the .parallax element. The foreground and background layers are still in a 3d space, but it's only relative to the .perspective element.

Is there a way to somehow pass that perspective down to the homepages grandchildren, or great grandchildren? Or do I need to divide my entire page into foreground and background sections in order to achieve this effect?

1 Answers

I came up with a "hacky" way of achieving this with JavaScript.

Here's a rundown of the steps (you may call it the algorithm):

  • listen for the window scroll event
  • wait until the parallax container (parent of what you defined as base and back) is in view
  • in my case, I fixed back and changed top value of base over a transition duration.

Here's my implementation (specific to my use case):

/**
 * hacky parallax effect
 */
const viewportHeight =
  'innerHeight' in window
    ? window.innerHeight
    : document.documentElement.offsetHeight

const headerHeight = document.querySelector('header').offsetHeight

window.onscroll = () => {
  const preFooterPosition = document
    .querySelector('.pre-footer')
    .getBoundingClientRect()

  /** start parallax when pre-footer is in view */
  if (
    preFooterPosition.top <= headerHeight &&
    preFooterPosition.bottom >= viewportHeight
  ) {
    // parallax
    document.querySelector('.content').classList.add('transform-content')
  } else {
    // reverse parallax
    document
      .querySelector('.content')
      .classList.remove('transform-content')
  }
}
.content {
  display: flex;
  flex-direction: column;
  flex: 1;
  z-index: 1;
  position: relative;
  top: 0;
  transition: top 1s ease;
}

.transform-content {
  top: -5rem;
}

.watermark {
  position: absolute;
  z-index: 0;
  flex: 1;
  display: flex;
}
<template>
  <section class="pre-footer">
    <div class="wrapper">
      <div class="watermark">
        <SVGIcon class="watermark-left" icon="LearnLongShort" />
        <SVGIcon class="watermark-right" icon="FreeEducation" />
      </div>
      <div class="content">
        <div class="content-left content-wrapper">
          <div>
            <h3 class="title">Evidence base</h3>
            <div class="body">
              <p>The Academy of Medical Cannabis Evidence Base is an advanced referencing tool for CBMP research. Containing the history of research to date and all emerging findings, this cutting-edge engine underpins our learning content.</p>
            </div>
            <WhiteButton text="View database" />
          </div>
        </div>
        <div class="content-right content-wrapper">
          <div>
            <h3 class="title">White Papers</h3>
            <div class="body">
              <p>Alongside our learning platform, The Academy publishes a series of authoritative papers discussing the core topics and themes related to CBMPs. Register to view and download the archive.</p>
            </div>
            <WhiteButton text="Archive" />
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

I hope that helps. Let me know when you come up with a better solution. In the meantime, I'm pushing this.

Cheers!

Related