Fixed Header when the Div above is scrolled past - javascript

I have this setup so that when the page is scrolled 400px the #headermenu becomes fixed. However the div above this one will have a variable height depending on the screen size.
I need the JS to make the #headermenu become fixed when the bottom of the div above it(#mixedheightheader) has reached the top of the window.
JSFIDDLE
Thanks in advance for you help
<div id="mixedheightheader"></div>
$(function() {    
$('#headermenu');
});
$(window).scroll(function() {    
if ($(document).scrollTop() < 400)     {        
if ($('#headermenu'))         {            
$('#headermenu');            
$('#headermenu').stop().css({
top: '0',
position: 'relative'
});        
}    
}    
else     {        
if ($('#headermenu'))         {            
$('#headermenu');            
$('#headermenu').stop().css({
top: '0',
position: 'fixed'
});        
}      
}
});
body {
height: 3000px
}
#headermenu {
width: 100%;
background: black;
min-height: 100px;
}
#mixedheightheader {
top: 0;
bottom: 0;
width: 100%;
height: 100vh;
min-height: 200px;
overflow: hidden;
background: grey;
clear: both;
}
#below {
width: 100%;
background: darkgrey;
height: 100px;
position: relative;
z-index: -1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="mixedheightheader"></div>
<div id="headermenu"></div>
<div id="below"></div>

I have updated you fiddle:
https://jsfiddle.net/yLon2oj3/11/
$(function() {    
var isFixed = false; //This is to not fix if already fixed and reverse
$(window).scroll(function() {
var mixedHeightHeader = $('#mixedheightheader');
//This uses the offset top position and the height to calculate the bottom of your variable header
var mixedHeightHeaderBottom = mixedHeightHeader.offset().top + mixedHeightHeader.height();
var headerMenu = $('#headermenu');
if ($(document).scrollTop() < mixedHeightHeaderBottom && isFixed)     {        
if (headerMenu) {                  
headerMenu.css({
top: '0',
position: 'relative'
});  
isFixed = false;
//this is to remove the placeholder space of the fixed top nav, when its not fixed to top
mixedHeightHeader.css('margin-bottom', '0');
}    
}    
else  if ($(document).scrollTop() > mixedHeightHeaderBottom && !isFixed)   {        
if (headerMenu) {                      
headerMenu.css({
top: '0',
position: 'fixed'
});
//This holds the position that was occupied by the fixed top nav when it was a relative element, because its now taken out of the flow.
mixedHeightHeader.css('margin-bottom', headerMenu.height() + 'px');
}
isFixed = true;
}
});
});

Related

How to center with javascript an element on y?

I am trying to make a sticky banner witn html and css and js. My html is this
window.addEventListener('scroll', function(ev) {
var distanceToTop = container.getBoundingClientRect().top;
if (container.getBoundingClientRect().top >= document.documentElement.scrollTop - screen.height + 400) {
sticky.style.top = "100px"
} else {
sticky.style.top = document.documentElement.scrollTop - screen.height + 400 + "px";
}
});
.container {
background: red;
width: 600px;
height: 100px;
position: relative;
}
.sticky {
background: blue;
width: 200px;
height: 200px;
position: absolute;
right: 0;
top: 100px;
}
<div class="container">
<div class="sticky"></div>
</div>
I would want when i scroll the window the stocky div to be center on y axis and when the distance between container and top of the page is less then 200px the two divs to be attached.
Can anyone to give me a clue?

Two conditions for scroll offset and element

