CSS: "overflow: hidden" alternative that doesn't break 3D transforms
Asked Answered
H

2

10

I'm trying to make a horizontal section with a parallax effect. In the background there should be an image that scrolls at a different speed than the page.

The problem is: I want the parallax element to be contained in the parent element, so the parent element works kind of like a mask for the child: the child is only visible within the boundries of the parent.

I know that this can be achieved by having the parallax element beetween two elements with backgrounds that are "above" the parallax element and obstruct it, but this method is not applicable for my case.

The obvious idea that comes to mind is to use overflow: hidden on the parent. This however breaks the 3D transforms so there is no parallax left.

How do I achieve the described effect?

Here is a codepen: https://codepen.io/rradarr/full/mdwgard. I want the red rectangle to not be visible outside the "parallax-container" with the black border.

* {
      margin: 0;
    }
    
    html, body {
      height: 100%
    }
    
    main {
      position: relative;
      width: 100%;
      
      perspective: 1px;
      transform-style: preserve-3d;
      overflow-y: auto;
      overflow-x: hidden;
      height: 100vh;
      
      background-color: blue;
    }
    
    .static {
      min-height: 800px;
    }
    
    .parallax-container {
      border: solid black 3px;
      height: 600px;
      width: 100%;
      transform-style: preserve-3d;
      position: relative;
    }
    
    .parallax-child {
      position: relative;
      width: 100%;
      height: 100%;
      transform: translateZ(-2px) scale(2.01);
      z-index: -1;
    }
    
    #img-or-whatever {
      height: 900px;
      width: 100%;
      background-color: red;
      position: relative;
      z-index: -1;
    }
<main>
      <div class="static"></div>
        
      <div class="parallax-container">
        <div class="parallax-child">
          <div id="img-or-whatever"></div>
        </div>
      </div>
    
      <div class="static"></div>
    </main>
Hildehildebrand answered 10/10, 2021 at 18:55 Comment(0)
V
2

As far as I know you can't achieve the described effect with translateZ. This is because according to this article about CSS 3D

...giving overflow any value other than visible effectively forces the value of transform-style to flat, even when we have explicitly set it to preserve-3d.

The only alternative for overflow hidden is to put something "above" the parallax element as far as I know (which you said you want to avoid).

If there is really no option to put something "above" the parallax element you could try to do something similar with js (something like this for example). This is not ideal since it will imply a lot of calculations and variables and might take some time to accomplish exactly what you want (and you loose the 3D inside the container since you need overflow: hidden anyway).

If you really need the 3d inside there you could create a more complex solution with javascript that skips overflow: hidden as well. But I'd try to avoid that if is not mandatory (I'd rather add an absolute element over the overflow: hidden container where 3D is enabled. And give the absolute container transparent background if you still need 3D in that section).

Usually I would also advise to try to avoid .js for this kind of stuff (if possible) but I don't think you have a lot of options here.

Vinnievinnitsa answered 21/10, 2021 at 14:44 Comment(0)
H
0

You could try the :not() pseudo clss, but I don't know what you would pass into the parentheses that would be similar to not in the black square.

Hanafee answered 23/10, 2021 at 23:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.