Scroll Horizontally on hover only runs once? - javascript

I'm trying to make a simple scroll left and right div on hover. I'm really not sure what I'm doing wrong, I hover, but it only moves the 50 specified in the if statement. Do I need to add some kind of loop while I'm still hovering? Any help would be greatly appreciated.
Basically, I want to be able to hover over the two black boxes right and left and while it's hovered move right or left, when I remove the mouse it should stop.
$("#left").hover(function() {
var leftPos = $('#wrapper').scrollLeft();
$("#wrapper").animate({
scrollLeft: leftPos - 50
}, 1);
});
$("#right").hover(function() {
var leftPos = $('#wrapper').scrollLeft();
$("#wrapper").animate({
scrollLeft: leftPos + 50
}, 1);
});
html,
body {
background-color: #eeeeee;
margin: 0;
overflow-x: scroll;
overflow-y: hidden;
}
#left {
position: absolute;
width: 10vw;
height: 100vh;
top: 0;
left: 0;
z-index: 1;
background-color: black;
}
#right {
position: absolute;
width: 10vw;
height: 100vh;
top: 0;
right: 0;
z-index: 1;
background-color: black;
}
#wrapper {
width: 100%;
height: 100vh;
white-space: nowrap;
overflow-y: hidden;
overflow-x: scroll;
}
#inner_wrap {
width: 4000px;
height: 100vh;
align-items: center;
display: flex;
}
#firstcontent {
align-items: center;
display: flex;
vertical-align: middle;
color: white;
float: left;
margin-left: 20vw;
width: 400px;
height: 250px;
background-color: #2d2d2d;
}
.thumbone {
width: 400px;
height: 250px;
background-color: lightgrey;
display: inline-block;
}
.thumbtwo {
width: 400px;
height: 250px;
background-color: grey;
display: inline-block;
}
<script src="https://corporate3.bdjobs.com/js/jquery.min.js"></script>
<div id="left"></div>
<div id="right"></div>
<div id="wrapper">
<div id="inner_wrap">
<div id="firstcontent">hover or scroll</div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
</div>
</div>
Link to script
jsfiddle
[also a side note, why does this work only on jsfiddle and no where else?]

Your issue is because the mouseenter and mouseleave events (which underpin the hover() logic) only fire once, when the mouse enters/leaves the targeted element. If you want to repeatedly perform an action whilst the element is over those elements you'll need to implement your own logic.
To achieve this you can use an interval within the mouseenter handler of the hover() to repeatedly shift the scroll position of the required element. Then in the mouseleave you can clear that timer.
Also note that you can DRY up your code by using a common class on both elements along with a data attribute to govern the movement increment per tick of the interval. Try this:
var timer;
$('.hover-scroll').hover(function() {
var increment = $(this).data('pos');
timer = setInterval(function() {
var leftPos = $("#wrapper").scrollLeft();
$("#wrapper").animate({
scrollLeft: leftPos + increment
}, 1);
}, 50);
}, function() {
clearInterval(timer);
});
html,
body {
background-color: #eeeeee;
margin: 0;
overflow-x: scroll;
overflow-y: hidden;
}
#left {
position: absolute;
width: 10vw;
height: 100vh;
top: 0;
left: 0;
z-index: 1;
background-color: black;
}
#right {
position: absolute;
width: 10vw;
height: 100vh;
top: 0;
right: 0;
z-index: 1;
background-color: black;
}
#wrapper {
width: 100%;
height: 100vh;
white-space: nowrap;
overflow-y: hidden;
overflow-x: scroll;
}
#inner_wrap {
width: 4000px;
height: 100vh;
align-items: center;
display: flex;
}
#firstcontent {
align-items: center;
display: flex;
vertical-align: middle;
color: white;
float: left;
margin-left: 20vw;
width: 400px;
height: 250px;
background-color: #2d2d2d;
}
.thumbone {
width: 400px;
height: 250px;
background-color: lightgrey;
display: inline-block;
}
.thumbtwo {
width: 400px;
height: 250px;
background-color: grey;
display: inline-block;
}
<script src="https://corporate3.bdjobs.com/js/jquery.min.js"></script>
<div id="left" class="hover-scroll" data-pos="-50"></div>
<div id="right" class="hover-scroll" data-pos="50"></div>
<div id="wrapper">
<div id="inner_wrap">
<div id="firstcontent">hover or scroll</div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
<div class="thumbone"></div>
<div class="thumbtwo"></div>
</div>
</div>
If you want to speed up or slow down the scroll, change the delay on the interval

Related

How to scroll to next div with full page?

