addClass and removeClass trigger with Waypoints - html

I am making a website that is horizontal parallax scroller. My intention is to have environmetal effect from dawn to night by moving gradient (div 100vw, 300vh) up and down while changing opacity. I want javascript to trigger desired action when a certain div comes to viewport.
I am using jquery, Waypoints and jInvertScroll.
I get this from console:
<div class="dawndusk"></div> when everything is in the beginning. <div class="dawndusk lettherebenight"></div> when I scroll to #dawn. And nothing changes when I scroll to other divs. Why?
This is my HTML
<div class="dawndusk"></div>
<div class="flex" id="birth">
...content...
</div>
<div class="flex" id="dawn">
...content...
</div>
<div class="flex" id="day">
...content...
</div>
<div class="flex" id="dusk">
...content...
</div>
<div class="flex" id="night">
...content...
</div>
This is my CSS
.dawndusk {
z-index:750;
opacity: .9;
background: #4B79A1;
background: -webkit-linear-gradient(to top, #f6d365 0%, #fda085 50%, #283E51 50%, #0A2342 100%);
background: -olinear-gradient(to top, #f6d365 0%, #fda085 50%, #283E51 50%, #0A2342 100%);
background: linear-gradient(to top, #f6d365 0%, #fda085 30%, #283E51 60%, #0A2342 100%);
width:100vw;
height:300vh;
position:fixed;
}
#birth,
#dawn,
#day,
#dusk,
#night {
position: absolute;
top:0;
}
#birth {
left:0;
}
#dawn {
left:100vw;
}
#day {
left:200vw;
}
#dusk {
left:300vw;
}
#night {
left:400vw;
}
.lettherebebirth,
.lettherebedawn,
.lettherebeday,
.lettherebedusk,
.lettherebenight {
transition: all 4s;
-webkit-transition: all 4s;
}
.lettherebebirth {
opacity: .9;
transform: translateY(0);
}
.lettherebedawn {
opacity: .2;
transform: translateY(-200vh);
}
.lettherebeday {
opacity: 0;
transform: translateY(0);
}
.lettherebedusk {
opacity: .5;
transform: translateY(-200vh);
}
.lettherebenight {
opacity: .8;
transform: translateY(-200vh);
}
Javascript is like this:
$('#birth').waypoint(function(direction) {
if (direction === 'up') {
$('.dawndusk').removeClass('lettherebedawn');
$('.dawndusk').addClass('lettherebebirth');
}
});
$('#dawn').waypoint(function(direction) {
if (direction === 'down') {
$('.dawndusk').removeClass('lettherebebirth');
$('.dawndusk').addClass('lettherebedawn');
}
});
$('#day').waypoint(function(direction) {
if (direction === 'down') {
$('.dawndusk').removeClass('lettherebedawn');
$('.dawndusk').addClass('lettherebeday');
}
});
$('#dusk').waypoint(function(direction) {
if (direction === 'down') {
$('.dawndusk').removeClass('lettherebeday');
$('.dawndusk').addClass('lettherebedusk');
}
});
$('#night').waypoint(function(direction) {
if (direction === 'down') {
$('.dawndusk').removeClass('lettherebedusk');
$('.dawndusk').addClass('lettherebenight');
}
});
How do I get the wanted classes to trigger on and off when I want to?

I figured it out myself.
jInvertscroll mimics horizontal scrolling on vertical scrolls behalf. So though everything seemed ok on screen and on code, the problem was that waypoints triggers were all placed on horizontal axis. It was supposed be on vertical axis.
#birth {
top:0;
}
#dawn {
top:100vw;
}
#day {
top:200vw;
}
#dusk {
top:300vw;
}
#night {
top:400vw;
}

Related

Is there a way to fade two div elements into one another in CSS?

