jQuery Stick header on scroll - javascript

I have made a rediculasly small snippet to make a sub-header stick to the top.
But since , Like I said - I am by no means a js genious or jQuery genious - and actually far from it - I have my doubts about my own coding abilities..
the demo is here : http://jsfiddle.net/obmerk99/VvKq3/1/
The questions :
1 - there seems to be a lot of plugins (and a lot of questions also
in this very site) with much more code than my snippet - what am i
missing ?? What am I doing wrong ?
2 - will this work cross-browser ?
3 .. and this is a small problem, how to avoid the small "jump" that occurs ?
(if you go to the fiddle, and scroll slowly - you will see that the main div "jumps" when the script is evoked ..
I have tried to add another .pad class to the lower divs -
added class : .pad when script evoked.
.pad{padding-top:42px;}
but it does not seems to work right : http://jsfiddle.net/obmerk99/VvKq3/2/
5 .How can I calculate the real position of the div ? when I try
something like this :
var top = jQuery(window).scrollTop();
var div_top = jQuery('#header_stick').offset().top;
if (top > div_top) // height of float header;
it is jumpy ... http://jsfiddle.net/obmerk99/VvKq3/4/
6 any other suggestions are welcome..

The "jumping" occurs because the element was occupying space in the parent element, and when you change its position to fixed it's suddenly not anymore. I don't know the best way to handle it, but one option would be adding a small span (maybe with a single space) just before your #header_stick, with the same height of it, so when it's class is changed there will still be something there to account for the height difference. (Update: your pad solution is probably the best one, once done right; see below)
Your padding solution might also work, provided that: 1) you remember to remove that class when the user scrolls to the top (in your fiddle I see you adding it, but don't see you removing it); 2) You get the height right - I still couldn't look closely to your code, so I don't know where you got wrong. (Edit: the problem was that your .pad class was using the height of the floating header, not the stick header - fixing that and removing the class yielded what I believe to be the correct result)
About the real position of the div, have you tried subtracting the div's offset from the offset of the parent element? This way you'll have its position relative to the parent (pay attention to things like borders, though - I've recently answered another question where details like this mattered).
Update: your problem here seems to be that, when the position is changed to fixed, the offset also varies wildly. I'd suggest calculating the correct height, once, then storing it somewhere so the scroll function can use it. In other words, don't calculate it while scrolling, that makes it much more difficult to find the right theshold to do the class switch.
Other than that, I think you're code is fine, and I believe it will work cross browsers too (at least standards compliant ones; can't say anything about old versions of IE). Very insightful too, I always wondered how this "trick" worked, now I see it's simpler than I imagined...

You can try this way. I made a shorter version for easier analysis.
fiddle here
<div id="ontop">floating heading</div>
<header>sticky heading</header>
<div id="wrapper">
1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>10<br/>
</div>
#ontop {width:100%; height:80px; background-color:yellow;}
header {width:100%; height:20px; background-color:lightgrey; }
#wrapper {background-color:lightblue; height:5000px;}
.navfixed {position: fixed; top: 0px; z-index: 100; width:100%; display:block; margin-bottom:120px; }
.wrapperBelow{margin-top:22px;}
$(function () {
var elem = $('header'),
wrapperElem = $('#wrapper'),
elemTop = elem.offset().top;
$(window).scroll(function () {
elem.toggleClass('navfixed', $(window).scrollTop() > elemTop);
wrapperElem.toggleClass('wrapperBelow', $(window).scrollTop() > elemTop);
}).scroll();
});

Related

Coudn't scroll to end of the page using window.scrollTo

I am not able to scroll all the way until end. Following code stop working near the end of page.
I have used following methods to scroll programmatically,
// 1 still see scrolling left
window.scrollTo(x,y) > window.scrollTo(window.scrollWidth,0)
window.scrollBy(x,y) >
// 2
scrollingElement.scrollLeft = scrollingElement.scrollWidth - document.documentElement.clientWidth;
Info:
Some width related info for my case,
window.scrollWidth > 6180
scrollingElement.scrollWidth > 6183
document.documentElement.clientWidth > 412
Note: I have used webkitColumnGap css and turned vertical page into horizontal. That's why I have bigger scrollWidth.
If I use following (full scroll) I still see, there is some scrolling left and I can use mouse to scroll that part,
window.scrollTo(window.scrollWidth,0) // go to end
scrollingElement.scrollLeft = <full width> // go to end
// log scroll position for inpection ~ this number does not match the full width
window.scrollX ~ 4k
(window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0) ~ 4k
I have run out of ideas so would need help from you guys to find out the issue.
Browser details:
I am using flutter Webview in android device.
Edit:
After lot of trial and error adding following css fixed the issue, I don't why this fixed it?
body {
overflow: hidden !important;
}
Thanks.
You want to scroll to the bottom?
Try this:
var height = document.body.scrollHeight
window.scroll(0, height)
Hope i understood your question correctly
After lot of trial and error adding following css fixed the issue, I don't why this fixed it?
body {
overflow: hidden !important;
}
This means that some of your children elements bled out of its parent container. overflow: hidden tells the browser to cut out the parts that are not fitting inside the body container. That also means that this issue can be solved by changing the size or positioning of the body's children, and that would probably be a better approach to fixing the issue.
By default, overflow is set to visible, and therefore the browser allows you to see (and to scroll) outside of the containing box (overflow property explained)
The !important part tells the browser to artificially increase the specificity of this rule. For more details on specificity: css-tricks/sprecificity

make div (position:fixed) scroll horizontally

I know this topic has been posted quite often already, but none of the solutions presented have been of any help to me by far. I have a sidebar on the left side of my page, which I assigned position:fixed in CSS, and which I would like to scroll horizontally (along with all the other content on my page)
For my header and footer I solved the issue like this:
$(window).scroll(function ()
{
$("header,footer").css('margin-left', -($(window).scrollLeft()) + "px");
});
But this doesn't do it properly for my sidebar.
This is the html for my sidebar:
<div class="fullscreen_block hided">
<div class="left-sidebar-block">
and CSS:
.left-sidebar-block {
position: fixed;
margin-left: 70px;
}
Can anybody show me how I can fix this without using the above JS code? (any other JS or CSS or jQuery is fine)
Thanks!!
First off, I think you want to use scrollTop instead of scrollLeft. From your description, it sounds like you want to have an element slide to the left as the user scrolls down. scrollTop will give you the distance the user has scrolled.
Second, I recommend using the transform property instead of the margin property, as long as it meets your browser support requirements. Scrolling tricks are often performance intensive so you should try to use high performance css properties like transform and opacity rather than slower properties like margin, left, and display.
The following code does what I think you are trying to do. (Codepen demo: http://codepen.io/regdoug/pen/yyYvaV):
$(window).scroll(function ()
{
var top = $(window).scrollTop();
$("left-sidebar-block").css('transform', 'translateX(' + (-top) + "px)")
.css('-ms-transform', 'translateX(' + (-top) + "px)")
.css('-webkit-transform', 'translateX(' + (-top) + "px)");
});
References
http://www.html5rocks.com/en/tutorials/speed/scrolling/
http://css-tricks.com/almanac/properties/t/transform/
http://caniuse.com/#feat=transforms2d
Your problem is not really clear.. but I think you shoukd better play with the "left" attribute rather than "margin-left". Margins won't have any effect on a fixed element..

vertically center page around a form

I know vertical center in CSS is a pain to begin with, but I've just made it a bit more complicated. On my page, I have:
<ul id="complete">
</ul>
<form id="new_item_form">
<input type="text" id="add_item" placeholder="Type some tasks here"/>
</form>
<ul id="incomplete">
</ul>
It's for a basic task list. Tasks are added to the incomplete ul, and when completed move to the complete ul. What I want to do via css is have the text field vertically centered on the page and stay there, with the two lists butted up against it. I've been looking at all sorts of vertical alignment (a summary of forms found here: http://blog.themeforest.net/tutorials/vertical-centering-with-css/ ) but I can't seem to find a way that I can figure out how to adapt to allow what I need. How would I accomplish this style of fixed position centering?
EDIT:
Here's an image of what I'm looking for: https://www.dropbox.com/s/i0oit3v84j93b5g/Screen%20Shot%202012-10-11%20at%204.27.16%20PM.png
Is this what you want to obtain?
Of course, my code is a bit sketchy (use of height attribute on tds! Don't scold me to much). But you get the point.
If the height of the table is not known nor fix, but its parent height is known, it won't work (see this example) and you'll have to break it down.
If you just don't know any height at all, it's kind of hard to align...
Further reading on vertical-align
I can't think of any way to do this with CSS, but it's fairly easy to do with JavaScript/jQuery. Here is a working jsFiddle that does what you want on document load. You'd call the code again if you changed the lists, of course.
First, you enclose your lists and form in a div. I called this id="cmiddle". Then you use CSS to set the cmiddle div as position: relative. Then you use JavaScript code to get the enclosing window or frame height, calculate the center for the form, and then, subtract the upper list height to get the correct div position:
$(document).ready(function(e) {
// To work with frames, too
function getParentDocHeight($ele) {
for (;;) {
if (!$ele || !$ele.length) {
return $(window).height();
}
$ele = $ele.parent();
if ($ele.is("frame") || $ele.is("window")) {
return $ele.height();
}
}
}
var $cm = $("#cmiddle");
var formHeight = $("#new_item_form").outerHeight();
var viewHeight = getParentDocHeight($cm)
var formTop = (viewHeight - formHeight) / 2;
var divTop = formTop - $("#complete").outerHeight();
$cm.css("top", divTop);
});
Edit: Kraz was nice enough to add a simulation of adding list items to both lists and calling the code again to recalc. His jsFiddle here.
Well, I'm not sure what you are talking about
But generally,
put the line-height = the div's height. I will create a div around it if necessary
if some very particular situations, i do some math to manually center it
So if you want to centering 1 thing, create a div go around it with line-height = the div's height
And then make the div position: absolute, width, height, ....
Hope this helps

Chrome Extension Scrollbar Placement

After dabbling in Chrome Extensions I've noticed that when the data inside the Page Action gets to a certain point the scroll bars automatically attach themselves to the popup, this I expect. However, instead of pushing the content to the left of the scroll bar it overlays the content causing a horizontal scrollbar to become active. I ended up just adding a check on my data and applying a css class to push the content to the left more to run parallel to the scroll bar and beside it not under it. What is the correct way to handle this besides my hackish solution?
I was wondering this myself too. Currently I just don't put anything important closer than 20px to the right side of a popup and disable horizontal scrollbars:
body {overflow-x:hidden;overflow-y:auto;}
So when a vertical scrollbar appears the content at least doesn't jump.
Perhaps you need to specify a width on the scrollbar.
::-webkit-scrollbar {
width: 42px; //Do not know actual width, but I assume you do
}
I haven't found a way to do this that isn't a hack, but here's the simplest hack I could think of:
<script type="text/javascript">
function tweakWidthForScrollbar() {
var db = document.body;
var scrollBarWidth = db.scrollHeight > db.clientHeight ?
db.clientWidth - db.offsetWidth : 0;
db.style.paddingRight = scrollBarWidth + "px";
}
</script>
...
<body onresize="tweakWidthForScrollbar()">
The idea is to detect whether the vertical scrollbar is in use, and if it is, calculate its width and allocate just enough extra padding for it.

Adjusting elements based on scrollHeight using JQuery

Here's what i have so far:
function loadOff(){
$(document).ready(function(){
$("#eLoader").ajaxStop(function(){
$(this).hide();
$("#eventsContent").show();
var h = document.body.scrollHeight;
$("#bodyBackground").css("height",h+100+"px");
$("#sidePanel1").css("height",h-105+100+"px");
$("#bottom").css("top",h+100+"px");
});
});
}
This is a callback function for a JQuery ajax function, basically what is does is when all ajax is finished .ajaxStop() it hides the loader then shows the content.
The problem i am having is adjusting bodyBackground, sidePanel, and bottom to fit the content. I dont care to have it elastic and retract for short content at this point, i would just like it to extend to proper positioning based on content length.
All divs are absolutely positioned. The numbers in the function are broken down simply to make it easy to explain. -105 is the offsetTop of that element and +100 is the margin between the end of the content and the elements.
if there is a better, more efficient way to achieve this outcome, please, do tell.
Thanks.
Based on your code, the only thing you ought to see is the top 105px of #sidePanel1. Is that your intent? (h = the bottom of the window, according to your code.)
Sticking with the JQuery patterns, you would use
var h = $(window).height();
Maybe you're looking for this instead of the browser window's height? It will get the height of the content element.
$("#eventsContent").outerHeight();

Categories