I want to stick the div to the top of its parent element.
It generally works, except in this example: http://jsfiddle.net/HV9HM/2859/
function sticky_relocate() { var window_top = $('#container').scrollTop(); var div_top = $('#sticky-anchor').offset().top; if (window_top > div_top) { $('#sticky').addClass('stick'); $('.stick').css('width', $('#sticky').next().css('width')); } else { $('#sticky').removeClass('stick'); } } $(function () { $('#container').scroll(sticky_relocate); sticky_relocate(); });
.child { height: 200px; background: gray; } #sticky { padding: 0.5ex; width: 600px; background-color: #333; color: #fff; font-size: 2em; border-radius: 0.5ex; } #sticky.stick { position: fixed; z-index: 10000; border-radius: 0 0 0.5em 0.5em; } body { margin: 1em; } p { margin: 1em auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <br> <br> <br> <div id="container" style="overflow-y: auto; height: 800px;"> <div id="sticky-anchor"></div> <div id="sticky">This will stay at top of page</div> <div class="child"></div> <div class="child"></div> <div class="child"></div> <div class="child"></div> </div>
The problem is that if you scroll the div that is called container
to the bottom, the div will be scrolled to the top (it's a bug).
If you add another child to div:
<div class="child"></div>
It works..
You can see the working fiddle here: http://jsfiddle.net/HV9HM/2860/
function sticky_relocate() { var window_top = $('#container').scrollTop(); var div_top = $('#sticky-anchor').offset().top; if (window_top > div_top) { $('#sticky').addClass('stick'); $('.stick').css('width', $('#sticky').next().css('width')); } else { $('#sticky').removeClass('stick'); } } $(function () { $('#container').scroll(sticky_relocate); sticky_relocate(); });
.child { height: 200px; background: gray; } #sticky { padding: 0.5ex; width: 600px; background-color: #333; color: #fff; font-size: 2em; border-radius: 0.5ex; } #sticky.stick { position: fixed; z-index: 10000; border-radius: 0 0 0.5em 0.5em; } body { margin: 1em; } p { margin: 1em auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <br><br><br> <div id="container" style="overflow-y: auto; height: 800px;"> <div id="sticky-anchor"></div> <div id="sticky">This will stay at top of page</div> <div class="child"></div> <div class="child"></div> <div class="child"></div> <div class="child"></div> <div class="child"></div> </div>
(The difference is that the first fiddle has one less child with class child
).
Any help appreciated!
Method 1: Using the sticky value of the position property It can be given a value of '0px' to make the element leave no space from the top of the viewport, or increased further to leave space from the top of the viewport.
To freeze the row/column we can use a simple HTML table and CSS. HTML: In HTML we can define the header row by <th> tag or we can use <td> tag also. Below example is using the <th> tag. We also put the table in DIV element to see the horizontal and vertical scrollbar by setting the overflow property of the DIV element.
Use position:fixed; and set the top:0;left:0;right:0;height:100px; and you should be able to have it "stick" to the top of the page.
The reason this is happening is that as soon as you give position: fixed
to your #sticky
element, it takes it out of the document flow. This means that all of your div.child
elements shift up, which makes the height of your container element get smaller. Because the container element height gets smaller, the container element no longer needs to scroll, which means its scrollbar disappears and its scroll position is reset to 0. When its scroll position is reset to 0, the script again removes the stick
class from your #sticky
element and we are back where we started, but with the container element scrolled all the way to the top.
In summary:
#sticky
element gets .stick
class.
#sticky
element is removed from document flow, child elements shift up, container element height decreases and scrollbar disappears. Container's scrollTop
is reset to 0.
Script fires again, removing the .stick
class from #sticky
, and the container's scrollTop
remains at 0 (thus the container div is scrolled back up to the top).
Below is a solution that uses position: absolute
for the #sticky
element, and when the #sticky
element gets the stick
class, it gives the #sticky-anchor
element a height equal to the height of the #sticky
element to prevent the child divs from shifting upwards.
Working Live Demo:
function sticky_relocate() { var window_top = $('#container').scrollTop(); var div_top = $('#sticky-anchor').offset().top; $('.stick').css('width', $('#sticky').next().css('width')); if (window_top > div_top) { $('#sticky-anchor').height($("#sticky").outerHeight()); $('#sticky').addClass('stick'); $("#sticky").css("top", (window_top) + "px"); } else { $('#sticky').removeClass('stick'); $('#sticky-anchor').height(0); } } $(function () { $('#container').scroll(sticky_relocate); sticky_relocate(); });
.child { height: 200px; background: gray; } #sticky { padding: 0.5ex; background-color: #333; color: #fff; font-size: 2em; border-radius: 0.5ex; } #sticky.stick { position: absolute; top: 0; z-index: 10000; border-radius: 0 0 0.5em 0.5em; } body { margin: 1em; } p { margin: 1em auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <br> <br> <br> <div id="container" style="overflow-y: auto; height: 800px; position: relative;"> <div id="sticky-anchor"></div> <div id="sticky">This will stay at top of page</div> <div class="child"></div> <div class="child"></div> <div class="child"></div> <div class="child"></div> </div>
JSFiddle Version: http://jsfiddle.net/HV9HM/2883/
As a side note, the reason it was working fine in your second example is that the additional child element made it so that even when your #sticky
element was removed from document flow and the container element's height was reduced, the height of the container element was still large enough to keep the scrollbar from jumping/disappearing and changing/resetting your scrollTop
.
Although the best answer to this particular question is clearly @MaximillianLaumeister's, here is a general solution for fixing an element to another element.
Tether is a JavaScript library for efficiently making an absolutely positioned element stay next to another element on the page.
Tether includes the ability to constrain the element within the viewport, its scroll parent, any other element on the page, or a fixed bounding box.
http://github.hubspot.com/tether/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With