bigspotteddog / ScrollToFixed

This plugin is used to fix elements on the page (top, bottom, anywhere); however, it still allows the element to continue to move left or right with the horizontal scroll.
http://bigspotteddog.github.com/ScrollToFixed/
MIT License
1.81k stars 532 forks source link

Sidebar not stopping at footer properly?... #65

Open lukeetheridge opened 11 years ago

lukeetheridge commented 11 years ago

Hi guys,

First off, great plugin!

I think this should be a relatively quick fix for you but basically I'm having issues on this page:

http://hotspot.prouddesigns.com/research/dsr-score/

I'm scrolling the #sidebar with your plugin but there is currently some strange activity when the sidebar gets to the place I'd like it to stop (#footer-widgets-bg). If you make you're browser small enough so that you can scroll past the navy footer you'll see what I mean.

Could you let me know the fix for this? I basically would like the bottom of the #sidebar to stop 30px or so from the top of the #footer-widgets-bg div (fairly standard request).

Here is the code I've been using...

I'd appreciate a quick reply as I'm currently getting back to my client on this, so thank in advance.

Thanks, Luke

lukeetheridge commented 11 years ago

I would also like to only serve this plugin for screens of 960px width and above. If you could tell me how this is done aswell that would be great :)

bigspotteddog commented 11 years ago

There are a couple of issues:

  1. To get the sidebar to unfix and move up the page when the footer hits it, set the limit like this:

    $('.page-template-template-dsr-php #sidebar').scrollToFixed({ marginTop: $('#header').outerHeight(), limit: $('#footer-widgets-bg').offset().top - $('.page-template-template-dsr-php #sidebar').outerHeight(true) - 30 });

  2. The layout is using a float:right to move main to the other side of the sidebar. This is not where it is as dictated by the order of the markup. As a result, the sidebar is jumping out of the layout when it goes absolute to travel up the page. Try putting the sidebar before main in the markup.

Hope that helps.

bigspotteddog commented 11 years ago

For your second question, add this to the options:

minWidth: 960

Looks like I left that out of the documentation. Oops!

lukeetheridge commented 11 years ago

You da man! (well sort of)...

I've done everything above and the only thing that's not working is the sidebar popping out when I reach the #footer-widgets-bg div and I've moved it to before the #main div.

Any thoughts on that one?

lukeetheridge commented 11 years ago

..Ideally it doesn't want to be going back to 'absolute' positioning because it wasn't absolutely positioned in the first place (if that makes sense).

bigspotteddog commented 11 years ago

The plugin sets the target element to absolute to give the impression that the element is now scrolling up the page from where the limit kicks in. If it jumped back to where it was in the layout, without absolutely scrolling from there, there would be a big jump visually, if the target did not disappear completely because it would now be scrolled complete out of view.

The style of some other container element is causing a left and top to be applied. I will look at it more closely.

lukeetheridge commented 11 years ago

I understand and thanks for you're help so far and I understand you can't spend all day tending to my issues but my only stylesheets are...

http://hotspot.prouddesigns.com/wp-content/themes/canvas-child/style.css http://hotspot.prouddesigns.com/wp-content/themes/canvas-child/css/layout.css (for responsive shiz)

I can't see any reason that #sidebar would not display correctly when absolutely positioned.

bigspotteddog commented 11 years ago

I am closer by moving the #main-sidebar-container before the #content container. Of course, this messes up the other styling, but the jump no longer occurs and it fixes and limits as expected. I also removed position: relative from its style, but I don't know if that helped or not yet. Almost there, I think :)

lukeetheridge commented 11 years ago

Nice one!

But isn't #main-sidebar-container inside the #content container?...

bigspotteddog commented 11 years ago

Sorry, I meant #sidebar :)

lukeetheridge commented 11 years ago

Ah I see.

the only issue with that is that the site is responsive so that would push the sidebar up to above the content when viewing on devices of less width than 768px.

Although I suppose I could effectively repeat two sidebars and serve the different ones in different positions for each width variant...

bigspotteddog commented 11 years ago

Yeah, moving it out of the #content container is not the ideal solution. Just trying to see what is causing the jump.

lukeetheridge commented 11 years ago

Ok thanks for all this time bud!

bigspotteddog commented 11 years ago

This is a tough one so far. Sorry, I have not come up with the solution to the jump yet.

It appears that, although the layout and css are simple, something is causing the plugin to see an offset left and top. I usually recommend getting rid of as many containers as possible for the target element when this happens.

I will keep looking and thinking about this as I have time today. Again, sorry I was not able to come up with a quick solution.

lukeetheridge commented 11 years ago

I understand bud.

Also, I'm assuming that the layout/css is fairly simple enough so there's not a lot I can do in that respect?

I'll delay showing the client for the time-being so that we can get it sorted. Thanks again for your time and I look forward to the solution.

bigspotteddog commented 11 years ago