If I have two div elements that contain some text and I want them into one another such that as one disappears the other appears and it then repeats how do i go about doing this? I'm not sure where to where to start.
<div id="body">
<div>My great adventure</div>
<div>Travel, adventure, leisure</div>
</div>
Using CSS animations we can achieve this pretty simply.
We will create 2 animations. One that causes the text to fade in initially, and one to cause the text to fade out initially. We will set these animations to loop forever.
You can fine tune the timings and opacity levels to your needs.
.fade {
position: absolute;
}
#start {
opacity: 1;
animation-name: fadeStart;
animation-duration: 4s;
animation-iteration-count: infinite;
}
#end {
opacity: 0;
animation-name: fadeEnd;
animation-duration: 4s;
animation-iteration-count: infinite;
}
#keyframes fadeStart {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes fadeEnd {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
<div id="container">
<div class="fade" id="start">My great adventure</div>
<div class="fade" id="end">Travel, adventure, leisure</div>
</div>
If you are just talking about non-animated, static elements visually fading into one another, you can use a linear-gradient for the background of ::before and ::after pseudo-elements.
Below is a pure CSS example making use of CSS variables for consistent colors and sizing. The ::before and ::after pseudo-elements fade from the background color to transparent. You can increase the multiplier in margin on the #body > div to decrease the amount of overlap.
body {
--div-bg: orange;
--fade-height: 3rem;
background: white;
}
#body>div {
position: relative;
color: black;
background: var(--div-bg);
padding: 1rem;
margin: calc(var(--fade-height) * 1) 0 0;
}
#body>div::before,
#body>div::after {
content: "";
position: absolute;
left: 0;
right: 0;
height: var(--fade-height);
}
#body>div::after {
bottom: calc(var(--fade-height) * -1);
background: linear-gradient(to bottom, var(--div-bg), transparent);
}
#body>div::before {
top: calc(var(--fade-height) * -1);
background: linear-gradient(to top, var(--div-bg), transparent);
}
<div id="body">
<div>My great adventure</div>
<div style="--div-bg: #33F;">Travel, adventure, leisure</div>
</div>

Why my animation doesnt work on different browsers?

I am currently developing website on Html & CSS & JS.
I cant make my animation work for some reasons. I mean, they work on Google Chrome but not on Mozilla. Here is some code from my CSS file.
<style>
.fullBackground {
background-color: rgba(0,0,0,0.5); /* Tint color */
background-blend-mode: multiply;
background-position: center center;
background-repeat: no-repeat;
background-attachment: fixed;
background-size: cover;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
animation: slideBg 25s linear infinite;
background-image: url("/assets/slideshowImages/1.jpg");
}
#keyframes slideBg {
0% {
background-image: url("/assets/slideshowImages/1.jpg");
}
5% {
background-image: url("/assets/slideshowImages/1.jpg");
}
10% {
background-image: url("/assets/slideshowImages/1.jpg");
}
15% {
background-image: url("/assets/slideshowImages/1.jpg");
}
20% {
background-image: url("/assets/slideshowImages/1.jpg");
}
25% {
background-image: url("/assets/slideshowImages/2.jpg");
}
30% {
background-image: url("/assets/slideshowImages/2.jpg");
}
35% {
background-image: url("/assets/slideshowImages/2.jpg");
}
40% {
background-image: url("/assets/slideshowImages/2.jpg");
}
45% {
background-image: url("/assets/slideshowImages/2.jpg");
}
50% {
background-image: url("/assets/slideshowImages/3.jpg");
}
55% {
background-image: url("/assets/slideshowImages/3.jpg");
}
60% {
background-image: url("/assets/slideshowImages/3.jpg");
}
65% {
background-image: url("/assets/slideshowImages/3.jpg");
}
70% {
background-image: url("/assets/slideshowImages/3.jpg");
}
75% {
background-image: url("/assets/slideshowImages/4.jpg");
}80% {
background-image: url("/assets/slideshowImages/4.jpg");
}85% {
background-image: url("/assets/slideshowImages/4.jpg");
}90% {
background-image: url("/assets/slideshowImages/4.jpg");
}
100% {
background-image: url("/assets/slideshowImages/4.jpg");
}
}
</style>
And here is how I use it in HTML
<div class="fullBackground"></div>
I would be very very glad to you, if you might give me any clue.
Thank you in advance!
As you have said you are using html, css and js for your website, so I would suggest using javascript for consistent results across all browsers.
I don't have a good knowledge of javascript so for transition I am using javascript form w3.schools.com
var myIndex = 0;
carousel();
function carousel() {
var i;
var x = document.getElementsByClassName("slides");
// The images for transition are selected by the class name of "slides"
//so whichever image has the class name of slides will get picked by this javascript code for the slideshow animation.
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
myIndex++;
if (myIndex > x.length) {
myIndex = 1
}
x[myIndex - 1].style.display = "block";
setTimeout(carousel, 4000); // Here 4000 is the time in millisecond fot an image to transition from one to another.
}
.slides {
width: 30rem;
height: 20rem;
}
.fading {
animation: fading 4s infinite /* 4s defines how much time does 1 image takes for fading in and fading out */
}
/* Here the image fades in form opacity 0 to 1 from the 0% time 25% time */
#keyframes fading {
0% {
opacity: 0
}
25% {
opacity: 1
}
75% {
opacity: 1
}
100% {
opacity: 0
}
}
/* The image stays of opacity 1 for the duration of 2s as 25% to 75% of 4s is 2s. */
<img class="slides fading" src="https://picsum.photos/id/10/200/300">
<img class="slides fading" src="https://picsum.photos/id/11/200/300">
<img class="slides fading" src="https://picsum.photos/id/13/200/300">
<img class="slides fading" src="https://picsum.photos/id/16/200/300">
There are comments in the code explaining which element you need to change to get different outcomes.
One thing to keep in mind is if you change the fading animation duration from 4s to any other value you will have to change the timeout value 4000ms in javascript.