when it's clicked to smoothly scroll to next div
and Divs that take 100% height
but
I want to scroll to the next div instead of the "next" button
who can help me to edit this code?
pleas help guys to make my web site
$(".next").click(function() {
$('html,body').animate({
scrollTop: $(".p2").offset().top
},
'slow');
});
body {
margin: 0;
height: 100%;
}
.p1 {
height: 100vh;
width: 70%;
background-color: #2196F3;
}
.p2 {
height: 100vh;
width: 70%;
background-color: #E91E63;
}
.p3 {
height: 100vh;
width: 70%;
background-color: #01579B;
}
.admin {
background-color: #B71C1C;
height: 100vh;
position: fixed;
right: 0%;
top: 0%;
width: 30%;
float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="p1">
</div>
<div class="p2">
</div>
<div class="p3">
</div>
<div class="admin">
<button class="next">NEXT</button>
</div>
I think CSS's Scroll Snap feature can help you;
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap/Basic_concepts
https://caniuse.com/?search=scroll-snap
$(".next").click(function() {
$('html,body').animate({
scrollTop: $(".p2").offset().top
},
'slow');
});
body {
margin: 0;
}
.container {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
div[class*=p] {
scroll-snap-align: start;
}
.p1 {
height: 100vh;
width: 70%;
background-color: #2196F3;
}
.p2 {
height: 100vh;
width: 70%;
background-color: #E91E63;
}
.p3 {
height: 100vh;
width: 70%;
background-color: #01579B;
}
.admin {
background-color: #B71C1C;
height: 100vh;
position: fixed;
right: 0%;
top: 0%;
width: 30%;
float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="p1">
</div>
<div class="p2">
</div>
<div class="p3">
</div>
<div class="admin">
<button class="next">NEXT</button>
</div>
</div>

ScrollIntoView breaks the overflow scroll

I have a nested child container and when I'm trying to scrollIntoView it breaks the parent container. I'm not able to understand why it's acting like this. Please help me out in this.
Please have a look at the code below or on jsfiddle
function moveToTop() {
console.log('MOVE TO TOP::');
const child = document.getElementById('child');
child.scrollIntoView({
behavior: "smooth"
});
}
#parent {
background-color: blue;
padding: 10px;
height: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
}
#scroller {
overflow: auto;
padding: 10px;
background-color: red;
flex-grow: 1;
}
#child {
height: 10000px;
background-color: green;
}
body {
overflow: hidden;
color: #fff;
font-weight: bold;
}
button {
position: fixed;
bottom: 20px;
width: 140px;
left: 20%;
right: 0;
}
<div id="parent">
PARENT
<div id="something">Something</div>
<div id="scroller">
CHILD
<div id="child">
GRAND CHILD
<button onclick="moveToTop()">Top</button>
</div>
</div>
</div>
The whole problem is that scrollIntoView() is moving the window. But since the #parent overflow is hidden, when the window is moved, this element itself breaks. I could suggest setting a position: fixed for the #parent, which will solve your problem, but it can harm the layout in general.
Use the scroll() method. The scrolling mechanism itself is:
scroller.scroll(0, child.offsetTop - 55);
child.offsetTop - top element;
55 - distance from the top of the #parent to the top #scroller.
The transition animation must be set to css, in selector #scroller. Like that:
#scroller {
...
scroll-behavior: smooth;
}
function moveToTop() {
console.log('MOVE TO TOP::');
const child = document.getElementById('child');
const scroller = document.getElementById('scroller');
scroller.scroll(0, child.offsetTop - 55);
}
#parent {
background-color: blue;
padding: 10px;
height: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
}
#scroller {
overflow: auto;
padding: 10px;
background-color: red;
flex-grow: 1;
scroll-behavior: smooth;
}
#child {
height: 10000px;
background-color: green;
}
body {
overflow: hidden;
color: #fff;
font-weight: bold;
}
button {
position: fixed;
bottom: 20px;
width: 140px;
left: 20%;
right: 0;
}
<div id="parent">
PARENT
<div id="something">Something</div>
<div id="scroller">
CHILD
<div id="child">
GRAND CHILD
<button onclick="moveToTop()">Top</button>
</div>
</div>
</div>

Showing the div after scrolling down the website

