So i am trying to build a scroll indicator using 3 div elements. All code (meaning the 3 div HTML,CSS,JS) seems to work by itself in codepen.io but when i am using Atom with the rest or my project it seems to stop working.
I tried putting the 3 div's first before everything else. All the way to the end. Using other divs as parents but nothing seems to work.
window.onscroll = function() {myFunction()};
function myFunction() {
var winScroll = document.body.scrollTop ||
document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight -
document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 100;
document.getElementById("myBar").style.height = scrolled + "%";
}
*{
padding: 0;
margin: 0
}
/* Global Stylings */
/* ID and Class Stylings */
#containter {
width: 100%;
height: 100vh;
scroll-behavior: smooth;
overflow: auto;
scroll-snap-type: y mandatory;
}
#Landing{
display: flex;
justify-content: space-around;
align-items: center;
background-color: ;
width: 100%;
height: 100vh;
}
#projects {
background-color: ;
width: 100%;
height: 100vh;
}
#gallery {
background-color: ;
width: 100%;
height: 100vh;
}
#logo{
width: 30em;
height: 30em;
}
.scroll {
scroll-snap-align: start;
}
.scrollindicator {
position: fixed;
top: 0;
z-index: -1;
width: 100%;
height: 100%;
background-color: #f1f1f1;
}
.progress-container {
width: 8px;
height: 100%;
background: #ccc;
}
/* The progress bar (scroll indicator) */
.progress-bar {
height: 0%;
background: #4caf50;
width: 8px;
<div id="containter" class="snap">
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
</div>
<div id="Landing" class="scroll">
<img id="logo" src="AC-Logo.png" alt="Logo">
</div>
<div id="projects" class="scroll">
</div>
<div id="gallery" class="scroll">
</div>
</div>
<script src="scroll.js">
</script>
</body>
The div ID= myBar should show a progress of scrolling throughout the whole page and should be visible at all times.
Your css styling was wrong. Check out the snippet!
window.onscroll = function() {myFunction()};
function myFunction() {
var winScroll = document.body.scrollTop ||
document.documentElement.scrollTop;
var height = document.documentElement.scrollHeight -
document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 100;
document.getElementById("myBar").style.height = scrolled + "%";
}
*{
padding: 0;
margin: 0
}
/* Global Stylings */
/* ID and Class Stylings */
#containter {
width: 100%;
height: 100vh;
scroll-behavior: smooth;
overflow: auto;
scroll-snap-type: y mandatory;
position: fixed; // Make the bar stick to the left of the screen
}
#Landing{
display: flex;
justify-content: space-around;
align-items: center;
background-color: ;
width: 100%;
height: 100vh;
}
#projects {
background-color: ;
width: 100%;
height: 100vh;
}
#gallery {
background-color: ;
width: 100%;
height: 100vh;
}
#logo{
width: 30em;
height: 30em;
}
.scroll {
scroll-snap-align: start;
}
.scrollindicator {
top: 0;
z-index: -1;
width: 100%;
height: 100%;
background-color: #f1f1f1;
}
.progress-container {
width: 8px;
height: 100%;
position: fixed;
}
/* The progress bar (scroll indicator) */
.progress-bar {
height: 0%;
background: #ccc; // Set color to the actual bar that changes height
width: 8px;
<div id="containter" class="snap">
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
</div>
<div id="Landing" class="scroll">
<img id="logo" src="AC-Logo.png" alt="Logo">
</div>
<div id="projects" class="scroll">
</div>
<div id="gallery" class="scroll">
</div>
<script src="scroll.js">
</script>
Add position: fixed to your class progress-container .
Edit : scroll-snap-type wasn't working because your elements weren't included in the container having the property scroll-snap-type: y mandatory; . So I added everything in 'containter', making that css property work again.
Had to change a bit your Javascript so the custom scrollbar should work again.
function myFunction() {
var elem = document.getElementById('containter');
var winScroll = elem.scrollTop;
var height = elem.scrollHeight - document.documentElement.clientHeight;
var scrolled = (winScroll / height) * 100;
document.getElementById("myBar").style.height = scrolled + "%";
}
*{
padding: 0;
margin: 0
}
/* Global Stylings */
/* ID and Class Stylings */
#containter {
width: 100%;
height: 100vh;
scroll-behavior: smooth;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
#Landing{
display: flex;
justify-content: space-around;
align-items: center;
background-color: red;
width: 100%;
height: 100vh;
}
#projects {
background-color: blue;
width: 100%;
height: 100vh;
}
#gallery {
background-color: pink;
width: 100%;
height: 100vh;
}
#logo{
width: 30em;
height: 30em;
}
.scroll {
scroll-snap-align: start;
}
.scrollindicator {
position: fixed;
top: 0;
z-index: -1;
width: 100%;
height: 100%;
background-color: #f1f1f1;
}
.progress-container {
width: 8px;
height: 100%;
background: #ccc;
position: fixed;
}
/* The progress bar (scroll indicator) */
.progress-bar {
height: 0%;
background: #4caf50;
width: 8px;
}
<body>
<div onscroll="myFunction()" id="containter" class="snap">
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
<div id="Landing" class="scroll">
<img id="logo" src="AC-Logo.png" alt="Logo">
</div>
<div id="projects" class="scroll"></div>
<div id="gallery" class="scroll"></div>
</div>
<script src="scroll.js"></script>
</body>
Related
I'm trying to learn how to use the parallax effect using simple JavaScript and CSS.
my JavaScript is :
window.addEventListener('scroll', function(){
document.getElementById("second").style.left = window.scrollY + 'px';
document.getElementById("third").style.left = window.scrollY + 'px';
})
from my understanding of things, it should make the element called third and second scroll left by the same value as the vertical scroll. But it doesn't work and I can't find what's the problem here.
My whole code is:
* {
scroll-behavior: smooth;
}
body {
size: 100%;
margin-top: 0px;
margin-left: 0px;
}
section {
position: relative;
width: 100%;
height: 100vh;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
section::before {
content: '';
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background-image: linear-gradient(to bottom right, #350529, #45392c);
z-index: 100;
}
section img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
section img#sixth {
z-index: 10;
}
#text {
position: absolute;
color: white;
white-space: nowrap;
font-size: 7.5vw;
z-index: 9;
}
<section>
<img src="Plan-parallax-1.png" id="first">
<img src="Plan-parallax-2.png" id="second">
<img src="Plan-parallax-3.png" id="third">
<img src="Plan-parallax-4.png" id="fourth">
<img src="Plan-parallax-5.png" id="fifth">
<h2 id="text">Monde parallele</h2>
<img src="Plan-parallax-6.png" id="sixth">
</section>
<script>
window.addEventListener('scroll', function() {
document.getElementById("second").style.left = window.scrollY + 'px';
document.getElementById("third").style.left = window.scrollY + 'px';
})
</script>
If your code is simplified down to just focus on the question of moving an element based on scroll, it works fine. Example included
window.addEventListener('scroll', function() {
document.getElementById("second").style.left = window.scrollY + 'px';
})
* {
scroll-behavior: smooth;
}
section {
position: relative;
width: 100%;
height: 100vh;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
section::before {
content: '';
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background-image: linear-gradient(to bottom right, #350529, #45392c);
z-index: 100;
}
section img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
<!DOCTYPE html>
<html>
<body style="size: 100%; margin-top: 0px; margin-left: 0px;">
<section>
<img src="https://picsum.photos/600" id="second">
</section>
</body>
</html>
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; }
}
My idea is to get the child object (#example the ".moon") to have the equal values of height and width, and not exceed the width or the height of the parent (#example the ".sun").
So when the parent width is bigger than its height, the child's value for width and height is the smaller one, the parent height.
In the same way when the parent height is bigger than its width, the child's value for width and height is the smaller one, the parent width.
I mean inscribe an object inside the container but only using CSS.
The "padding-top" trick only works when the parent width is bigger than its height. And the "object-fit" only work for images I guess.
I did reference the circles, just to make it clear that the sides have to have the same value (height and width), also that the child can contain elements.
I know it can be perfectly done with JavaScript getting the parent height and width, comparing the smaller one and set it to the child height and width, I made it with jQuery, but wanna know if its possible to achieve it without jQuery or JavaScript, pure CSS.
Try the example and resizing the screen.
var pw = ""; var ph = ""; var cw = ""; var ch = "";
$( window ).resize(function() {
pw = $('.sun').width();
ph = $('.sun').height();
cw = $('.moon').width();
ch = $('.moon').height();
if(pw > ph){
$('.moon').css({
'width': ph + 'px',
'height': ph + 'px'
});
}
else {
$('.moon').css({
'width': pw + 'px',
'height': pw + 'px'
});
}
});
function mySUNction() {
pw = $('.sun').width();
ph = $('.sun').height();
cw = $('.moon').width();
ch = $('.moon').height();
if(pw > ph){
$('.moon').css({
'width': ph + 'px',
'height': ph + 'px'
});
}
else {
$('.moon').css({
'width': pw + 'px',
'height': pw + 'px'
});
}
}
* {
padding: 0;
margin:0;
}
.sky {
position: absolute;
width: 100%;
height: 100%;
background: purple;
display: flex;
justify-content: center;
align-items: center;
}
.sun {
position: relative;
width: 33%;
/*padding-top: 33%;*/
height: 33%;
background: yellow;
display: flex;
justify-content: center;
align-items: center;
}
.moon {
background: blue;
/*object-fit: fill;*/
/*border-radius: 50%;*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<div class="sky">
<div class="sun">
<div class="moon"></div>
</div>
<div>
<button onclick="mySUNction()">Click me</button>
If you only want the visual, it can be done with gradient:
body {
margin:0;
}
.sky {
height: 100vh;
background: purple;
display: flex;
justify-content: center;
align-items: center;
}
.sun {
position: relative;
width: 33%;
height: 33%;
background:
radial-gradient(circle closest-side,blue 99%,transparent 100%)
yellow;
}
<div class="sky">
<div class="sun">
</div>
</div>
The same logic you apply with a mask and you can use any background:
body {
margin:0;
}
.sky {
height: 100vh;
background: purple;
display: flex;
justify-content: center;
align-items: center;
}
.sun {
position: relative;
width: 33%;
height: 33%;
background:
yellow;
}
.sun > div {
width:100%;
height:100%;
background:url(https://picsum.photos/id/1074/800/800) center/contain;
-webkit-mask:radial-gradient(circle closest-side,blue 99%,transparent 100%);
mask:radial-gradient(circle closest-side,blue 99%,transparent 100%);
}
<div class="sky">
<div class="sun">
<div></div>
</div>
</div>
You can also consider the use of min()/max() like below
body {
margin:0;
}
.sky {
height: 100vh;
background: purple;
display: flex;
justify-content: center;
align-items: center;
}
.sun {
position: relative;
width: 33vw;
height: 33vh;
background: yellow;
display: flex;
}
.sun > div {
margin:auto;
height:min(100%,33vw);
width:min(100%,33vh);
background:url(https://picsum.photos/id/1074/800/800) center/contain;
}
<div class="sky">
<div class="sun">
<div></div>
</div>
</div>
Also like below:
body {
margin:0;
}
.sky {
height: 100vh;
background: purple;
display: flex;
justify-content: center;
align-items: center;
}
.sun {
position: relative;
width: 33vw;
height: 33vh;
background: yellow;
display: flex;
}
.sun > div {
margin:auto;
display: flex;
width:min(100%,33vh);
background:url(https://picsum.photos/id/1074/800/800) center/contain;
}
.sun > div::before {
content:"";
padding-top:100%;
}
<div class="sky">
<div class="sun">
<div></div>
</div>
</div>
Related question if you want the circumscribed circle: Make a perfect circle around a div of variable height
You can use 33vh (it should match the number with .sun's height) for child width. See the CSS for .moon element.
* {
padding: 0;
margin:0;
}
.sky {
position: absolute;
width: 100%;
height: 100%;
background: purple;
display: flex;
justify-content: center;
align-items: center;
}
.sun {
position: relative;
width: 33%;
/*padding-top: 33%;*/
height: 33%;
background: yellow;
display: flex;
justify-content: center;
align-items: center;
}
.moon {
background: blue;
/*object-fit: fill;*/
border-radius: 50%;
height:min(33vh, 33vw);
width: min(33vh, 33vw);
}
<div class="sky">
<div class="sun">
<div class="moon"></div>
</div>
</div>
You can see it here also..
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
I need to set up a video width/height accordingly to its container.
Basically the video should have height 100% of its green container and the width should be variable.
plyr.setup();
body {
margin: 0;
}
.plyr {
height: 100%;
width :100%;
}
#wrapper{
display: flex;
justify-content:center;
width: 900px;
height: 500px;
background-color: green;
}
<script src="https://cdn.plyr.io/2.0.11/plyr.js"></script>
<div id="wrapper">
<div>
<div data-type="youtube" data-video-id="5p-Jdjo7sSQ"></div>
</div>
</div>
You can try this solution :
add other class for player's generated html.
plyr.setup();
body {
margin: 0;
}
.plyr {
height: 100%;
width :100%;
}
#wrapper{
display: flex;
justify-content:center;
width: 900px;
height: 500px;
background-color: green;
}
.plyr__video-wrapper {
height: 100%;
}
.plyr__video-wrapper iframe {
width: 100%;
height: 100%;
}
<script src="https://cdn.plyr.io/2.0.11/plyr.js"></script>
<div id="wrapper">
<div data-type="youtube" data-video-id="5p-Jdjo7sSQ"></div>
</div>
Then your height/width percents will actually perfectly work.
Under #wrapper, if you remove
display: flex;
Then your height/width percents will actually work. Then you can change the width to however you'd like in your JS.
Try this. Fiddle
body {
margin: 0;
}
.plyr {
height: 100%;
width :100%;
}
#wrapper{
display: flex;
justify-content:center;
width: 100%;
background-color: green;
}
.plyr__video-wrapper {
position: relative;
padding-bottom: 56.25%;
}
.plyr__video-wrapper iframe {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
}