janpaepke / ScrollMagic

The javascript library for magical scroll interactions.
http://ScrollMagic.io
Other
14.89k stars 2.17k forks source link

Start with a pinned element in a "fixed" position #226

Closed ursbraem closed 9 years ago

ursbraem commented 9 years ago

Hi Jan

Is it possible to start with an element pinned to the bottom of the viewport (n pixels above the bottom), IF there is enough space for it? So it would start like a position:fixed element, but when the scrolling begins, it would scroll normally?

Sorry for the lazy question, I guess after a few hours with another scroll plugin it's more tired than lazy anyway... I've looked through a few issues here and I couldn't find the answer yet.

By the way, the visual debug information is awesome!

Cheers Urs

janpaepke commented 9 years ago

Hi Urs, If an element scrolls normally "when the scrolling begins" it can't be a pinned element. That's contradictory. Why don't u just absolutely position the element x px from the bottom? Like so: http://jsfiddle.net/mbuod494/

Out of curiosity: Which plugin did you use before and why were you dissatisfied with it?

ursbraem commented 9 years ago

Waypoints. I just don't get its logic.

I'll look into your proposition with positioning it absolutely - i've tried fixed, but then I had huge jumps when changing to position:relative when scrolling. Probably absolute is better. 

If you'd like to see what I mean: neu.ofosu.ch - the yellow part at the bottom should peek out only a few pixels (one yellow line) at the beginning, but scroll up and down normally later on.

I also thought about measuring the screen height and pushing down the object the required distance, keeping it relative. Which would probably not need scrollmagic anymore then.

By the way, is it possible and would it make sense to use scrollmagic without GSAP, just to detect the scroll position  in a comfortable way? Which would lead us back to waypoints, which I failed to understand...

janpaepke commented 9 years ago

Positioning it absolutely was meant as an alternative to pinning/fixing it at all. That is due to the fact that you said it should scroll "normally, when the scrolling begins".

Now you changed that definition by saying it should peek out for a while and then scroll up later on. That is indeed an example for a pin. Pushing it down is not a valid solution, because only fixed elements are positioned relative to viewport without any jitters.

If you want the element to be pinned right from the start and then unpin after some time, just create a scene with the duration you want your element to be pinned for and start it right from the start. Like this: http://jsfiddle.net/mbuod494/2/

As to your second question: Currently there is no way to use ScrollMagic without GSAP, as it is deeply connected to its core. This however changes in ScrollMagic 2.0, which is currently in alpha stadium. It will probably released some time next month.

Best regards from Lausanne to Bern, J

PS.: When making the above example I stumbled over a problem with bottom positioned elements that are pinned. The height isn't transferred to the spacer and thus the positioning is off. I will fix this bug for 2.0 as well... In the meantime the example contains a valid workaround.

ursbraem commented 9 years ago

Hi Jan

thanks so much for your help! The thing is that I want the container to be bigger than displayed.

Now I've made a very barebones positioning thing, #carpet being the #element.

function setCarpet(){
    var _rowwidth = $("#mainrow").width();
    var _viewportHeight = $(window).height();
    var _carpetOffset = _viewportHeight - 16;
    $('#carpet').css({
      "width": _rowwidth,
      "height": _rowwidth,
      "position": "absolute"
    }).offset({top: _carpetOffset});
    $('#carpet-wrapper').css({
       "height": _rowwidth+500
    });
}

This is called on page load and on resize. I admit it's not that elegant. Actually, I think I could add a ScrollMagic scene on top of that positioning to have the #carpet element scroll by itself first until it bumps into the content, couldn't I? But I hesitate, thinking about reducing dependencies. So I'll probably just leave it barebones as is.

That said, I think I've found the perfect scrolling effects library! And I'll look into the v2 for sure.

Cheers Urs

janpaepke commented 9 years ago

Hi Urs, I have said it lots of time before and will probably say it lots of time again:

Do not position elements using javascript!

It is (sadly) a very common practice to sort of brute force elements to be positioned somewhere on the page using javascript. Yet this is EXACTLY what css was made for. People seem to go for it because it seems to be a quick fix and it friggin does what it's supposed to. In my experience though it will very often lead to other problems along the way. Not to speak of performance drawbacks. In 99% percent of the cases I came across it can be done in pure CSS and it will be easier maintainable, more performant and cross browser compatible.

I'm not sure what you mean by "the container to be bigger than displayed". But if you mean it should extend below the viewport that's no problem at all, see here: http://jsfiddle.net/mbuod494/3/ If that's not what you mean, please clarify.

If you create a js fiddle of your example (working with your script above) I can show you how to do it in pure css.

ursbraem commented 9 years ago

Ok, I'll try again! Let you know.

ursbraem commented 9 years ago

"the container to be bigger than displayed"

Ah, maybe I can word this better: in your fiddle, I want the green box to be pinned to the bottom ONLY IF the rest of the content ABOVE the green box is smaller than the viewport and leaves some space before the green box. Else, no pinning is intended to happen whatsoever. What do you think?

On the academic part: without looking at the code, I thought that GSAP and Scrollmagic were also using JS to position / transform elements, so I thought I'd be more economic doing it with a few lines of ugly jQuery.

ursbraem commented 9 years ago

I've been thinking: I guess a "pin" is not what I mean at all. I think by pin, you mean "not scroll with the page". What I was looking for was position:fixed or position:absolute.

Do I need ScrollMagic for this at all? If so, great! I'm just not sure

janpaepke commented 9 years ago

Hi Urs,

I've been thinking: I guess a "pin" is not what I mean at all. I think by pin, you mean "not scroll with the page". What I was looking for was position:fixed or position:absolute.

position:fixed means by definition "not scroll with the page". position:absolute means it does scroll with the page but is taken out of flow, it doesn't influence following elements. By definition to 'pin' elements or make them 'sticky' means to take them out of the scroll flow (set to position:fixed) for a set amount of time. That is why I said your question is "contradictory" in my very first answer.

On the academic part: without looking at the code, I thought that GSAP and Scrollmagic were also using JS to position / transform elements, so I thought I'd be more economic doing it with a few lines of ugly jQuery.

That is beside the point. They are both javascript plugins that put a lot of experience, know-how and time into making these modifications as small and optimized as possible. This whole issue is actually a perfect example why you should always try to find a DOM/CSS solution for things like this first. It's not about being a code-snob and being disgusted by "ugly jQuery". It's about best practice and learning. The more you try to do things with DOM and CSS the more you will learn the benefits and find easier ways of achieving your desired outcome.

The issue at hand I think I understand you now: You basically just want your element to be outside of the initial viewport? In that case you are correct - you don't need ScrollMagic, as that is just a very basic DOM setup and CSS... Simply create an element that contains the initial content and has the minimum height of the viewport. All following elements will be pushed down accordingly and will scroll into view the way they are expected to: http://jsfiddle.net/jfxz4u7o/4/

If you want the following content to "peak" in, either set them to like 90% height or use negative margins to offset them by fixed pixel values.

ursbraem commented 9 years ago

You basically just want your element to be outside of the initial viewport

That's what I meant!!! And thank you so much for your examples. I got it working now. Three days and a so many detours to finish with a few lines of css.

It's about best practice and learning

Absolutely. I'm doing CSS for 10 yrs now and I'm still on the surface

Thanks again!