What I trying to do is, show .box-tocart when scroll top bigger than .product-info-main offset top and also if reached to .page-footer should hide but I couldn't mix these conditions together, each condition work separately but not working together with || or &&
var target = $('.product-info-main').offset().top;
$(window).scroll(function() {
var footer = $('.page-footer').offset().top;
var element = $('.box-tocart').offset().top;
if (($(window).scrollTop() >= target) || (element >= footer)) {
$('.box-tocart').show();
} else {
$('.box-tocart').hide();
}
});
body {
height: 2000px;
}
#nothing {
height: 100px;
background: red;
}
.product-info-main {
height: 1000px;
}
.box-tocart {
height: 30px;
background: green;
display: none;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
.page-footer {
background: blue;
height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="nothing"></div>
<div class="product-info-main">
<div class="box-tocart"></div>
</div>
<div class="page-footer"></div>
Goal: show .box-tocart if scroll top bigger than .product-info-main offset top, else hide. Also if reached to .page-footer hide, else show, but I want these two conditions together, but couldn't make it work.
The problem with current snippet is, it not hide .box-tocart after reach .page-footer
Simple explanation: green div should show after red div, else hide and should hide after
reach to blue div else hide.
You need to change the condition to:
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
if ((scrollTop >= target) && (scrollTop + windowHeight <= footer)) {
// ...
}
Updated example:
var target = $('.product-info-main').offset().top;
$(window).scroll(function() {
var footer = $('.page-footer').offset().top;
var element = $('.box-tocart').offset().top;
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
if ((scrollTop >= target) && (scrollTop + windowHeight <= footer)) {
$('.box-tocart').show();
} else {
$('.box-tocart').hide();
}
});
body {
height: 2000px;
}
#nothing {
height: 100px;
background: red;
}
.product-info-main {
height: 1000px;
}
.box-tocart {
height: 30px;
background: green;
display: none;
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
.page-footer {
background: blue;
height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="nothing"></div>
<div class="product-info-main">
<div class="box-tocart"></div>
</div>
<div class="page-footer"></div>
You should use $(window).scrollTop() instead of element so your OR condition should be like if (... || $(window).scrollTop() >= footer, that’s because the scroll position is all relative to the window view and not to the cart box
I hope it can help you.

Built a scroll controller, need to reverse it

My code allows scrolling vertically in the bottom section to control scrolling horizontally in the top section.
My jsfiddle
You'll see the colors shift through a gradient. Works pretty well. Problem is that I can't quite seem to get the inverse to work. Scrolling horizontally in the top controls scrolling in the bottom.
Any ideas?
Here's the script that makes it work:
// Add event listener for scrolling
$("#bottom").on("scroll", function bottomScroll() {
var scrolledleft = parseInt($("#bottom").scrollTop()) * 1;
console.log(scrolledleft + scrolledright)
$("#top").scrollLeft(scrolledleft + scrolledright)
})
//Move right column to bottom initially
$("#top").scrollLeft($("#top").height())
//Get actual distance scrolled
var scrolledright = parseInt($("#top").scrollLeft())
Your event handlers need to temporarily cancel each other so that they don't both fire at once. You want to calculate your position percentage based on the current scrollLeft / (width of child div - width of container), then apply that percentage to the other element, and likewise for top/height. Also I changed the height of #top to 50% in CSS.
var handler = function (e) {
var src = e.target;
// the first element that triggers this function becomes the active one, until it's done
if (!activeScroller) activeScroller = src.id;
else if (activeScroller != src.id) return;
var $b = $("#bottom");
var $t = $("#top");
var scrollH = $("#bottom-content").height() - $b.height();
var scrollW = $("#top-content").width() - $t.width();
var scrollPct = 0;
if (src.id == "top") {
if (scrollW > 0) {
scrollPct = $t.scrollLeft() / scrollW;
}
$b.scrollTop(scrollH * scrollPct);
} else {
if (scrollH > 0) {
scrollPct = $b.scrollTop() / scrollH;
}
$t.scrollLeft(scrollW * scrollPct);
}
// give all animations a chance to finish
setTimeout(function () { activeScroller = ""; }, 100);
};
var activeScroller = "";
$("#top,#bottom").on("scroll", handler);
#top {
position: absolute;
margin: auto;
top: 0;
right: 0;
left: 0;
width: 100%;
height: 50%;
position: fixed;
overflow: auto;
background: red;
}
#top-content {
height: 100%;
width: 2000px;
background: linear-gradient(90deg, red, blue);
}
#bottom {
position: absolute;
margin: auto;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 50%;
position: fixed;
overflow: auto;
background: green;
z-index: 100;
}
#bottom-content {
height: 2000px;
width: 100%;
background: linear-gradient(0deg, orange, green);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="top">
<div id="top-content"></div>
</div>
<div id="bottom">
<div id="bottom-content"></div>
</div>
Check out this:
https://jsfiddle.net/1p7gp72h/1/
I'm not sure what your end goal is here.
$("#top").on("scroll", function topScroll() {
var scrolledleft = parseInt($("#top").scrollTop()) * 1;
$("#bottom").scrollLeft(scrolledleft + scrolledright)
});
#top {
top: 0;
right: 0;
left: 0;
width: 5000px;
height: 100%;
overflow: auto;
background: red;
overflow-x: scroll;
overflow-y: hidden;
white-space:nowrap;
}
Scroll to left ::
$('div').scrollLeft(1000);
Scroll back to normal/ scroll to right ::
$('div.slick-viewport').scrollLeft(-1000);

