I have the following code which fixes the position of a menu at the point that it is going to scroll off the top of the page.
$(function () {
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('.menu').offset().top - parseFloat($('.menu').css('margin-top').replace(/auto/, 0));
$(window).scroll(function (event) {
var y = $(this).scrollTop();
if (y >= top) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
});
}
});
css
.container {
width:400px;
margin:auto;
}
.header {
background-color:#096;
height:150px;
}
.fixed {
position:fixed;
top:0px;
left:50%;
margin-left:50px;
}
.bodyContainer {
overflow:hidden;
}
.menu {
float:right;
width:150px;
height:250px;
background-color:#F00;
}
.bodyCopy {
float:left;
width:250px;
height:1000px;
}
.footer {
background-color:#096;
height:250px;
}
HTML
<div class="container">
<div class="header">
<p>Test Header</p>
</div>
<div class="bodyContainer">
<div class="menu">
<p>test</p>
</div>
<div class="bodyCopy">
<p>test</p>
</div>
</div>
<div class="footer">
<p>Test Footer</p>
</div>
What I now want to do is make it start scrolling again when the user reaches the bottom of the page (so that it does not cover the footer in the page).
jsfiddle here...
Here is new a approach with css3.
use position:sticky to follows the scroll.
Here is the article explained.
http://updates.html5rocks.com/2012/08/Stick-your-landings-position-sticky-lands-in-WebKit
and old way of doing this demo
with sticky position demo
var top = $('.menu').offset().top - parseFloat($('.menu').css('margin-top').replace(/auto/, 0));
var _height = $('.menu').height();
$(window).scroll(function(event) {
var y = $(this).scrollTop();
var z = $('.footer').offset().top;
if (y >= top && (y+_height) < z) {
$('.menu').addClass('fixed');
} else {
$('.menu').removeClass('fixed');
}
});
http://jsfiddle.net/AlienWebguy/CV3UA/1/
If you want the menu to simply stay where it is when it reaches the footer you'll need to add more logic to append it into the DOM:
var msie6 = $.browser == 'msie' && $.browser.version < 7;
if (!msie6) {
var top = $('.menu').offset().top - parseFloat($('.menu').css('margin-top').replace(/auto/, 0));
var _height = $('.menu').height();
var _original_top = $('.menu').offset().top;
$(window).scroll(function(event) {
var y = $(this).scrollTop();
var z = $('.footer').offset().top;
if (y >= top && (y + _height) < z) {
$('.menu').insertBefore($('.bodyCopy')).removeClass('stuck-bottom').addClass('fixed');
} else {
if ((y + _height) >= z) {
$('#menu').insertBefore($('.footer')).removeClass('fixed').addClass('stuck-bottom');
}
else $('.menu').insertBefore($('.bodyCopy')).removeClass('stuck-bottom').removeClass('fixed');
}
});
}
I'm sure there's a more elegant way to do this. Play around :)
http://jsfiddle.net/AlienWebguy/CV3UA/2/
Related
I am working on the below code. Why am I not able to detect which div is reaching at the top of page in both down or up scroll?
$(window).scroll(function() {
$(".container").each(function() {
var $that = $(this);
var po = $(this).offset().top;
if (po >= 0 && po <= 300) {
console.log($that.data('map'));
}
});
});
.container {
height: 690px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" data-map="One">One</div>
<div class="container" data-map="Two">Tow</div>
<div class="container" data-map="Three">Three</div>
<div class="container" data-map="Four">Four</div>
<div class="container" data-map="Five">Five</div>
You'll need to use $(window).scrollTop(); as well as $that.outerHeight()
$(window).scroll(function() {
var windowScrollTop = $(this).scrollTop(); // window scroll top
$(".container").each(function() {
var $that = $(this);
var po = $that.offset().top;
var poHeight = $that.outerHeight(true); // the height of the element
var distanceTop = 100; // the distance from top to run the action .. it can be 0 if you want to run the action when the element hit the 0 top
if (windowScrollTop + distanceTop >= po && windowScrollTop + distanceTop <= po + poHeight) {
if(!$that.hasClass('red')){ // if element dosen't has class red
console.log($that.data('map'));
$(".container").not($that).removeClass('red'); // remove red class from all
$that.addClass('red'); // add red class to $that
}
}
});
}).scroll(); // run the scroll onload
.container {
height: 690px;
}
.container.red{
background : red;
color : #fff;
font-size: 30px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container" data-map="One">One</div>
<div class="container" data-map="Two">Two</div>
<div class="container" data-map="Three">Three</div>
<div class="container" data-map="Four">Four</div>
<div class="container" data-map="Five">Five</div>
I have a fixed div on the page which contains a logo and as the user scrolls and this logo passes over other divs I wnat to the change the colour of the logo.
I have this working over a single div but need to it work across multiple so any help appreciated.
The WIP site can be seen here... dd.mintfresh.co.uk - if you scroll down you'll (hopefully) see the logo change from black to white as it crosses an illustrated egg. I need the same to happen when it crosses other divs further down the page.
The script so far...
jQuery(window).scroll(function(){
var fixed = jQuery("logo");
var fixed_position = jQuery("#logo").offset().top;
var fixed_height = jQuery("#logo").height();
var toCross_position = jQuery("#egg").offset().top;
var toCross_height = jQuery("#egg").height();
if (fixed_position + fixed_height < toCross_position) {
jQuery("#logo img").css({filter : "invert(100%)"});
} else if (fixed_position > toCross_position + toCross_height) {
jQuery("#logo img").css({filter : "invert(100%)"});
} else {
jQuery("#logo img").css({filter : "invert(0%)"});
}
}
);
Any help appreciated. Thanks!
you need to fire a div scroll event. you can assign
$("div1").scroll(function(){
//change the color of the div1
}
});
$("div2").scroll(function(){
//change the color of the div2
}
});
or you can assign a class to divs which you want to change the color
$(".div").scroll(function(){
//change the color of the div which you are scrolling now
}
});
You can use like this :-
$(window).scroll(function() {
var that = $(this);
$('.section').each(function() {
var s = $(this);
if (that.scrollTop() >= s.position().top) {
if(s.hasClass('active')) {
$('.logo').addClass('invert');
} else {
$('.logo').removeClass('invert');
}
}
});
});
body {
padding: 0;
margin: 0;
}
div {
background: #f00;
height: 400px;
}
.logo {
position: fixed;
top: 0;
left: 0;
width: 100px;
}
.logo.invert {
filter: invert(100%);
}
div:nth-child(even) {
background: #ff0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src="https://dd.mintfresh.co.uk/wp-content/uploads/2018/06/DD_logo.svg" class="logo" />
<div id="page1" class="section"></div>
<div id="page2" class="section active"></div>
<div id="page3" class="section"></div>
<div id="page4" class="section active"></div>
<div id="page5" class="section"></div>
As your site code you can do like this :
$(window).scroll(function() {
var that = $(this);
$('#content > section').each(function() {
var s = $(this);
if (that.scrollTop() >= s.position().top) {
if(s.hasClass('black')) {
$('#logo img').css({filter: 'invert(0%)'});
} else {
$('#logo img').css({filter: 'invert(100%)'});
}
}
});
});
Please have a look at my example.
I have multiple rows on my website and a scrollto() button, wich is always at the bottom of the screen.
Depending on where the usere is located on my site at a certain moment, I would like him to move to the next row after he clicked the button.
I am aware of how to make a user scrollto(), but I have no clue what kind of selector I should use.
function myFunction() {
var winScroll = window.scrollTop; // current scroll of window
// find closest div
var rows = document.querySelectorAll('.row');
var closest = rows[0]; // first section
var closest_idx = 0;
var min = closest.offsetTop - winScroll;
rows.forEach(function(row, index) {
var divTopSpace = row.offsetTop - winScroll;
if( divTopSpace < min && divTopSpace > 0 ) {
closest = row;
closest_idx = index;
min = divTopSpace;
}
});
var next_idx = closest_idx + 1;
if (next_idx == rows.length) {
next_idx = 0;
}
console.log(rows[next_idx]);
}
.rowOne {
height: 100vh;
background-color: peachpuff;
}
.rowTwo {
height: 100vh;
background-color: firebrick;
}
.rowThree {
height: 100vh;
background-color: deepskyblue;
}
.btn {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 30px;
}
<div class="main">
<div class="row rowOne">
<div class="a">
<div class="b">
Foo
</div>
</div>
</div>
<div class="row rowTwo">
<div class="a">
<div class="b">
Bar
</div>
</div>
</div>
<div class="row rowThree">
<div class="a">
<div class="b">
Foobar
</div>
</div>
</div>
<button id="btn" class="btn" onclick="myFunction()">Button</button>
</div>
Thank you in advance.
Since they are all the same height (100% of the window height), the simple solution would be to simply scroll by that amount.
window.scrollBy(0, window.innerHeight);
Otherwise, you'll need to detect which element is the "current" one, and then get it's next sibling, and then scroll to it. Something like this (haven't tested, so syntax might be off, but this should give you an idea)
var winScroll = window.scrollTop; // current scroll of window
// find closest div
var rows = document.querySelectorAll('.row');
var closest = rows[0]; // first section
var closest_idx = 0;
var min = closest.offsetTop - winScroll;
rows.forEach(function(row, index) {
var divTopSpace = row.offsetTop - winScroll;
if( divTopSpave < min && divTopSpave > 0 ) {
closest = row;
closest_idx = index;
min = divTopSpace;
}
});
var next_idx = closest_idx + 1;
if (next_idx == rows.length) {
next_idx = 0;
}
window.scrollTo(rows[next_idx].scrollTop);
Is there any way to check if specified html element is in viewport - no window but specified div? I found only one meaningful solution but I can't make it work for me.
According to this question Check if element is visible in div
I created a example here: http://jsfiddle.net/jm91n80u/
This is my html code:
<body style="overflow:hidden;">
<div id="outer" style="position:absolute;left:150px;top:20px;right:100px;bottom:30px;overflow:hidden;border:1px solid blue;">
<div id="inner" style="position:relative;height:300px;border:1px solid red;width:100px;overflow-y:auto;overflow-x:hidden;">
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">1</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">2</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">3</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;background:yellow;" class="test" id="id1">4</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">5</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">6</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">7</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">8</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">9</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">10</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">11</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">12</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">13</div>
<div style="position:relative;width:100%;height:30px;border:1px solid grey;" class="test">14</div>
</div>
</div>
<div id="result" style="position:absolute;bottom:0px;overflow:hidden;border:1px solid black;height:20px;width:100%;"></div>
</body>
This is a js function
$(document).ready(function () {
$.belowthefold = function (lookIn, elements, settings) {
var fold = $(lookIn).height() + $(lookIn).scrollTop();
return $(elements).filter(function () {
return fold <= $(this).offset().top - settings.threshold;
});
};
$.abovethetop = function (lookIn, elements, settings) {
var top = $(lookIn).scrollTop();
return $(elements).filter(function () {
return top >= $(this).offset().top + $(this).height() - settings.threshold;
});
};
$.rightofscreen = function (lookIn, elements, settings) {
var fold = $(lookIn).width() + $(lookIn).scrollLeft() + $(lookIn).offset().width;
return $(elements).filter(function () {
return fold <= $(this).offset().left - settings.threshold;
});
};
$.leftofscreen = function (lookIn, elements, settings) {
var left = $(lookIn).scrollLeft();
return $(elements).filter(function () {
return left >= $(this).offset().left + $(this).width() - settings.threshold;
});
};
$("#inner").scrollTop(100);
var b = $.belowthefold("#inner", ".test", { threshold: 0 }).toArray();
var t = $.abovethetop("#inner", ".test", { threshold: 0 }).toArray();
var r = $.rightofscreen("#inner", ".test", { threshold: 0 }).toArray();
var l = $.leftofscreen("#inner", ".test", { threshold: 0 }).toArray();
var el = $("#id1")[0];
var bS = "below the fold : ";
for (var i = 0; i < b.length; i++) {
bS += $(b[i]).html() + ",";
}
var tS = "above the top : ";
for (var i = 0; i < t.length; i++) {
tS += $(t[i]).html() + ",";
}
var rS = "right of screen : ";
for (var i = 0; i < r.length; i++) {
rS += $(r[i]).html() + ",";
}
var lS = "left of screen : ";
for (var i = 0; i < l.length; i++) {
lS += $(l[i]).html() + ",";
}
console.log(bS);
console.log(tS);
console.log(rS);
console.log(lS);
});
What I'm trying to do is get all '.test' elements which are currently invisible (or partial invisible in target solution, any switch will be appreciated) in inner container with information about their position. The result of this should be:
below the fold : 13, 14
above the top : 1,2,3,4
right of screen :
left of screen :
But in this particular case those functions doesn't work. I tried use several other solutions, but each one treats viewport as window.
Can you explain what am I doing wrong? Any help will be appreciated.
You should compare div's positions to: viewport size and windows bounds.
Roughly : if(div.top > (window.top + viewport.height )) {/*this is visible*/} else {/*this is not visible*/}
You could even make it more specific (how much area of div ?)
if((div.top **+ 50% of div.height**) > (window.top + viewport.height )) {/*this is visible*/}
This post gives some codes Check if element is between 30% and 60% of the viewport
$(document).ready(function() {
// Get viewport height, gridTop and gridBottom
var windowHeight = $(window).height(),
gridTop = windowHeight * .3,
gridBottom = windowHeight * .6;
$(window).on('scroll', function() {
// On each scroll check if `li` is in interested viewport
$('ul li').each(function() {
var thisTop = $(this).offset().top - $(window).scrollTop(); // Get the `top` of this `li`
// Check if this element is in the interested viewport
if (thisTop >= gridTop && (thisTop + $(this).height()) <= gridBottom) {
$(this).css('background', 'red');
} else {
$(this).css('background', 'gray');
}
});
});
});
$(document).ready(function() {
var mouseX;
var mouseY;
$(document).mousemove(function(e) {
mouseX = e.pageX;
mouseY = e.pageY;
});
$("#maincontainer").mousemove(function() {
// $('#DivToShow').css({'top':mouseY,'left':mouseX}).fadeIn('slow');
$('#DivToShow').html("Y " + mouseY + " --- " + "X " + mouseX);
if (mouseY > 230) {
$('html, body').animate({
scrollBottom: $elem.height()
}, 800);
}
});
});
pls help, I am trying to make a auto page up and down scroll based on pointer position. when pointer coming to bottom of browser, page need to scroll down 60px ++. not a single scroll to end of page.
Try this solution.
On mousemove, get the clientY and the window height. If the difference is less than 60, then scroll 60 more than the current scrollTop:
$(document).on('mousemove', function(e) {
var y = e.clientY;
var h = $(window).height();
var n = h - y;
if (n < 60) {
var t = parseFloat($(window).scrollTop());
console.log(t);
$('html,body').animate({scrollTop:t + 60 + 'px'},200);
} else {
$('html,body').stop();
}
});
#wrapper,
.section {
width:100%;
float:left;
}
.section {
height:80px;
border:1px solid #ccc;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="wrapper">
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
<div class="section"></div>
</div>