how to animate the display property in css or an alternative, without using javascript

so i am making an advertisement, which has animations using css only(this is a requirement for the project). The problem is that I am not able to remove the elements from the screen because the display property is not animatable. I want to remove the elements from the screen because there needs to be a complete scene change 2 times, hence there will be 3 scenes. Old elements need to go away and new elements need to be shown , in a fraction of a second.
I have reached the following state using no javascript but i dont know how to make the 2 images disappear and make space for the next elements of text divs.
https://jsfiddle.net/br93px4z/1/
changes are that javascript has been completely removed
and the following css has been edited :
#keyframes scale{
0%{transform: scale(0.2);}
99.9%{transform: scale(2.3);left:280px;top:40px;}
100%{transform: scale(0.0000001);left: -4000px;top: -4000px;}
}
#keyframes topToBottom{
0%{transform: translateY(-100px);}
80%{transform: translateX(700px) translateY(100px) scale(2);left: -248px;
top: -62px;}
99%{transform: translateX(700px) translateY(100px) scale(2);left: -248px;
top: -62px;}
100%{transform: scale(0.0000001);left: -4000px;top: -4000px;}
}
here is what i want to achieve but it is achieved using javascript:
https://jsfiddle.net/t6ackzeb/4/
important javascript used(just for reading ):
logo.addEventListener("webkitAnimationEnd", postAnimation1);
logo.addEventListener("animationend", postAnimation1);
function postAnimation1() {
logo.style.display = "none";
part1.style.backgroundColor = "#d6a333";
part1.style.backgroundImage = "none";
txtAdventure.style.display="block";
}
txtAdventure.addEventListener("animationend", postAnimation2);
function postAnimation2() {
img1.style.display = "none";
img2.style.display = "none";
txtAdventure.style.display="none";
part1.style.backgroundImage="url('https://i.imgur.com/KsS80IE.png')"
txt1.style.display = "block";
txt2.style.display = "block";
txt3.style.display = "block";
endLogo.style.display = "block";
}
````````````````````````
So is there an an alternative to achieving the same results as display:none; but without using javascript ?
thank you
Found the solution thanks to https://stackoverflow.com/users/9166287/adnan-toky :
here:
https://jsfiddle.net/mnpsavkq/16/
Try the following code sample.
CSS:
.animatedDiv {
height:100px;
width:100px;
float: left;
margin:5px;
}
.d1 {
animation:hide1 10s linear 10;
background:red;
}
.d2 {
animation:hide2 10s linear 10;
background:green;
}
.d3 {
animation:hide3 10s linear 10;
background:blue;
}
#keyframes hide1{
0% {
opacity:1;
height:100px;
width:100px;
}
33% {
opacity:0;
height: 100px;
width:100px;
}
34% {
width: 0;
height: 0;
}
100% {
opacity:0;
height:0;
width:0;
}
}
#keyframes hide2{
0% {
opacity:1;
height:100px;
width:100px;
}
33% {
opacity:1;
}
66% {
opacity:0;
height: 100px;
width:100px;
}
67% {
width: 0;
height: 0;
}
100% {
opacity:0;
height:0;
width:0;
}
}
#keyframes hide3{
0% {
opacity:1;
height:100px;
width:100px;
}
66% {
opacity:1;
}
99% {
opacity:0;
height: 100px;
width:100px;
}
100% {
width: 0;
height: 0;
}
}
HTML:
<div class="animatedDiv d1"></div>
<div class="animatedDiv d2"></div>
<div class="animatedDiv d3"></div>