While the layout is simple without javascript, it becomes very complex with all of the dynamic movement, with javascript, which is throwing off the static values with which the plugin is initialized. For example, the header and the hellobar move around (resize) quite a bit as the window is scrolled. When the plugin is initialized, it is done with the initial position and size of these "header" elements, but those change once the window is scrolled, but the plugin was only given the initial values (statically).

Still looking at what can be done with this, but that is what is happening.

bigspotteddog commented 11 years ago

OK, here is the solution:

I added an option to the plugin to removeOffsets. This will reduce the top and left by their initial offset values, respectively. This will compensate for whatever is happening to move the containers around on the page. Download the latest version of the plugin.

Change your initialization code for the plugin to this:

$(document).ready(function() {
    $('.page-template-template-dsr-php #sidebar').scrollToFixed({
        marginTop: function() {
            return $('#header').outerHeight(true) + 10;
        },
        limit: function() {
            return (
                $('#footer-widgets-bg').offset().top -
                $('.page-template-template-dsr-php #sidebar').outerHeight(true) -
                30
            );
        },
        minWidth: 769,
        zIndex: -1,
        removeOffsets: true
    });
});

Here is an explanation of the code changes above:

As far as the "resizing" headers go, you will want to call

$(window).resize()

to get the plugin to reinitialize its offsets once the headers are done moving around.

Good luck with your project.

lukeetheridge commented 11 years ago

Thanks for all of this info man, I really appreciate it!

It doesn't seem to have fixed though? - http://hotspot.prouddesigns.com/research/dsr-score/

I even tried moving the sidebar out of #main and #main-sidebar-container with no luck...

bigspotteddog commented 11 years ago

To see it in action, go here:

http://23.23.186.156/hotspot.prouddesigns.com/

bigspotteddog commented 11 years ago

When running on a server, it does not appear that the bit about "$(window).resize()" is necessary. I was testing it from disk before and Chrome needed it.

bigspotteddog commented 11 years ago

I just looked at your link, you do not have the latest version of the plugin.

lukeetheridge commented 11 years ago

It's working!!

I had to change the 'zIndex: -1' to equals 1 because the links in the sidebar weren't working. It still displays below the scrolling header though because that header had a z-index of 999.

Is that all cool?

You've been great at sorting this out for me and I really appreciate your time you've spent on this.

bigspotteddog commented 11 years ago

Yup, that's all cool. You can make it any number that is less than the header.

Best of luck!

van-knowmad commented 11 years ago

This seems to be working for me, too. I had an ad at the bottom of an absolutely positioned sidebar, which itself was inside a relatively positioned main section. (As another programmer once told me, "Where there's not logic, there's history.")

I had to add hacks to the callback function to get the scroll element to look right once it hit the lower limit. Here are the options I used:

$fixed_ad.scrollToFixed({
    marginTop: 10,
    limit: limit_element_top - ad_height + limit_element_height,
    removeOffsets: true,
    preAbsolute: function() {
        jQuery( this ).css('padding', '400px 0 0 10px');
    },
    postAbsolute: function() {
        jQuery( this ).css('padding', '0');
    }

Not elegant, but the 400px top padding accounts for the site's header and the non-scrolling content above the element in the sidebar.

I'd love better, less brittle solutions, but I can live with this.

bigspotteddog commented 11 years ago

Thanks for sharing. I like, "Where there's not logic, there's history." :) That removeOffsets option only removes the left offset. Looks like you had to remove the top as well. Unfortunately, I have not had the time to look into detecting when an element will jump out of its container when it goes absolute. This quick removeOffsets "Just do this, don't ask why" solution has no logic to it at all :( Hopefully, I will understand it at some point and get rid of the "historical" importance of this information :)

jibograf commented 10 years ago

Hi, I have a similar problem. I tried to follow the various explanations through this post and others but it doesn't work the way I want... And I'm not very comfortable with javascript. In addition, it doesn't work the same way on Firefox and Chrome for example.

Here is my function:

$('#sidebar-activites').scrollToFixed({ 
        marginTop: 90,
        zIndex: 50,
        dontSetWidth: true,
        limit: $('.footer').offset().top - $('#sidebar-activites').height()
    });

And here is the link to the page on which is the bar: http://josso-palettes.com/wordpress/activites/

Something is wrong with my function? Any suggestion? Thank you!

bigspotteddog commented 10 years ago

@jibograf The limit attribute in the scrollToFixed call should be a function as it appears the footer offset is changing due to dynamically loaded elements. Making the limit a function will cause the footer offset to be recalculated every time it is needed rather than only on document.ready. Also, the sidebar needs to have a z-index lower than the header so it goes under it rather than over it. Other than that, it looked fine for me in Chrome.

jibograf commented 10 years ago

@bigspotteddog Oh my god, you're my Lord! It works, indeed! :+1: Thank you again, sincerely.