Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
ursbraem opened this issue Jan 20, 2015 · 10 comments
Closed

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

ursbraem opened this issue Jan 20, 2015 · 10 comments

Comments

@ursbraem
Copy link

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
Copy link
Owner

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
Copy link
Author

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
Copy link
Owner

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.

janpaepke added a commit that referenced this issue Jan 21, 2015
When using `bottom` or `right` to position absolutely positioned
elements the positions were off.
Fixed by copying the size to the spacer.
More info here:
#226 (comment)
7
@ursbraem
Copy link
Author

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
Copy link
Owner

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
Copy link
Author

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

@ursbraem
Copy link
Author

"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
Copy link
Author

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.

  • if the element, when relatively positioned, is outside the viewport, don't do anything.
    What I don't want is that the absolutely positioned element is laid over any of the prior content, as in your example and more visible in http://jsfiddle.net/ursbraem/jfxz4u7o/2/
  • if the (relatively positioned) element would appear inside the viewport, set its position to absolute in the way you did it, affixing it to the bottom
  • On scroll, the green box should scroll up with the content regularly.

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

@janpaepke
Copy link
Owner

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
Copy link
Author

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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants