I'm looking for a soultion when a section is out of viewport, Locomotive scroll will change the css attributes on another element and when is in viewport, it reverts that back.
I couldn't find a soulution or a topic. basic knowledge of JS. So, appreaciate if someone can help me out to figure this out.
This function from https://stackoverflow.com/a/57279138/3807365 is pretty simple to incorporate on scroll.
function isInView(el) {
const box = el.getBoundingClientRect();
return box.top < window.innerHeight && box.bottom >= 0;
}
Lets try
function isInView(el) {
const box = el.getBoundingClientRect();
return box.top < window.innerHeight && box.bottom >= 0;
}
var div1 = document.querySelector(".div1")
var div2 = document.querySelector(".div2")
window.onscroll = function() {
if (isInView(div1)) {
div2.classList.add("active");
} else {
div2.classList.remove("active");
}
if (isInView(div2)) {
div1.classList.add("active");
} else {
div1.classList.remove("active");
}
}
body {
height: 1000px;
}
.div {
width: 50px;
height: 50px;
}
.div1 {
margin-top: 100px;
background: aqua;
margin-bottom: 100px;
}
.div2 {
background: magenta;
}
.active {
border: 2px solid red;
}
<body>
<div class="div div1"></div>
<div class="div div2"></div>
</body>
Related
i'm trying to do a simple task of moving a div's position when the mouse is clicked. While style.left isn't working, style.backgroundColor is working. Google hasn't been helpful, please help
`body {
background-color: aquamarine;
}
.box {
height: 120px;
width: 120px;
border-radius: 60px;
background-color: black;
}`
const moving = document.querySelector(".box");
function move() {
let x = 100;
moving.style.left = 10 + "px";
console.log("hi");
moving.style.backgroundColor = "white";
}
moving.addEventListener("click", move);
by default div have a static position
static
The element is positioned according to the normal flow of the
document.
The top, right, bottom, left, and z-index properties have no
effect. This is the default value.
https://developer.mozilla.org/fr/docs/Web/CSS/position
an idea can be to set the position of your box in relative or absolute
const moving = document.querySelector(".box");
function move() {
let x = 100;
moving.style.left = 10 + "px";
console.log("hi");
moving.style.backgroundColor = "white";
}
moving.addEventListener("click", move);
body {
background-color: aquamarine;
}
.box {
height: 120px;
position: relative;
width: 120px;
border-radius: 60px;
background-color: black;
}
`
<div class="box"></div>
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.
I'm trying to create a seamless looping webpage where the content repeats over and over without having to actually duplicate the divs. I came across a THIS CODEPEN, which is exactly what I was looking for, but the mobile experience is really glitchy and flickers when repositioning to the top of the page.
Any solves for mobile? Or edits to this JS?
See below and thanks!
var doc = window.document,
context = doc.querySelector('.js-loop'),
clones = context.querySelectorAll('.is-clone'),
disableScroll = false,
scrollHeight = 0,
scrollPos = 0,
clonesHeight = 0,
i = 0;
function getScrollPos () {
return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
}
function setScrollPos (pos) {
context.scrollTop = pos;
}
function getClonesHeight () {
clonesHeight = 0;
for (i = 0; i < clones.length; i += 1) {
clonesHeight = clonesHeight + clones[i].offsetHeight;
}
return clonesHeight;
}
function reCalc () {
scrollPos = getScrollPos();
scrollHeight = context.scrollHeight;
clonesHeight = getClonesHeight();
if (scrollPos <= 0) {
setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
}
}
function scrollUpdate () {
if (!disableScroll) {
scrollPos = getScrollPos();
if (clonesHeight + scrollPos >= scrollHeight) {
// Scroll to the top when you’ve reached the bottom
setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
disableScroll = true;
} else if (scrollPos <= 0) {
// Scroll to the bottom when you reach the top
setScrollPos(scrollHeight - clonesHeight);
disableScroll = true;
}
}
if (disableScroll) {
// Disable scroll-jumping for a short time to avoid flickering
window.setTimeout(function () {
disableScroll = false;
}, 40);
}
}
window.requestAnimationFrame(reCalc);
context.addEventListener('scroll', function () {
window.requestAnimationFrame(scrollUpdate);
}, false);
window.addEventListener('resize', function () {
window.requestAnimationFrame(reCalc);
}, false);
// Just for this demo: Center the middle block on page load
window.onload = function () {
setScrollPos(Math.round(clones[0].getBoundingClientRect().top + getScrollPos() - (context.offsetHeight - clones[0].offsetHeight) / 1));
};
html,
body {
height: 100%;
overflow: hidden;
}
.Loop {
position: relative;
height: 100%;
overflow: auto;
-webkit-overflow-scrolling: touch;
}
section {
position: relative;
text-align: center;
min-height: 100vh;
max-height: 100vh;
height: 100%;
}
::scrollbar {
display: none;
}
body {
font-family: "Avenir Next", Helvetica, sans-serif;
font-weight: normal;
font-size: 100%;
}
.red {
background: #FF4136;
}
.green {
background: #2ECC40;
}
.blue {
background: #0074D9;
}
.orange {
background: rebeccapurple;
}
h1 {
margin: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 100%;
font-size: 80px;
letter-spacing: 5px;
color: #fff;
text-transform: uppercase;
}
<main class="Loop js-loop">
<section class="green">
<h1>FIRST</h1>
</section>
<section class="red">
<h1>For</h1>
</section>
<section class="blue">
<h1>All</h1>
</section>
<section class="orange">
<h1>And</h1>
</section>
<section class="blue">
<h1>All</h1>
</section>
<section class="red">
<h1>LAST</h1>
</section>
<!--
These blocks are the same as the first blocks to get that looping illusion going.
You need to add clones to fill out a full viewport height.
-->
<section class="green is-clone">
<h1>FIRST</h1>
</section>
<section class="red is-clone">
<h1>For</h1>
</section>
</main>
I'm trying to write a function that watches the window for a few things:
If the window is greater-than 900px and the window is scrolled passed 100 add a BG color to the nav
If the nav is scrolled passed 100 and the window is resized to less-than 900px change the BG color nav.
I've written two functions that should be doing the trick. My problem is my functions work right up until you scroll passed 100 and resize the screen: they won't apply the second class with the second bg color.
Snippet below. Can anyone provide assistance?
$(document).ready(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
var nav = $('nav');
if( scroll > 100 ) {
nav.addClass('scrolled');
} else {
nav.removeClass('scrolled');
}
});
$(window).resize(function() {
var mq = window.matchMedia('(min-width: 100px) and (max-width: 900px)');
if( mq.matches && $('nav').hasClass('scrolled')) {
$('nav').removeClass('scrolled');
console.log("Working");
$('nav').addClass('scrolledTwo');
} else {
console.log("Not working");
$('nav').removeClass('scrolledTwo');
}
});
});
* {
padding: 0;
margin: 0;
}
nav {
height: 70px;
width: 100%;
border: 1px solid;
transition: all .2s ease;
background-color: transparent;
position: fixed;
top: 0;
left: 0;
z-index: 1000;
}
.nav-fixedWidth {
height: inherit;
width: 1000px;
margin: 0 auto;
border: 1px solid #ccc;
}
main {
width: 100%;
height: 2000px;
border: 1px solid;
background-color: #f1f1f1;
}
.scrolled {
background-color: red;
}
.scrolledTwo {
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div class="nav-fixedWidth"></div>
</nav>
<main></main>
Your code is working fine it is even applying the second class with the second bg color if you will resize slowly your window. The only issue is this if( mq.matches && $('nav').hasClass('scrolled')) condition. As you have mentioned $('nav').hasClass('scrolled') so first time when you will resize it will be true and then
$('nav').removeClass('scrolled');
console.log("Working");
$('nav').addClass('scrolledTwo');
this will apply scrolledTwo class to nav. After that when you will further resize it will never pass this if( mq.matches && $('nav').hasClass('scrolled')) condition, until you don't resize the screen width to less than 100px or greater than 900px and scroll, and will always goto else and you will always see the red color. Try removing it
$(document).ready(function() {
$(window).scroll(function() {
var scroll = $(window).scrollTop();
var nav = $('nav');
if( scroll > 100 ) {
nav.addClass('scrolled');
} else {
nav.removeClass('scrolled');
}
});
$(window).resize(function() {
var mq = window.matchMedia('(min-width: 100px) and (max-width: 900px)');
if( mq.matches ) {
$('nav').removeClass('scrolled');
console.log("Working");
$('nav').addClass('scrolledTwo');
} else {
console.log("Not working");
$('nav').removeClass('scrolledTwo');
}
});
});
* {
padding: 0;
margin: 0;
}
nav {
height: 70px;
width: 100%;
border: 1px solid;
transition: all .2s ease;
background-color: transparent;
position: fixed;
top: 0;
left: 0;
z-index: 1000;
}
.nav-fixedWidth {
height: inherit;
width: 1000px;
margin: 0 auto;
border: 1px solid #ccc;
}
main {
width: 100%;
height: 2000px;
border: 1px solid;
background-color: #f1f1f1;
}
.scrolled {
background-color: red;
}
.scrolledTwo {
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav>
<div class="nav-fixedWidth"></div>
</nav>
<main></main>
Another issue in your code is if I scroll and resize the screen width between 100 to 900 and then again resize it to out of this window then there is no class assigned to your div and that is due to no class added in else of resize function. Changing that to this will do that trick also :)
else {
console.log("Not working");
$('nav').removeClass('scrolledTwo');
var scroll = $(window).scrollTop();
if( scroll > 100 ) {
$('nav').addClass('scrolled');
}
}
I'm trying to display a thumbnail version of a logo in the header after I get past the main page and when the content starts. I'd also like it to disappear again once I go back to the main page. I've attempted some JavaScript but if anyone has any feedback or suggestions on how to fix it. I added some code to a JSFiddle for help.
HTML
<header>
<img src="img.png" id="logo" />
</header>
<div id="mainPage">
<img src="img.png" />
</div>
<div id="main">
This is the content page.
</div>
CSS
header {
background-color: blue;
width: 100%;
height: 20px;
position: fixed;
top: 0;
border-bottom: 1px solid white;
}
#mainPage {
margin: 0;
padding: 0;
background-color: blue;
height: 500px;
}
#mainPage img {
width: auto;
display: block;
margin: 0 auto;
}
#main{
height: 500px;
}
#logo {
visibility: hidden;
}
JS
function showImg() {
var img = document.getElementById('logo');
var h = window.innerHeight;
if(h < 600) {
img.style.visibility = 'hidden';
}
else {
img.style.visibility = 'visible';
}
}
http://jsfiddle.net/nkjqLyfg/2/
As you can see in my fork of your fiddle, you just need to set up your function as a handler for the scroll event. Also, different browsers have different ways of expressing the current scroll position. The following works in Chrome:
function showImg() {
var img = document.getElementById('logo');
var scrollY = window.scrollY;
if(scrollY < 600) {
img.style.visibility = 'hidden';
}
else {
img.style.visibility = 'visible';
}
}
document.addEventListener("scroll", showImg);