How to set a div as background?

I've found something interesting on this link. But I can't figure out how to make it and I want to know if anyone has any idea how. So what I realised on this is that even if you resize de browser window the elements keep floating but somehow the only focused element here is the webpage not the floating divs from left and right. This is what I've tried https://jsfiddle.net/eoopvgmc/9/ but the only thing that is working is those floating elements.
Here is what I want to know how to do it http://demo.inskinmedia.com/cds/show.php?live=uxtxbpwvx&ismState=1
(function($) {
var element = $('.left-zone'),
originalY = element.offset().top;
var topMargin = 0;
element.css('position', 'relative');
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
element.stop(false, false).animate({
top: scrollTop < originalY ? 0 : scrollTop - originalY + topMargin
});
});
})(jQuery);
(function($) {
var element = $('.right-zone'),
originalY = element.offset().top;
var topMargin = 0;
element.css('position', 'relative');
$(window).on('scroll', function(event) {
var scrollTop = $(window).scrollTop();
element.stop(false, false).animate({
top: scrollTop < -250 ? -250 : scrollTop - originalY + topMargin
});
});
})(jQuery);
Just add a div with a fixed width to wrap them
Edit: Changed the code to fit the request ->
$(document).ready(function() {
$(document).on('scroll', function() {
$('.ads').css({
'top': $(window).scrollTop() + 'px'
});
})
});
body {
margin: 0;
}
.wrapper {
position: relative;
width: 500px;
margin: 0 auto;
}
.main_content {
background: blue;
float: left;
height: 1500px;
width: 500px;
}
.top_banner {
background: orange;
float: left;
height: 250px;
width: 500px;
}
.left-zone,
.right-zone {
position: absolute;
top: 0;
width: 224px;
height: 284px;
transition: top 0.8s;
}
.left-zone {
background: yellow;
left: -224px;
}
.right-zone {
background: red;
right: -224px;
top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="left-zone ads"></div>
<div class="top_banner"></div>
<div class="main_content"></div>
<div class="right-zone ads"></div>
</div>

Position Fixed - Set width to be equal to container

I have been trying to set a div's position to fixed when a user has scrolled far enough. I noticed that when the div's position is set to fixed the width is not the same as the parent elemnt. How can I keep the width of the div with position: fixed the same as the parent element?
In this example I want the bottom div to be the same width as the yellow box once position:fixed is set.
http://jsfiddle.net/BYJPB/
Here's my HTML:
<header>
<div class="filler-space">
Filler Space
</div>
<div class="toolbar">
<div class="current-article">
<div class="progress-bar"></div>
My article
</div>
</div>
</header>
Here's my CSS:
body {
padding:0 10px;
height: 1000px;
}
.filler-space {
background-color: yellow;
border:1px solid #000000;
height: 140px;
}
.toolbar {
border: 1px solid black;
}
.current-article {
font-weight: 600;
height: 100%;
line-height: 40px;
overflow: hidden;
width: 100%;
z-index: -1;
}
.progress-bar {
position: absolute;
}
.prog .progress-bar {
background: none repeat scroll 0 0 #F2F4F7;
bottom: 0;
height: 100%;
left: 0;
margin: 0 -10px 0 -10px;
overflow: hidden;
right: 0;
top: 0;
transition: width 0.1s ease 0s;
z-index: -1;
width: 100%;
}
Here is my JavaScript:
var $toolbar = $('.toolbar');
var $window = $(window);
var $header = $('header');
$(document).scroll(function() {
var scrollTop = $window.scrollTop();
if ( scrollTop > 150) {
$toolbar.css({
'position' : 'fixed',
'top' : 0
});
$header.addClass('prog');
}
else {
$toolbar.css({
'position' : 'static',
'top' : 0
});
$header.removeClass('prog');
}
});
Update your js, I dont understand your requirements, but i think this is what you are looking for.
if ( scrollTop > 150) {
$toolbar.css({
'position' : 'fixed',
'top' : 0,
'width':$header.width()
});
$header.addClass('prog');
}
else {
$toolbar.css({
'position' : 'static',
'top' : 0
});
$header.removeClass('prog');
}

Categories