I want to set the animation of the element while scrolling down the page. I want to use only JavaScript to achieve that.
I wanted it to work like this: There is no animation, but when you scroll down to second container, the JS sets the animation and the content inside the container is shown.
The problem is, when I load the page, there is no animation (That's good). When I scroll down, there is still no animation (That's bad!) but when I refresh the page with F5 while being on the bottom of the site, the animation shows up but still not showing my element with blue background.
Here is my full code for this part:
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.main {
display: block;
margin: auto;
height: 1000px;
width: 100%;
background-color: grey;
}
.main-inner1 {
display: block;
margin: auto;
height: 600px;
width: 100%;
background-color: orange;
}
.main-inner2 {
display: block;
margin: auto;
height: 600px;
width: 100%;
background-color: green;
}
.main-inner2-container {
display: block;
position: relative;
height: 50px;
width: 200px;
overflow: hidden;
margin: auto;
}
.main-inner2-content1 {
display: block;
position: absolute;
top: 100%;
margin: auto;
height: 50px;
width: 200px;
background-color: blue;
}
#keyframes FadeIn {
{ from: top: 100%; }
{ to: top: 0; }
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function(){
var y = window.scrollY;
var x = document.querySelector(".main-inner2-container").getBoundingClientRect().top;
if (y >= x) {
document.querySelector(".main-inner2-content1").style.animation = "FadeIn 1s linear 0s 1 forwards";
}
});
</script>
<body>
<div class="main">
<div class="main-inner1"></div>
<div class="main-inner2">
<div class="main-inner2-container">
<div class="main-inner2-content1">
</div>
</div>
</div>
</div>
I'm learning JS so it's important to me to not use any libraries :P
Thanks a lot
I modified your code a bit. You were listening for DOMContentLoaded event which is fired only once (after the DOM is completely loaded), instead of window scroll event.
window.onscroll = function() {
var y = window.scrollY;
var x = document.querySelector(".main-inner2-container").getBoundingClientRect().top;
if (y >= x) {
document.querySelector(".main-inner2-content1").style.animation = "FadeIn 1s linear 0s 1 forwards";
}
}
* {
margin: 0;
padding: 0;
}
.main {
display: block;
margin: auto;
height: 1000px;
width: 100%;
background-color: grey;
}
.main-inner1 {
display: block;
margin: auto;
height: 600px;
width: 100%;
background-color: orange;
}
.main-inner2 {
display: block;
margin: auto;
height: 600px;
width: 100%;
background-color: green;
}
.main-inner2-container {
display: block;
position: relative;
height: 50px;
width: 200px;
overflow: hidden;
margin: auto;
}
.main-inner2-content1 {
display: block;
position: absolute;
top: 100%;
margin: auto;
height: 50px;
width: 200px;
background-color: blue;
}
#keyframes FadeIn {
from { top: 100%; }
to {top: 0; }
}
<div class="main">
<div class="main-inner1"></div>
<div class="main-inner2">
<div class="main-inner2-container">
<div class="main-inner2-content1">
</div>
</div>
</div>
</div>
Also, your syntax for defining keyframe was incorrect. It is
#keyframes FadeIn {
from { top: 100%; }
to {top: 0; }
}
And not
#keyframes FadeIn {
{ from: top: 100%; }
{ to: top: 0; }
}

How to position text and Div on top of eachother and align them in center?

So I can't figure this out.
I'm trying to get a red vertical box to display in middle of page. I've set the div's margin to auto.
And then there's another div that holds a centered text.
Setting margin auto on both.
They are both stacking on top of eachother fine in middle of page.
However I want it to be responsive to all heights. Right now it's just responsive to the x-axis and not the height.
HTML & CSS:
.parentDiv {
position: relative;
width: 250px;
height: 450px;
margin: auto;
}
#RedBox {
width: 250px;
height: 450px;
background-color: #FF0000;
margin: auto;
}
#CSText {
position: absolute;
top: 45%;
width: 250px;
color: black;
text-align: center;
}
<div class="parentDiv" style="margin-top: auto;">
<div id="CSText" class="TextAlignCenter">
</div>
<div id="RedBox">
</div>
</div>
flexbox would be a great solution to this:
.container {
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.red-box {
background-color: red;
padding: 100px;
color: white;
}
<div class="container">
<div class="red-box">text</div>
</div>
I did this for you.
https://jsfiddle.net/95ssv6q1/
HTML
<div class="parentDiv">
<div class="inner">
<div id="RedBox">
</div>
</div>
</div>
CSS
.parentDiv {
display:table;
width: 100%;
height: 100%;
position: absolute;
}
.inner{
display: table-cell;
vertical-align:middle;
}
#RedBox {
width: 250px;
height: 450px;
background-color: #FF0000;
margin: auto;
}

Website with a tricky structure with JS

