I am trying to create a nav bar that is down 500px from the top of the page, but once you scroll down to it, it becomes fixed at the top, like this
Originally I had the following code:
$(window).scroll(function() {
if ($(document).scrollTop() > 500) {
$nav.addClass('fixed');
}
else {
$nav.removeClass('fixed');
}
});
and
.fixed {
position: fixed;
top: 0;
z-index: 1;
}
However, my page is responsive and the nav bar will not always be 500px down the page. Therefore, I used .offset().top to trigger the fixed class when scrolling reaches the top of my nav bar.
$(window).scroll(function() {
var $navTop = $nav.offset().top;
if ($(document).scrollTop() > $navTop) {
$nav.addClass('fixed');
}
else {
$nav.removeClass('fixed');
}
});
The issue is that the nav bar flickers terribly when you scroll. I tried replacing .offset() with .position(), which gets rid of the flicker, but it keeps the nav bar fixed for longer than it should when scrolling back up past its original position. Please, help!
I don't see the issue on my computer (chrome & mac) but I have a likely guess.
My guess is that this is caused by something similar to layout thrashing. It is super gross to be adding / removing the class even if it isn't changing state. Since you are reading the offset from the DOM, and then setting a class / removing a class on every scroll tick (tons of times a second), this would be a likely cause of flicker.
Related
I have a main menu at the top of the website which when the user scrolls, changes and becomes more compact.
I was achieving that by checking scrolling events and whether we're at the top or not.
This is the code that was working:
/*Defines how the 'main menu' will be displayed when we scroll down (if) and how it will fallback to original look when we're up again (else)*/
$(document).ready(function(){
if ($(window).width() > 480){ //not on mobile, then:
$(window).bind('scroll', function () {
if ($(window).scrollTop() > 0) {
$('.visible-bar-container').css("position", "fixed");
$("#white-logo").css("display", "none");
//...etc
} else {
$('.visible-bar-container').css("position", "absolute");
$("#spread-out-menu").css("display", "flex");
//...etc
}
});
}
});
Mid project, the client decides that he wants the sections of the homepage to have a 'smooth scroll'. Long story short, I managed to do that after giving the whole homepage a CSS of position: absolute.
In case it matters, here is the whole CSS added to my homepage (which falls inside an element with id='main'):
#main {
position: absolute;
width: 100%;
height: 100%;
overflow: auto;
}
The problem is that now, the js code no longer works. (I believe that when the whole page has position absolute, checking for scrolling events no longer works-?). How then, can I check if the user has scrolled?
I might try checking whether user has moved past first section (through seeing if the div is visible in the viewport), but I would prefer the menu to become compact once we started moving down, not after the whole section has been moved past. So is there a way to check scrolling in this case?
I am the OP - so the answer was provided by Sim1-81 in the comments above. The trick was to change the third and fourth lines in the javascript:
...
$("#main").bind('scroll', function () {
if ($("#main").scrollTop() > 0) {
...
Where #main in my case is the id of the of page which I set to be 'position: absolute'.
So im using Adminlte with a fixed layout. The thing is I only wanted the sidebar fixed and not the header. So I removed the position: fixed from the main header.
The problem - when scrolling down there is a gap (the size of header) at the top of the sidebar.
I tried this at first :
.fixed .main-sidebar{
padding-top:0;
}
But the problem is if you don't scroll past the heading completely the sidebar jumps under it.
So now I added a function in js to calculate the position and add padding accordingly. Its kinda working but its laggy and probably a bad solution.
$(window).scroll(function () {
var positionNow = $(window).scrollTop();
if (positionNow < 50){
$('.fixed .main-sidebar').css({"padding-top" : 50 - positionNow});
} else {
$('.fixed .main-sidebar').css({"padding-top" : "0"});
$('.main-sidebar').css({"padding-top" : "0"});
}
});
Is there a better way to make the sidebar jump to top?
I realized that the gap is showing because the class main-sidebar includes the logo at top. But making the class .sidebar fixed weirdly doesn't affect sidebar-collapse.
There are two very simple way to achieve this
Remove fixed class from body(Note: It will make sidebar scrollable) or
Add css property position: absolute in main-header class
.main-header {
position: absolute !important;
}
or you can simply add "fixed" to your body on main.php
<body class="hold-transition skin-blue sidebar-mini fixed">
I've added a sticky 'call to action' bar to my site, it works like a sticky navigation, however it's stuck to the bottom of the window its original position in the page is scrolled past, then it jumps back in to the flow of the document.
It uses a CSS class '.sticky' to add the fixed position when the scroll position is less than the vertical position of the bar's original position.
The issue is, when I resize the page I get a nasty flicker and the bar more often than not disappears from view.
The code I am using is below...
(function() {
$(window).on('resize', function() {
var stickyNavTop = $('#wrap-bar').offset().top;
var stickyNav = function(){
var scrollBottom = $(window).scrollTop() + $(window).height() - $('.cta-bar').height();
if (scrollBottom < stickyNavTop) {
$('#wrap-bar').addClass('sticky');
$('#wrap-bar-dummy').show();
} else {
$('#wrap-bar').removeClass('sticky');
$('#wrap-bar-dummy').hide();
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});
$(document).ready(function() {
$(window).trigger('resize');
});
})(jQuery);
Can anyone point me in the right direction as to what I need to change to get the bar to stop flickering when resizing?
Thanks.
The flickering you're reporting is most likely because Javascript isn't rendering your DOM changes as quickly as you scroll. As mentioned by #Switching Brains, attempt using CSS to absolutely position your footer at 0px from the bottom of the window. Then, you'll only need Javascript to locate when you've reached the bottom of the page, then apply your class to hold it in a fixed position.
A realy dirty example of this, but you'll get the idea:
HTML
<div id="body">
<div id="bar">Bar at the bottom</div>
</div>
CSS
html, body {
height:100%;
widht:100%;
}
#body {
position:relative;
height:100%;
border:1px solid #000000;
}
#bar {
position:absolute;
bottom:20px;
width:300px;
left:50%;
margin-left:-150px;
background-color:#cccccc;
}
http://jsfiddle.net/Auc6n/
I found with Mozilla that .resize() caused a lot of page flickering as it was being driven too hard.
I used:
$window.resize(throttle(500,function(){
I have a div (RightSide) on the far right side of my web page that sits just underneath another div (TopBanner). The TopBanner div maintains its exact position at the top of the screen even when user scrolls down. Exactly what I want. But I also want RightSide div (underneath TopBanner) to stay exactly where it is even when user scrolls down.
I have achieved this about 80% but it behaves strangely. When you begin to scroll down, RightSide begins to move up the page until it starts being obscured by TopBanner (goes behind it), and then suddenly it pops back down to its fixed position, and stays there for the remainder of scrolling. Here's the jquery that does the "popping back down":
var stickerTop = parseInt($('#RightSide').offset().top);
$(window).scroll(function () {
$("#RightSide").css((parseInt($(window).scrollTop()) + parseInt($("#RightSide").css('margin-top')) > stickerTop) ? {
position: 'fixed',
top: '0px'
} : {
position: 'relative'
});
});
It's the initial behavior of RightSide moving up the page for a hundred pixels or so before it pops back to its correct position that is driving my boss and our users crazy. I have experimented with changing "top: '0px'" to various values, but that only makes things worse.
It seems to me that the jquery that "re-anchors" RightSide doesn't get invoked until I've scrolled a hundred pixels or so, and then suddenly it moves the div down and keeps it in the right place after that.
Summary: I never want RightSide to move up or down, even while the user is dragging the vertical scrollbar (scrolling).
How can this be achieved? (I really don't want to use an iframe for this.) Thanks.
How about packing these two divs into one with fixed position? Something like this?
<div id="StickToTop">
<div id="TopBanner">
...
</div>
...
<div id="RightSide">
...
</div>
</div>
And CSS:
#StickToTop {
position: fixed;
top: 0px;
}
#TopBanner {
float: left;
...
}
#RightSide {
float: right;
...
}
Quick preview: http://jsfiddle.net/k5xH4/3/
On my website www.staygold-design.com I have a fixed nav bar that floats above all the content.
I have a jquery cycle slide show going on in the second section (click portfolio and scroll the page right to see what I'm trying to explain) and it seems to float above the nav bar.
any thoughts?
Use z-index to change the layer precedence.
#slideshowcontainer {
z-index: 5;
}
#fixednav {
z-index: 10;
}
I've just tested in Firebug an it works. You may need to add position: relative to #slideshowcontainer for this to work in all browsers though.