CSS page transition by adding & removing a class (Vanilla JavaScript) - javascript

I'm attempting to create a transition that quickly fades in the page on load and then when a link is clicked, the page fades out and moves up slightly.
To do this I created the class 'is-loaded' which I would apply to the elements ('wrapper' and 'page-fade'). When the document is loaded, the 'is-loaded' class would be added, then when a link is clicked, the same class would be removed from both elements.
The code:
.wrapper {
transform: translateY(-25px);
transition: transform cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.3s;
}
.wrapper.is-loaded {
transform: translateY(0);
}
.page-loader {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #ffffff;
z-index: 999999;
transition: opacity cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.4s, visibility cubic-bezier(0.25, 0.46, 0.45, 0.95) 0.4s;
}
.page-loader.is-loaded {
opacity: 0;
visibility: hidden;
}
document.querySelectorAll('a').forEach(e => {
e.addEventListener('click', function() {
event.preventDefault()
var i = this.getAttribute('href')
var wrapper = document.querySelector('wrapper');
var pageloader = document.querySelector('page-loader');
wrapper.classList.remove('is-loaded'),
setTimeout(function() {
pageloader.classList.remove('is-loaded');
}, 80),
setTimeout(function() {
window.location = i
}, 100)
})
})
document.addEventListener("DOMContentLoaded", function() {
var wrapper = document.querySelectorAll('wrapper');
var pageloader = document.querySelectorAll('page-loader');
wrapper.classList.add('is-loaded'),
pageloader.classList.add('is-loaded');
})
I'm new to writing in JavaScript so i'm unsure why my code does nothing. Is there a way to get this to work? No jQuery please and just vanilla js. Thank you.

You're missing the prefix selector notation . necessary to find 'wrapper' or 'page-loader' with document.querySelector()|document.querySelectorAll(). In both cases, you'd use the same kind of selector syntax as you do in your CSS.
var wrapper = document.querySelectorAll('.wrapper');
var pageloader = document.querySelectorAll('.page-loader');
Also, document.querySelectorAll() returns a(n Array-like) HTML NodeList, which doesn't have a classList property. You could convert the NodeList to an Array and iterate through the result, adding to the classList of each element or, if you know there's only one of what you're looking for on the page, swap document.querySelectorAll() for document.querySelector() — which will return a single element.

Related

Add an addEventListner on a class remove

I made some fandeIn and fadeOut codes to an exercise.
I'm trying to remove the setTimeout() on the fadeIn().
Like using an addEventListner maybe, but there is no transition on .displayNone.
On the MDN I just found transitions interacting with EventListner.
function fadeOut(disable) {
disable.classList.remove('visible');
disable.classList.add('hidden');
disable.addEventListener('transitionend', () => disable.classList.add('displayNone'));
};
function fadein(enable, timer) {
if (!timer) timer = 350;
enable.classList.remove('displayNone');
setTimeout(function () {
enable.classList.remove('hidden');
enable.classList.add('visible');
}, timer);
};
.displayNone {
display: none;
}
.visible {
visibility: visible;
opacity: 1;
transition: opacity 1.5s linear;
}
.hidden {
visibility: hidden;
opacity: 0;
transition: visibility 0s 350ms, opacity 350ms, display 350ms linear;
}
P.S.: This works good, I'm just trying another way to make it works too.
The setTimeout method returns a timeout descriptor/id (actually just an integer). You may use it to remove the timeout later:
// setting timeout
var timeout = window.setTimeout(function(){}, 5000);
window.clearTimeout( timeout )

How can I control CSS transitions and animations with JS?

I have an image that goes from opacity 0 to 1 when a bit of text is hovered. I would like the transition to be smooth, something similar to CSS transition. Can't really figure out how to make this happen, so any help would be appreciated.
The JavaScript looks like this:
document.getElementById("text-hover").addEventListener("mouseover", imageTransition);
document.getElementById("text-hover").addEventListener("mouseout", imageTransitionOut);
function imageTransition() {
document.getElementById("pic").style.opacity = "1";
}
function imageTransitionOut() {
document.getElementById("pic").style.opacity = "0";
}
Just define the transition in css, it will trigger when you change the opacity value in javascript:
#pic {
transition: opacity .3s;
opacity: 0;
}
You don't need to change your javascript
Update
If you need to animate more than one property, it is better to define the animation in css and then trigger it from javascript by toggling a class on the element
the css:
#pic {
transition: all .3s;
opacity: 0;
transform: scale(.1);
}
#pic.animate {
opacity: 1;
transform: scale(1);
}
javascript:
var textHover = document.getElementById("text-hover");
var pic = document.getElementById("pic");
textHover.addEventListener("mouseover", function() {
pic.classList.add('animate');
});
textHover.addEventListener("mouseout", function() {
pic.classList.remove('animate');
});

