Adding perspective to HTML for global Parallax - Pure CSS
Asked Answered
E

2

11

I have been following Keith Clark's guide to CSS Parallax. His concept it like so:

HTML:

<div class="container”>
  <div class="parallax-child”></div>
</div>

CSS:

.container {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: scroll;
  perspective: 1px;
  perspective-origin: 0 0;
}

.parallax-child {
  transform-origin: 0 0;
  transform: translateZ(-2px) scale(3);
}

This works perfect for the most part, for example on my development website. However I need to add this effect to another website where I can't control the HTML structure much at all, below is the basic structure tree, added comments to where I can edit.

<html>
  <body>
    <div itemscope itemtype="http://schema.org/AutoDealer">
      <div id="main-wrap">
        <div class="row">
          <div class="main twelvecol">

            <!-- Editable -->
            <div>
              <div class="row-block finance parallax__group">
                <div class="parallax__layer--back parallax__layer">
                  <p>Content in here scrolls slower than everything else</p>
                </div>
                <div class="wrapper">
                  <div class="container">
                    <div class="parallax__layer--base parallax__layer">
                      <p>This is all of the top level content</p>
                    </div>
                  </div>
                </div>
              </div>
            </div>
            <!-- END Editable -->

          </div>
        </div>
      </div>
    </div>
  </body>
</html>

I can add any styles I want, just can't edit the HTML structure apart from where stated in the comments.

My issue is I can't seem to get the parallax effect to work, if I put the example container styles for the parallax effect (at the top of this post) on the body the parallax effect works...

From what I have read I would need to add the transform-style: preserve-3d; style onto elements between the container and the children, however this doesn't appear to work.

Anyone know what's going wrong?

Edit:

Codepen of the working CSS on the body.

Codepen of the non-working CSS on the HTML.

Edit: Due to more complications with fixed positions and detecting body scroll (not possible it seems), I really need to get this working by using the HTML element.

What is strange, is that is sort of works. Follow this link and click and drag the slider left/right, the parallax effect is there, just not when you scroll down...

Not too sure why this effect doesn't work when you scroll down...

Emmuela answered 5/6, 2017 at 14:6 Comment(2)
Why are you changing it to the HTML instead of the body?Tsushima
Having it on the body stops the footer from being displayed as this is below the body.Emmuela
E
2

Guessing no one knows the answer to this, so thought I may as well post what I did.

It appears that you simply can't use the HTML tag for this Parallax effect, so I have just put the effect on a containing div, so then for things functions such as sticky headers I can simply check for the scroll amount on this div and set anything sticky to position: sticky.

Sticky doesn't work on Edge or IE so a fall back would be just to completely disable the parallax effect on these browsers and give the scrolling back to the HTML element so you can use position: fixed.

Fallback:

@supports ((perspective: 1px) and (not (-webkit-overflow-scrolling: touch)) and ((position: sticky))) {
Emmuela answered 6/6, 2017 at 10:41 Comment(2)
Do you still need help or is your problem solved with this answer?Becca
Still need help, I will update my question with more extensive examples and re-open the bounty when I get chance, been busy.Emmuela
T
0

Not sure if I quite understood your problem, but why don't you ignore the body/HTML and just map it to your own editable elements.

See working example

.body {
  perspective: 1px;
  height: 100vh !important;
  overflow-x: hidden;
  overflow-y: auto;
  preserve-origin-x: 100%;
}
.body > div { height: 200%; }
p { color: #fff; }
.parallax__group {
  position: relative;
  // transform-style: preserve-3d;
  overflow: hidden;
  height: 300px;
  margin-top: 100px;
}
.parallax__layer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.parallax__layer--base {
  transform: translateZ(0);
  position: relative;
  float: left;
}
.parallax__layer--back {
  transform: translateZ(-1px) scale(2);
  height: 100vh;
  background-image: url('https://static.pexels.com/photos/173383/pexels-photo-173383.jpeg');
  background-size: cover;
  background-position: center center;
}

.row-block {
  background: red;
}
<html>

<body>
  <div itemscope itemtype="http://schema.org/AutoDealer">
    <div id="main-wrap">
      <div class="row">
        <div class="main twelvecol">

          <!-- Editable -->
          <div class="body">
            <div>
              <div class="row-block finance parallax__group">
                <div class="parallax__layer--back parallax__layer"></div>
                <div class="wrapper">
                  <div class="container">
                    <div class="parallax__layer--base parallax__layer">
                      <p>This is all of the top level content</p>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- END Editable -->

        </div>
      </div>
    </div>
  </div>
</body>

</html>

It uses the same CSS of the version you claimed as "working". The only change I made is changing your body for a .body which is an additional div wrapper. This way, it is only touching elements you own / can edit.

Tsushima answered 10/6, 2017 at 5:24 Comment(2)
Doing that would make just the div.body scroll separately to the page, I will set up a better example tomorrow so the effect makes more sense.Emmuela
Sure thing. Happy to check the new example :)Tsushima

© 2022 - 2024 — McMap. All rights reserved.