Crossfading the background-image of a single element without script

I want to switch background image of the body periodically, cross fading between each image.
A script solution would look like this:
css:
body
{
background-image: url("img/1.jpg");
background-size: cover;
background-position: center 0;
background-attachment: fixed;
transition: background-image 2s ease-in-out;
}
js:
var images = ["1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg"];
var current_image = 0;
$(function ()
{
var body = $("body");
setTimeout(next, 10000);
function next()
{
current_image = (current_image + 1) % images.length;
body.css("background-image", "url('img/" + images[current_image] + "')");
setTimeout(next, 10000);
}
});
But is it possible to cross fade the background of a single element (as opposed to change opacities of a number of img elements) using no scripting?
Yeah you could do it with css animations.
something like this.
* { box-sizing: border-box}
.slides {
width: 300px;
height: 300px;
background: tomato;
animation: images 4s linear 0s infinite alternate;
}
#keyframes images {
0% {
background: url('https://fillmurray.com/300/300')
}
50% {
background: url('http://www.placecage.com/c/300/300');
}
100% {
background: url('https://stevensegallery.com/300/300')
}
}
<div class="slides"></div>
I post this as an answer to my own question even if there is a solution that I accepted. What this will add is how to stay for a while on the same image without immediately transitioning to the next.
body {
background-size: cover;
background-position: center 0;
background-attachment: fixed;
animation: images 100s linear 0s infinite;
}
#keyframes images {
0% {
background-image: url("img/1.jpg")
}
19% {
background-image: url("img/1.jpg")
}
20% {
background-image: url("img/2.jpg");
}
39% {
background-image: url("img/2.jpg");
}
40% {
background-image: url("img/3.jpg");
}
59% {
background-image: url("img/3.jpg");
}
60% {
background-image: url("img/4.jpg");
}
79% {
background-image: url("img/4.jpg");
}
80% {
background-image: url("img/5.jpg");
}
99% {
background-image: url("img/5.jpg");
}
100% {
background-image: url("img/1.jpg")
}
}
I tried to group some percentages like
0%, 19%, 100% {
background-image: url("img/1.jpg");
}
but that resulted in "flickering" between images.

CSS animation in different browsers [duplicate]