Vanilla Javascript - Animation with different timing

I would like to make an animation using onscroll in Vanilla Javascript. I have 2 classes. The first one is .photography_box which is active and the second one is .photography_box_active which is not active. When i scroll down to 1500px my second class .photography_box_active kicks in and my animation is working great. My .photography_box consist of 12 boxes. When the animation happens all of them come in at the same time which is not what i want. I would like each one of them to come in one after the other. In jQuery i could use $.each but i would like to have the same effect using Vanilla Javascript. Can someone help me solve the problem?
Thanks
CSS code for my classes :
.photography_box {
overflow: hidden;
position:relative;
cursor: pointer;
margin-bottom:20px;
opacity: 0;
cursor: pointer;
-webkit-transform:translateX(-50px);
transform:translateX(-50px);
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
.photography_box_active {
opacity: 1;
-webkit-transform: translateX(0px);
transform: translateX(0px);
}
JS code is :
var photoBox = document.getElementsByClassName("photography_box");
window.onscroll = function() {
loopBox()
};
function loopBox(){
if ( window.pageYOffset > 1500 ){
for ( f = 0; f <= photoBox.length -1; f++ ) {
photoBox[f].classList.add("photography_box_active");
};
};
};
You can use setTimeout in your loop to delay the animation for each item based on its index. So if you want a delay of 150ms:
for ( f = 0; f < photoBox.length; f++ ) {
setTimeout(function(){
photoBox[f].classList.add("photography_box_active");
}, 150 * f);
}
Note that as you know in advance the number of items, and as you are using css transitions, this could be done purely in css, keeping your existing js code. Supposing your .photography_box items are in a .box container
.box .photography_box:nth-child(1) { transition-delay: 0 }
.box .photography_box:nth-child(2) { transition-delay: 0.05s }
// and so on...
quite cumbersome to write, especially with vendor-prefixes, but nothing annoying if you are using a css preprocessor like sass
Example: array.forEach(callback[, thisArg])
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

How to remove a div with fade out effect in JavaScript?

I want to remove a div element on click event but i want to remove it with a fade out effect. I have got some JQuery solution but i need pure JavaScript or css solution.
document.querySelector('.list').addEventListener("click", function(e){
if (e.target.localName === "span") {
var removeTarget = e.target.parentNode.parentNode;
removeTarget.parentNode.removeChild(removeTarget);
};
});
This code is removing the div element with no effect. How can i add a fade out effect?
I've made this function a while ago for a personal project:
function removeFadeOut( el, speed ) {
var seconds = speed/1000;
el.style.transition = "opacity "+seconds+"s ease";
el.style.opacity = 0;
setTimeout(function() {
el.parentNode.removeChild(el);
}, speed);
}
removeFadeOut(document.getElementById('test'), 2000);
There are two ways you can achieve this: CSS3 animation or jQuery animation.
CSS3 Animation
In your CSS document, add:
.list {
opacity: 1;
-webkit-transition: opacity 1000ms linear;
transition: opacity 1000ms linear;
}
This will make any change of opacity to your item fade by 1000ms.
Change line 4 of your JavaScript to:
removeTarget.style.opacity = '0';
setTimeout(() => removeTarget.remove(), 1000);
This will make your item change opacity to 0, thus making the transition from step 1 have an effect. Then it will remove the item with your code after 1000ms.
Note: Make sure the time of the CSS3 transition and the setTimeout are the same.
jQuery Animation
Get jQuery
Go to the jQuery Website and download it, or
Add ` in your HTML document before any jQuery code.
Change line 4 of your Javascript to:
removeTarget.fadeOut(1000)
This will Fade Out your item by 1000ms, you can change this time to whatever you want.
In 2020 you can forgo use of use setTimeout for the animationend event, removing the need to maintain the duration in two places:
.fade-out {
animation: fade 2s;
-webkit-animation: fade 2s;
-moz-animation: fade 2s;
}
/* Animate opacity */
#keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
#-moz-keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
#-webkit-keyframes fade {
from { opacity: 1 }
to { opacity: 0 }
}
const elementToFade = document.getElementById('my-element');
elementToFade.onanimationend = (e) => {
if (e.target.classList.contains('fade-out')) {
elementToFade.parentNode.removeChild(elementToFade);
}
};
// To fade away:
elementToFade.classList.add('fade-out');
It's a good question, but to animate some element in html, this element has to exist while it is animating. So, you have some ways to do this, a good way is hide this element with CSS and after the animation you remove this element. While you hiding you can animate, you can see this example:
<style>
.hide{
opacity: 0;
}
.fade-out {
transition:1s linear all;
}
</style>
<span class="list fade-out">
This is a List, click me to hide
</span>
<script>
document.querySelector('.list').addEventListener("click", function(e) {
if (e.target.localName === "span") {
//Add CSS hide and animate with fade out
var currentCSS = this.className;
this.className = currentCSS + ' hide';
var removeTarget = e.target.parentNode.parentNode;
setTimeout(function(){
removeTarget.parentNode.removeChild(removeTarget);
},1000);
};
});
</script>
Add the following CSS class to the element using elem.className="my-animation"; on click:
.my-animation {
animation: fade 3s steps(90) forwards;
-webkit-animation: fade 3s steps(90) forwards;
-moz-animation: fade 3s steps(90) forwards;
}
#keyframes fade {
from {
opacity: 1;
}
to {
opacity: 0.0;
}
}
You may control the speed of the animation by modifying the steps(number) as well.
Just goto jQuery source code, take out the fade code which is in pure javascript, and use it, no need to reinvent the wheel,
or a hint is reduce the height of div to 0 slowly using setTimeInterval()
or a css solution would be to use transform and transition properties

Rotating text with Javascript

I'd like to cycle through an array of words creating a text rotation affect. I have most of it working as expected. Is there any way I can use a css transition on the length of the p element?
When traversing from an object with char.length > 10 to an object with char.length < 5 (for example) the movement isn't smooth and I'd like to ease the movement of the text around the word rather than abruptly jumping backwards (or forwards depending on the length of the word)
HTML:
<p><span id="description-rotate"></span> something built on something else.</p>
SASS:
#-webkit-keyframes rotate-text
0%
opacity: 0
30%
opacity: 1
50%
opacity: 1
70%
opacity: 1
100%
opacity: 0
p
font-family: 'Helvetica', sans-serif
.rotate-text
-webkit-animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
-moz-animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
-o-animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
animation: rotate-text 3050ms cubic-bezier(0.645, 0.045, 0.355, 1.000) infinite
Javascript:
var descriptionArray = ['some text', 'some more text', 'some even longer text'];
var descriptionLength = descriptionArray.length;
var description = $('#description-rotate');
function loop(i) {
description.text(descriptionArray[i%descriptionLength]);
setTimeout(function() {
loop(i+1);
description.addClass('rotate-text');
}, 3050); // This duration must match the length of the animation
}
loop(0);
I realize this may be a poor way of explaining my goal, check out the CodePen for a better idea of what I'm trying to create.
Thanks!
See: http://codepen.io/anon/pen/JueGx
A simple example using jQuery
is by storing the desired looping / swapping words into the data-* attribute:
$("[data-words]").attr("data-words", function(i, words) {
var $self = $(this).text(""),
words = words.split("|"),
tot = words.length,
c = 0;
for(var i=0; i<tot; i++) $self.append($('<span/>',{text:words[i]}));
var $words = $self.find("span");
(function loop(){
$self.animate({ width: $words.eq( c ).width() });
$words.stop().fadeOut().eq(c).fadeIn().delay(1000).show(0, loop);
c = ++c % tot;
}());
});
/* DATA-WORDS Loop/swap words in sentence */
[data-words] {
vertical-align: top;
position: static;
}
[data-words] > span {
display: none;
position: absolute;
color: #0bf;
}
<p>
This is <span data-words="some|an interesting|some longer">some</span> text
</p>
<p>
Say <span data-words="hi|wow">hi</span> to <span data-words="Javascript|Stack Overflow">mom</span>
</p>
<script src="//code.jquery.com/jquery-3.1.0.js"></script>
The | -delimited words will be converted to Array and finally to child <span> elements
Such span elements need to be absolutely positioned inside the parent span
jQuery will than init a recursive loop, calculate the next word width, and animating it (fade + width)
How about jQuery's animate() function?
http://api.jquery.com/animate/
You can trigger an animation for each word in the array. Here's an idea, you will have to figure out how populate the variables hasMoreWordsInTheArray and nextWordInTheArray:
function animateParagraphTag(word) {
if(hasMoreWordsInTheArray) {
//some special code to calculate the best width based on the word's length (theNewWidthValue)
$('p').animate(
{ width: theNewWidthValue },
"fast",
animateParagraphTag(nextWordInTheArray)
);
}
}
You will have to calculate the width based on the length of the words and place that within the parameters of the animation, then, once the p tag finishes the expansion/contraction accordingly, it will trigger the callback function, you can then move on to the next element (word) of the array.

Categories