My question is how can I overlap a div over a fixed div on scroll without using a background image.
I want the bottom of the div to match the bottom of the screen to fix that div and make the content (the other divs) below to scroll up (like a parallax effect). Same with if the fixed div is bigger than the screen, as in bigger height (so position sticky won't work).
Here is what I've got so far. I checked if the user scrolled to the div, that I want the scroll effect at and fixed at the bottom. When I'm at that point the content acts like the fixed div doesn't exist and skips it abruptly instead of scrolling in from below. The effect works though when I scroll back up it just skips the fixed div.
I'm trying to achieve something like this:
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_parallax_percent
But without a background image.
.background-beige {
width: 100%;
background-color: #f8f8f8;
padding-bottom: 200px !important;
}
.contact-banner-wrapper {
height: 436px;
background-color: #c22a40;
position: relative;
}
$(window).scroll(function (e) {
var el = $(".contact-banner-wrapper");
var elem = $(".background-beige");
if (
$(window).scrollTop() >=
elem.offset().top + elem.outerHeight() - window.innerHeight
) {
elem.css({ position: "fixed", bottom: "0px"});
}
if ($(this).scrollTop() < 200) {
elem.css({ position: "static"});
console.log("reset");
}
});
Do you have improvements or any other solutions?
I did a work around, to my problem and now it works as intended. position: fixed; takes the div out of the flow of the DOM so it gets ignored and skipped by the other divs. I just gave the content (the other divs that scroll from below over the fixed div a top margin of the height of the fixed div to work around the position: fixed; change.
$(window).scroll(function (e) {
var scrollOverContent = $(".contact-banner-wrapper");
var fixedDiv = $(".contact-banner-wrapper").prev();
var heightFixedDiv = fixedDiv.outerHeight();
if (
$(window).scrollTop() >=
fixedDiv.offset().top + fixedDiv.outerHeight() - window.innerHeight
) {
fixedDiv.css({ position: "fixed", bottom: "0px", zIndex: "0" });
scrollOverContent.css("margin-top", heightFixedDiv);
}
if (
$(window).scrollTop() <
scrollOverContent.offset().top - $(window).height()
) {
fixedDiv.css({ position: "static" });
scrollOverContent.css({ marginTop: "0" });
}
});
Related
I have a webpage with a fixed y scrollable sidenav and a main body. When I scroll with my mouse scrollwheel, pointer inside the side nav, sometimes the body will scroll depending on where the element is positioned. Technically the margin of the main body is still overlapping with the side nav due to bootstrap offset like offset-md-3.
How can I stop the main body from scrolling while the mouse is on the sidenav? I need the solution without using any plugins. jQuery and Bootstrap 4 only please.
My initial instinct was like this, but changing to fixed caused the main body to snap back to the top.
I disabled scrolling on hover over the .SideNav, but I needed to keep the scrollbar for continuity.
$(".SideNav").hover(function () {
$('body').css({
"position": 'fixed',
"overflow-y": 'scroll'
});
},
function () {
$('body').css({
position: 'inherit',
"overflow-y": 'scroll'
});
});
Initially using fixed was causing the body to snap back to scrolling from the top of the page. I had to compensate like so.
var offset;
$(".SideNav").hover(function () {
offset = window.pageYOffset // Get offset to set position when fixed
$("main").css("position", "fixed");
$('body').css({
"position": 'fixed',
"overflow-y": 'scroll',
"top": 0 - offset
});
},
function () {
$("main").css("position", "inherit");
$('body').css({
"position": 'inherit',
"overflow-y": 'scroll'
});
$(window).scrollTop(offset); // When scroll bar returns, set page to original position
});
I found it to be an interesting situation and reading your answer I was wondering why you needed to also change the position and top properties although it very well may be necessary to accommodate to your specific html and css structure.
Any way, I thought I could include a different approach in a simpler/minimal scenario. Let me know what you think:
var currentOverflow;
$(".SideNav").hover(()=> {
currentOverflow = $('body').css('overflow');
$('body').css({
overflow: 'hidden'
})
},
() => {
$('body').css({
overflow: currentOverflow
})
});
.SideNav{
position: fixed;
height: 100vh;
width: 20vw;
background: red;
top: 0;
left: 0
}
span{
margin-left: 30vw
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="SideNav" id="fixed"></div>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
<br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span><br><span>a</span>
I have a header on a website that is fixed 20px from the top of the page.
However, I want this to catch the top of the page when scrolling and become fixed to the top of the screen once the user has scrolled that 20px down.
CSS
#header{
padding: 0px 0px 0px 0px;
background: url(../images/header-fill2.jpg) repeat-x top;
position: fixed;
height: 60px;
width: 100%;
top: 20px;
z-index: 5000;
}
I imagine some form of JavaScript is required but have little to no JavaScript experience, so any help would be greatly appreciated.
Just listen for the scroll event and read the value of $(window).scrollTop() and set the top according to that.
Something like:
$(window).on('scroll', function() {
$('#header').css('top', $(window).scrollTop() > 20 ? '0px' : '20px');
});
Example on jsFiddle
The scroll event tells you when the window scrolls. Then, use the scrollTop to find out how much closer to 0 to go:
$(window).on("scroll", function() {
$("#header").css("top", Math.max(0, 20 - $(window).scrollTop()));
});
Live Example
Or to avoid constantly re-creating objects:
(function() {
var $wnd = $(window),
$header = $("#header");
$wnd.on("scroll", function() {
$header.css("top", Math.max(0, 20 - $wnd.scrollTop()));
});
})();
Live Example
Thats how I do that with jQuery.
The position is also cached, for performance reasons:
Here is a fiddle:
http://jsfiddle.net/StephanWagner/u3yrS/
$(document).ready(function() {
var cfixed_nav = false, wscroll;
var setScroll = function() {
wscroll = $(window).scrollTop();
var fixed_nav = wscroll > 20; // Set pixel amount here
if (fixed_nav != cfixed_nav) {
$('body')[fixed_nav ? 'addClass' : 'removeClass']('fixed');
cfixed_nav = fixed_nav;
}
};
setScroll();
$(document).scroll(setScroll);
});
With CSS you set the fixed position:
.fixed #header {
position: fixed;
top: 0;
left: 0;
right: 0;
width: 100%
}
Also remember, that when the header gets the fixed position, those 20px of the header are missing. So you can add a body padding for example:
.fixed {
padding-top: 20px;
}
Or you add an element with 20 Pixel height and swap display none / block depending on the .fixed class in the body
I have a "sticky" sidebar contact form with jQuery, which turns to fixed-positioned div when page is scrolled down. My problem is that it overlaps the footer when scrolled down all the way. Is there a way where I could set it not to scroll down any further once its bottom margin starts hitting the footer? I'm not sure how I would detect that event, if at all possible, because it's a responsive site and footer's height varies.
CSS:
.sticky {
margin-top: 38px;
max-width: 300px;
padding-top: 20px;
z-index: 0;
}
jQuery:
jQuery(function(){ // document ready
if (!!jQuery('.sticky').offset()) { // make sure ".sticky" element exists
var stickyTop = jQuery('.sticky').offset().top; // returns number
jQuery(window).scroll(function(){ // scroll event
var windowTop = jQuery(window).scrollTop(); // returns number
if (stickyTop < windowTop){
jQuery('.sticky').css({ position: 'fixed', top: 0 });
}
else {
jQuery('.sticky').css('position','static');
}
});
}
Thanks all in advance.
I'm trying to create a basic sticky header.
The header contains 2 parts: top and main. When page is scrolled down, i want to keep only the .main sticky (so that the .top becomes invisible).
I'm trying following code, but it is jerky and if the content has a specific height, it does not let scroll, starts jumping. I have captured video to illustrate the problem. Please see:
http://www.screenr.com/Z89H
Here's the demo:
http://jsfiddle.net/M33g4/
(you might not see the issue because of different screen height, in that case drag the results window to set its height about 535px).
HTML:
<header>
<div class="top"></div>
<div class="main"></div>
</header>
<section>
</section>
jQuery:
$(window).scroll(function () {
var height = $('header').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
I'm sure you will have fixed this by now but after encountering the same issue I came up with a solution:
The issue was caused by the document size not having enough leeway beneath the fold to fit the height of the overall header. This meant that if a visitor tried to scroll down, the sticky part of the header will become fixed, but immediately unfix itself.I believe it may be the bounce-back effect that causes the problem but I haven't tested to verify this.
In short, I fixed it by adding simple check to ensure that there is more than enough space beneath the fold by comparing the height of the body and the height of the window. i.e body height minus window height must be greater than the total header height. Here's the code that worked in my instance:
// Sticky sub navbar
var sub_nav_height = $('#sub-nav').outerHeight();
var total_height = $('#main-head').outerHeight();
var header_height = total_height - sub_nav_height;
var content_height;
var y;
$(window).scroll(function() {
// Only make sticky if window is large enough not to cause jumping issue
content_height = $('body').height() - $(window).height();
if(content_height > total_height) {
y = $(this).scrollTop();
if($(this).scrollTop() > header_height) {
$('#sub-nav').addClass('fixed');
} else {
$('#sub-nav').removeClass('fixed');
}
}
});
There are two caveats which I decided were absolutely fine for my scenario. The first is that an extra calculation has been added every time the scroll event is triggered, but this hasn't caused me any performance issues. The second is that the sticky header functionality is simply disabled when a vistor's window is a problematic size, but again I had no qualms with this as the navbar could still just about be seen.
Check this
http://jsfiddle.net/M33g4/3/
JS
$(window).scroll(function () {
var height = $('.top').height();
if($(this).scrollTop() > height){
$('.top').hide();
$('header').addClass('sticky');
}else{
$('.top').show();
$('header').removeClass('sticky');
}
});
CSS
*{
margin: 0;
padding: 0;
}
header{
width: 100%;
}
.top{
height: 50px;
background: blue;
}
.main{
height: 70px;
background: green;
}
section{
height: 560px;
background: yellow;
}
.sticky{
position: fixed;
width: 100%;
}
You should target to the top but not to whole header demo
$(window).scroll(function () {
var height = $('header .top').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
http://jsfiddle.net/M33g4/1/
$(window).scroll(function () {
var height = $('.top').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
guess you got the wrong height.
Updated:
The blinking issue is caused by height changing (due to position: fixed)
check this one: http://jsfiddle.net/M33g4/6/
$(window).scroll(function () {
var height = $('.top').outerHeight();
if($(this).scrollTop() > height){
if($('.main.sticky').length == 0) {
$('header').append(
$('.main').clone().addClass('sticky'));
}
}else{
$('.main.sticky').remove();
}
});
and stick .main only:
.sticky{
position: fixed;
width: 100%;
top: 0;
}
This works for me:
Set the height variable to 30:
$(window).scroll(function () {
var height = 30;
if($(this).scrollTop() >= height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
and change the css for the sticky class to the following:
.sticky{
position: fixed;
width: 100%;
top: -30px;
left: 0;
}
Top is -30 instead of -40. Works for me!
Check how the content in this demo snaps to the top, under the header, but not visible. You might want to resize the Results window to about 500px. Is there a solution to this please?
$(window).scroll(function () {
var height = $('.top').outerHeight();
if($(this).scrollTop() > height){
$('header').addClass('sticky');
}else{
$('header').removeClass('sticky');
}
});
I am using following code to make a menu sticky when the window is scrolled down. It works fine if the window height is enough to scroll down the full header area, but it it creates problem is the height is just close enough to scroll, in that case it starts flashing and does not let scroll.
Here is the demo of the problem, refresh couple of times and try to scroll down. I have set the body height to 622px to reproduce the problem:
http://jsbin.com/ipEROYO/1
Here's the code I'm trying:
$(document).ready(function() {
var stickyNavTop = $('.nav').offset().top;
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('.nav').addClass('sticky');
} else {
$('.nav').removeClass('sticky');
}
};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});
CSS:
.sticky {
position: fixed;
width: 100%;
left: 0;
top: 0;
z-index: 100;
border-top: 0;
}
It's because when you are setting the navigation div to position:fixed you are shortening the length of the document (by the height of that div), which then causes the scroll bar to go away, which causes the scrollTop() value to be 0 which causes the .nav div to be position:static and it is an endless cycle if you keep scrolling down.
Here's my quick solution:
$(document).ready(function() {
var height = $('.nav').outerHeight();
$(window).scroll(function() {
if($(this).scrollTop() > height)
{
$('.nav').css('position','fixed');
$('body').css('padding-bottom',height+'px');
}
else if($(this).scrollTop() <= height)
{
$('.nav').css('position','static');
$('body').css('padding-bottom','0');
}
});
$(window).scroll();
});
Just modified the JSbin. Check it out. You were really close, just doing more than you needed to like setting the sticky class on load of the page rather than when the function first runs. Let me know if this helps.
try that
$(window).scroll(function () {
var scroll_top = $(this).scrollTop();
if (scroll_top > 66) {//height of header
$('.nav').addClass('sticky');
} else {
$('.nav').removeClass('sticky');
}
});
Strongly recommend a CSS only solution for this layout. No one seems to know what to call this method, so I've been referring to it as the absolute stretch technique, but in my experience it works beautifully across mobile devices and PC's including all major browsers except IE6 and below. There is some discussion of it here.
body, .header, .nav, .mainContent{
position: absolute;
top: 0;
left: 0;
right: 0;
}
body, .mainContent {
bottom: 0;
}
.header{
height: 120px;
}
.nav{
height: 70px;
top: 120px;
}
.mainContent{
top: 190px;
overflow: auto;
}
You'll find you can get very robust, concise, well organized layouts in this manner, and fixed headers, footers and sidebars follow very easily.