Why this isn't working? What am I doing wrong?
CSS
#-webkit-keyframes test {
0% {
background-image: url('frame-01.png');
}
20% {
background-image: url('frame-02.png');
}
40% {
background-image: url('frame-03.png');
}
60% {
background-image: url('frame-04.png');
}
80% {
background-image: url('frame-05.png');
}
100% {
background-image: url('frame-06.png');
}
}
div {
float: left;
width: 200px;
height: 200px;
-webkit-animation-name: test;
-webkit-animation-duration: 10s;
-webkit-animation-iteration-count: 2;
-webkit-animation-direction: alternate;
-webkit-animation-timing-function: linear;
}
DEMO
http://jsfiddle.net/hAGKv/
Updated for 2020: Yes, it can be done! Here's how.
Snippet demo:
#mydiv{ animation: changeBg 1s infinite; width:143px; height:100px; }
#keyframes changeBg{
0%,100% {background-image: url("https://i.stack.imgur.com/YdrqG.png");}
25% {background-image: url("https://i.stack.imgur.com/2wKWi.png");}
50% {background-image: url("https://i.stack.imgur.com/HobHO.png");}
75% {background-image: url("https://i.stack.imgur.com/3hiHO.png");}
}
<div id='mydiv'></div>
Background image [isn't a property that can be animated][1] - you can't tween the property.
Original Answer: (still a good alternative)
Instead, try laying out all the images on top of each other using position:absolute, then animate the opacity of all of them to 0 except the one you want repeatedly.
It works in Chrome 19.0.1084.41 beta!
So at some point in the future, keyframes could really be... frames!
You are living in the future ;)
Works for me.
Notice the use of background-image for transition.
#poster-img {
background-repeat: no-repeat;
background-position: center;
position: absolute;
overflow: hidden;
-webkit-transition: background-image 1s ease-in-out;
transition: background-image 1s ease-in-out;
}
This is really fast and dirty, but it gets the job done: jsFiddle
#img1, #img2, #img3, #img4 {
width:100%;
height:100%;
position:fixed;
z-index:-1;
animation-name: test;
animation-duration: 5s;
opacity:0;
}
#img2 {
animation-delay:5s;
-webkit-animation-delay:5s
}
#img3 {
animation-delay:10s;
-webkit-animation-delay:10s
}
#img4 {
animation-delay:15s;
-webkit-animation-delay:15s
}
#-webkit-keyframes test {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
}
}
#keyframes test {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
}
}
I'm working on something similar for my site using jQuery, but the transition is triggered when the user scrolls down the page - jsFiddle
I needed to do the same thing as you and landed on your question. I ended up taking finding about the steps function which I read about from here.
JSFiddle of my solution in action (Note it currently works in Firefox, I'll let you add the crossbrowser lines, trying to keep the solution clean of clutter)
First I created a sprite sheet that had two frames. Then I created the div and put that as the background, but my div is only the size of my sprite (100px).
<div id="cyclist"></div>
#cyclist {
animation: cyclist 1s infinite steps(2);
display: block;
width: 100px;
height: 100px;
background-image: url('../images/cyclist-test.png');
background-repeat: no-repeat;
background-position: top left;
}
The animation is set to have 2 steps and have the whole process take 1 second.
#keyframes cyclist {
0% {
background-position: 0 0;
}
100% {
background-position: 0 -202px; //this should be cleaned up, my sprite sheet is 202px by accident, it should be 200px
}
}
Thiago above mentioned the steps function but I thought I'd elaborate more on it. Pretty simple and awesome stuff.
Your code can work well with some adaptations :
div {
background-position: 50% 100%;
background-repeat: no-repeat;
background-size: contain;
animation: animateSectionBackground infinite 240s;
}
#keyframes animateSectionBackground {
00%, 11% { background-image: url(/assets/images/bg-1.jpg); }
12%, 24% { background-image: url(/assets/images/bg-2.jpg); }
25%, 36% { background-image: url(/assets/images/bg-3.jpg); }
37%, 49% { background-image: url(/assets/images/bg-4.jpg); }
50%, 61% { background-image: url(/assets/images/bg-5.jpg); }
62%, 74% { background-image: url(/assets/images/bg-6.jpg); }
75%, 86% { background-image: url(/assets/images/bg-7.jpg); }
87%, 99% { background-image: url(/assets/images/bg-8.jpg); }
}
Here is the explanation of the percentage to suit your situation:
First you need to calculate the "chunks". If you had 8 differents background, you need to do :
100% / 8 = 12.5% (to simplify you can let fall the decimals) => 12%
After that you obtain that :
#keyframes animateSectionBackground {
00% { background-image: url(/assets/images/bg-1.jpg); }
12% { background-image: url(/assets/images/bg-2.jpg); }
25% { background-image: url(/assets/images/bg-3.jpg); }
37% { background-image: url(/assets/images/bg-4.jpg); }
50% { background-image: url(/assets/images/bg-5.jpg); }
62% { background-image: url(/assets/images/bg-6.jpg); }
75% { background-image: url(/assets/images/bg-7.jpg); }
87% { background-image: url(/assets/images/bg-8.jpg); }
}
If you execute this code, you will see the transition will be permanantly. If you want the backgrounds stay fixed while a moment, you can do like this :
#keyframes animateSectionBackground {
00%, 11% { background-image: url(/assets/images/bg-1.jpg); }
12%, 24% { background-image: url(/assets/images/bg-2.jpg); }
25%, 36% { background-image: url(/assets/images/bg-3.jpg); }
37%, 49% { background-image: url(/assets/images/bg-4.jpg); }
50%, 61% { background-image: url(/assets/images/bg-5.jpg); }
62%, 74% { background-image: url(/assets/images/bg-6.jpg); }
75%, 86% { background-image: url(/assets/images/bg-7.jpg); }
87%, 99% { background-image: url(/assets/images/bg-8.jpg); }
}
That mean you want :
bg-1 stay fixed from 00% to 11%
bg-2 stay fixed from 12% to 24%
etc
By putting 11%, the transtion duration will be 1% (12% - 11% = 1%).
1% of 240s (total duration) => 2.4 seconds.
You can adapt according to your needs.
The linear timing function will animate the defined properties linearly. For the background-image it seems to have this fade/resize effect while changing the frames of you animation (not sure if it is standard behavior, I would go with #Chukie B's approach).
If you use the steps function, it will animate discretely. See the timing function documentation on MDN for more detail. For you case, do like this:
-webkit-animation-timing-function: steps(1,end);
animation-timing-function: steps(1,end);
See this jsFiddle.
I'm not sure if it is standard behavior either, but when you say that there will be only one step, it allows you to change the starting point in the #keyframes section. This way you can define each frame of you animation.
Like the above stated, you can't change the background images in the animation. I've found the best solution to be to put your images into one sprite sheet, and then animate by changing the background position, but if you're building for mobile, your sprite sheets are limited to less than 1900x1900 px.
I needed to do the same thing recently. Here's a simple implementation
#wrapper { width:100%; height:100%; position:relative; }
#wrapper img { position:absolute; top:0; left:0; width:100%; height:auto; display:block; }
#wrapper .top { animation:fadeOut 2s ease-in-out; animation-fill-mode:forwards; }
#keyframes fadeOut {
0% { opacity:1; }
100% { opacity:0; }
}
<div id="wrapper">
<img src="img1.jpg" class="top" style="z-index:2;">
<img src="img2.jpg" style="z-index:1;">
</div>
You can use animated background-position property and sprite image.
You can follow by this code:
#cd{
position: relative;
margin: 0 auto;
height: 281px;
width: 450px;
}
#cf img{
left: 0;
position: absolute;
-moz-transition: opacity 1s ease-in-out;
transition: opacity 1s ease-in-out;
}
#cf img.top:hover{
opacity: 0;
}
<div id="cf">
<img class="button" src="Birdman.jpg" />
<img src="Turtle.jpg" class="top" />
</div>
You can use the jquery-backstretch image which allows for animated slideshows as your background-images!
https://github.com/jquery-backstretch/jquery-backstretch
Scroll down to setup and all of the documentation is there.
Well I can change them in chrome. Its simple and works fine in Chrome using -webkit css properties.