2

EDIT: SOLVED

Here's the working code (checking for perspective support, and if it exists creating CSS parallax and listening for scrolling within div for the effect, otherwise it defaults to listening for window.scroll):

html,body {height: 100%; width: 100%;}
#nav {
    display:block;
    background:#d9ffff;
    position:fixed;
    z-index:10000;  
    width:100%;
    height:100px;
    padding-top:0px;
    transition: all 0.6s;
}
.prllx_group {
    position: relative;
    height: 100vh;
}
div {height:400px}
#one {background:#d9d9ff}
#two {background:#d9ffd9}
#three {background:#ffd9d9} 

@supports (perspective: 1px) {  

    body, html {
        overflow: hidden;
        height: 100%;
        width: 100%;
    }
    body {
        -webkit-transform: translateZ(0px);
        transform: translateZ(0px);
    }

    .prllx {
        position:relative;
        height: 45em;
        height: 100vh;
        overflow-x: hidden;
        overflow-y: auto;
        -webkit-perspective: 300px;
        perspective: 300px;
        perspective-origin-x: 100%;
    }
    .prllx_group {
        position:relative;
        -webkit-transform-style: preserve-3d;
        transform-style: preserve-3d;
    }
 }

HTML:

<nav id="nav">
    <ul class="menu">
        <li><a href="#one">ONE</a></li>
        <li><a href="#two">TWO</a></li>
        <li><a href="#three">THREE</a></li>
    </ul>
</nav>

<div id="parallax" class="prllx">

    <div></div>
    <div id="one" class="prllx_group">...</div>
    <div id="two" class="prllx_group">...</div>
    <div id="three" class="prllx_group">...</div>
    <div></div>
 </div>

JS:

    var container = window;
    var scrolledDiv = document.body;
    var hello = 1;

    if( typeof CSS !== "undefined" &&
    typeof CSS.supports !== "undefined" &&
    !CSS.supports("-webkit-overflow-scrolling", "touch") &&
    CSS.supports("perspective", "1px")) {
        var container = document.getElementById('parallax');
        var scrolledDiv = document.getElementById('parallax');
    };

    container.onscroll = function isTheTop() {
    var headerElement = document.getElementById('nav');
    var headerHeight = headerElement.offsetHeight;
    if (scrolledDiv.scrollTop > 80 || document.documentElement.scrollTop > headerHeight) {
        headerElement.style.background='rgba(29,29,29,0.9)'; 
        headerElement.style.paddingTop='0';
        headerElement.style.boxShadow='0 0 0.6em #1d1d1d';

    } else {
        headerElement.style.background='rgba(0,0,0,0)'; 
        headerElement.style.paddingTop='20px';
        headerElement.style.boxShadow='0';
    }
};

I also made sure the script is running after the HTML code, at the end of the page or deferred, then it works.

Thanks!


original question:

I can't get the following script to listen for scrolling within a div, rather than window scrolling. If I try to use a CSS parallax effect (i.e. all content is inside a div, which stays still relative to body, and all content scrolls within the div.)

Here's my CSS

SAME CSS AS ABOVE

Here's my HTML:

SAME HTML AS ABOVE

And here's the JS (which works if I override the @supports –with a !, for example– so it defaults to an unenhanced content):

function isTheTop() {
    var headerElement = document.getElementById('nav');
    var headerHeight = headerElement.offsetHeight;
    if (document.body.scrollTop > 80 || document.documentElement.scrollTop > headerHeight) {
        headerElement.style.background='rgba(29,29,29,0.9)'; 
        headerElement.style.paddingTop='0';
        headerElement.style.boxShadow='0 0 0.6em #1d1d1d';

    } else {
        headerElement.style.background='rgba(0,0,0,0)'; 
        headerElement.style.paddingTop='20px';
        headerElement.style.boxShadow='0';
    }
};
window.onscroll = function() {isTheTop()};

I tried listening for parallax.onscroll (instead of window.onscroll) but the effect does not work.

Laonikoss
  • 45
  • 1
  • 8
  • Please add a working code snippet so we can see how it looks and figure the best way to help. – Ason Mar 07 '16 at 14:08
  • You can use the ` Element.getBoundingClientRect()` .. This gives you an object with x,y,width,height. Beware that some browsers use top,left instead of x,y. – Daniel Mar 07 '16 at 14:34

1 Answers1

1

As stated here https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onscroll you should be able, if you don't want to trigger onscroll event handler if document is being scrolled, but just this element, to do this:

var scrolledDiv = document.getElementById("myScrollingDiv");
scrolledDiv.onscroll = function(){.....};

Alternatively, if this above doesn't work (I have no time to recreate your case and test it right now), you could do something like this:

window.onscroll = function() {isTheTop()};

function isTheTop() {
    if(scrolledDiv.scrollTop > 80) // rest of your code...
}
Bozidar Sikanjic
  • 667
  • 4
  • 12
  • Thanks for your answer! I updated the code to include HTML and CSS for a working example. I tried `var scrolledDiv = document.getElementById("parallax"); scrolledDiv.onscroll = function(){.....};` And I got this error in console: `Uncaught TypeError: Cannot set property 'onscroll' of null`. – Laonikoss Mar 08 '16 at 14:06
  • 1
    @Laonikoss make sure your script comes _after_ the elements you intend to manipulate. [See this answer](http://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element/8716680#8716680) – canon Mar 08 '16 at 14:08
  • Sorry, my mistake - fixed the parsing error, but the effect still doesn't work. I updated the original question to reflect the changes. – Laonikoss Mar 08 '16 at 14:18