Here is my tricky problem. I'm trying to do this:
http://www.hostingpics.net/viewer.php?id=767312test.gif
(More clear than an explication I think).
My structure :
<header></header>
<div class="section">
<div class="text"></div>
<div class="content"></div>
<div class="img"><img src="img1.png"/></div>
</div>
<div class="section">
<div class="text"></div>
<div class="content"></div>
<div class="img"><img src="img2.png"/></div>
</div>
<div class="section">
<div class="text"></div>
<div class="content"></div>
<div class="img"><img src="img3.png"/></div>
</div>
<footer></footer>
Important informations :
"Header" is fix
"Content" fit to the screen less the height of header
Every "section" are the same but with different content
When the image comes to an end, the "content" div is unfixed.
I am using "section" for implementing a next and previous button in the header (with anchors).
My problem is the scrolling part. I am really lost when I try to fix the "content" div. I don't know how to fix everything except the scroll of the image in the active "img" div when the active "content" div hits the header. (Everyone follows? Look here : http://www.hostingpics.net/viewer.php?id=767312test.gif
For the scrolling part in the "img" div, I was thinking use a sort of "overflow:scroll" but the scrollbar is really awful.
I don't know if it's enough clear. If there is any problem I can complete my problem. I am not very comfortable with complex structures in html with JS.
Thanks for your help!
This is pretty close to what you're asking for (using CSS only).
This relies on the fact that the backgrounds are solid colors. It uses various specifically-defined height properties as well that match some padding properties.
The .top-bar and .bottom-bar elements can probably be changed to pseudo elements if you don't want the extra HTML.
HTML:
<header>Header</header>
<div class="top-bar"></div>
<div class="bottom-bar"></div>
<div class="section">
<div class="text">Section 1 Text</div>
<div class="content">
<div class="img"><img src="http://placekitten.com/100/1000"/></div>
</div>
</div>
<div class="section">
<div class="text">Section 2 Text</div>
<div class="content">
<div class="img"><img src="http://placekitten.com/200/2000"/></div>
</div>
</div>
<div class="section">
<div class="text">Section 3 Text</div>
<div class="content">
<div class="img"><img src="http://placekitten.com/300/3000"/></div>
</div>
</div>
<footer>Footer</footer>
CSS:
body {
margin: 0;
padding: 100px 0 0;
}
header {
background-color: red;
height: 100px;
position: fixed;
top: 0;
width: 100%;
z-index: 10;
}
footer {
background-color: blue;
height: 100px;
}
.section {
min-height: 400px;
}
.text {
background-color: aqua;
height: 50px;
}
.content {
background-color: green;
min-height: 100%;
padding: 40px 0;
position: relative;
}
.img {
background-color: yellow;
min-height: 70%;
margin: 0 auto;
padding: 40px 0;
text-align: center;
width: 80%;
}
.img > img {
vertical-align: middle;
}
.top-bar, .bottom-bar {
background-color: green;
height: 40px;
position: fixed;
width: 100%;
z-index: 5;
}
.top-bar {
top: 100px;
}
.bottom-bar {
bottom: 0;
}
footer, .text {
position: relative;
z-index: 6;
}
JSFiddle here.
For an almost completely correct solution, here is one with some jQuery involved.
New CSS:
body {
margin: 0;
padding: 100px 0 0;
}
header {
background-color: red;
height: 100px;
position: fixed;
top: 0;
width: 100%;
z-index: 10;
}
footer {
background-color: blue;
height: 100px;
}
.section {
min-height: 400px;
}
.text {
background-color: aqua;
height: 50px;
}
.content {
background-color: green;
min-height: 100%;
padding: 40px 0;
position: relative;
}
.img {
background-color: yellow;
min-height: 70%;
margin: 0 auto;
padding: 40px 0;
text-align: center;
width: 80%;
}
.img > img {
vertical-align: middle;
}
.top-bar, .bottom-bar {
background-color: green;
height: 40px;
position: fixed;
width: 100%;
}
.top-bar {
top: 100px;
z-index: 5;
}
.bottom-bar {
bottom: 0;
z-index: 7;
}
footer, .text {
position: relative;
z-index: 8;
}
.img-fix {
bottom: 40px;
height: 400px;
overflow: hidden;
position: absolute;
width: 100%;
z-index: 6;
}
jQuery:
$(document).ready(function(){
$(".content").each(function(){
$(this).append($(this).html());
$(this).find(".img + .img").wrap("<div class='img-fix'></div>");
});
$(window).resize(function() {
resizeImgFix();
});
resizeImgFix();
});
function resizeImgFix() {
$(".img-fix").height($(window).height() - $("header").height() - $(".top-bar").height() - $(".bottom-bar").height());
$(".img-fix").each(function(){
$(this).scrollTop($(this).prop("scrollHeight"));
});
}
JSFiddle here.
Note: It duplicates the .img element and its children. This could be memory intensive depending. However, it does make it work as intended without any visual lag or artifacts.

Categories

Resources