I'm trying to make an splash loading with CSS/HTML/JS, but am having some problems.
The problem is when trying to make the splash screen disappear with a transition effect, but the transition effect isn't applying.
I am sure my JavaScript is work properly, as it appends the new class not-displayed to the div element.
const splash = document.querySelector('.splash');
console.log(splash);
document.addEventListener('DOMContentLoaded', (e) => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
.splash {
z-index: 100000;
position: fixed;
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffff;
}
//all of these code not working
.splash.not-displayed {
z-index: 20;
opacity: 0;
position: fixed;
height: 100vh;
width: 100%;
background-color: #f06c65;
transition: all 0.5298s ease-out;
-webkit-transition: all 0.5298s ease-out;
-moz-transition: all 0.5298s ease-out;
-o-transition: all 0.5298s ease-out;
}
#keyframes fadein {
to {
opacity: 1;
}
}
.fade-in {
opacity: 0;
animation: fadein 1s ease-in forwards;
}
<div class="splash">
<h1 class="fade-in">
hello
</h1>
</div>
You have two things going on here, a transition and an animation. First I removed a lot of unnecessary CSS code to make things clearer.
Your code is working as expected. When the page loads, the "fadein" animation is triggered by the fade-in class. The text "hello" fades in from opacity 0 to opacity 1 over the course of a second, as expected.
Meanwhile, your Javascript triggers on page load and adds the class not-displayed to the outer div after two seconds. This triggers the transition effect, which after half a second applies a red background to the div as it fades the div out, bringing it back to opacity 0.
I'm not sure what specifically you are trying to achieve here, but you have wired up a successful transition and animation effect.
const splash = document.querySelector('.splash');
console.log(splash);
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
.splash.not-displayed {
opacity: 0;
background-color: #f06c65;
transition: all 0.5298s ease-out;
}
.fade-in {
opacity: 0;
animation: fadein 1s ease-in forwards;
}
#keyframes fadein {
to {
opacity: 1;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="splash">
<h1 class="fade-in">
hello
</h1>
</div>
In your code
document.addEventListener('DOMContentLoaded', () => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
you are adding new class to remove the .splash and then add new class not-displayed
Everything is working just fine, except you have given opacity: 0 to the not-displayed class.
const splash = document.querySelector('.splash');
console.log(splash);
document.addEventListener('DOMContentLoaded', (e) => {
setTimeout(() => {
splash.classList.add('not-displayed');
}, 2000);
});
.splash {
z-index: 100000;
position: fixed;
height: 100vh;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: #ffff;
}
.not-displayed {
z-index: 20;
/* opacity: 0; */
position: fixed;
height: 100vh;
width: 100%;
background-color: #f06c65;
transition: all 0.5298s ease-out;
-webkit-transition: all 0.5298s ease-out;
-moz-transition: all 0.5298s ease-out;
-o-transition: all 0.5298s ease-out;
}
#keyframes fadein {
to {
opacity: 1;
}
}
.fade-in {
opacity: 0;
animation: fadein 1s ease-in forwards;
}
<div class="splash">
<h1 class="fade-in">
hello
</h1>
</div>
Codepen
You should set the transition to .splash not to .splash.not-displayed
Related
I'm trying to create a draft for a mobile website interface but I'm having some strange issues with the menu. Initially when the page loads it should display a blank footer except for a plus icon. When clicked, the plus icon expands and various other icons pop up that link to different parts of the interface. However, when I load the page these icons are visible. Further, when I try to expand and shrink the menu bar for the first time they disappear. However, if I then expand it again they pop in for a moment before vanishing then expanding like I expect.
I'm not sure why the transition effect works one way and not the other. I've tried messing with the timing of the opacity and visibility properties in the keyframes but so far it's still displaying this weird behavior. I've also tried adding a class that makes the elements hidden on page load and removing it the first time they're animating but that doesn't fix the pop in on subsequent cycles. I've included the relevant sections of the code below and a codepen of everything. I've slowed down the icon animations for the moment so it's easier to see their behavior.
JS
const mobile_menu = (() => {
const expandNavigation = (navButton, navBar, buttons) => {
navButton.addEventListener('click', () => {
let buttonType = ['slow', 'fast', 'fast', 'slow'];
if (navButton.classList.contains('clicked')) {
navButton.classList.add('unclicked');
navButton.classList.remove('clicked');
navBar.classList.add('retract');
navBar.classList.remove('expand');
for (let i = 0; i < buttons.length; i++) {
showButton(buttons[i], buttonType, 'retract');
}
}
else {
navButton.classList.add('clicked');
navButton.classList.remove('unclicked');
navBar.classList.add('expand');
navBar.classList.remove('retract');
for (let i = 0; i < buttons.length; i++) {
showButton(buttons[i], buttonType, 'expand');
}
}
});
}
const showButton = (button, type, direction) => {
if (direction === 'retract') {
if (type === 'slow') {
button.classList.remove('icon_appear_slow');
button.classList.add('icon_vanish_slow');
}
else {
button.classList.remove('icon_appear_fast');
button.classList.add('icon_vanish_fast');
}
}
else {
if (type === 'slow') {
button.classList.remove('icon_vanish_slow');
button.classList.add('icon_appear_slow');
}
else {
button.classList.remove('icon_vanish_fast');
button.classList.add('icon_appear_fast');
}
}
}
return { expandNavigation };
})();
HTML
<div class="screen">
<div class="page">Content</div>
<div class="nav_menu">
<span id="nav_bar"></span>
<div class="nav_button">
<i class = "material-icons call">call</i>
</div>
<div class="nav_button">
<i class = "material-icons message">chat</i>
</div>
<div class="nav_icon">
<i id="open_close" class = "material-icons unclicked">add</i>
</div>
<div class="nav_button">
<i class = "material-icons account">person</i>
</div>
<div class="nav_button">
<i class = "material-icons settings">settings</i>
</div>
</div>
</div>
CSS
.icon_appear_slow {
animation: grow 1s ease-in-out 2s 1 normal forwards;
}
.icon_appear_fast {
animation: grow 2s ease-in-out 1s 1 normal forwards;
}
.icon_vanish_slow {
animation: shrink 1s ease-in-out 2s 1 normal forwards;
}
.icon_vanish_fast {
animation: shrink 2s ease-in-out 1s 1 normal forwards;
}
#keyframes grow {
0% {
transform: rotate(0deg) scale(0.1);
visibility: hidden;
opacity: 0;
}
1% {
visibility: visible;
}
100% {
transform: rotate(360deg) scale(1);;
opacity: 1;
}
}
#keyframes shrink {
0% {
transform: rotate(0deg) scale(1);
visibility: visible;
opacity: 1;
}
99% {
visibility: hidden;
}
100% {
transform: rotate(-360deg) scale(0.1);
opacity: 0;
}
}
Change id="nav_bar" to class="nav_bar"
i dont really know but its not saving the changes with id
on the js part:
just change const navBar = document.getElementById('nav_bar');
to
const navBar = document.querySelector('.nav_bar');
on the css part:
.retract {
height: 60px;
width: 350px;
animation: retraction 0.3s ease-in-out 2.5s 1 normal forwards;
}
.icon_vanish_fast {
opacity:1;
animation: shrink 2s ease-in-out 1s 1 normal forwards;
}
.icon_vanish_slow {
opacity:1;
animation: shrink 1s ease-in-out 2s 1 normal forwards;
}
.nav_bar {
display: table-cell;
vertical-align: middle;
height: 50px;
width: 50px;
text-align: center;
background: rgb(30, 134, 30);
border-radius: 50%;
display: inline-block;
font-weight: bold;
font-size: 1.2em;
margin: 0 auto;
position: absolute;
}
.nav_button {
opacity:0;
}
I am doing a splash screen for my website. I have managed to get it working as JS wasn't working.
"use strict";
$(function(){
$('.fadein img:gt(0)').hide();
setInterval(function(){
$('.fadein :first-child').fadeOut()
.next('img').fadeIn()
.end().appendTo('.fadein');},
6000);
});
const splash = document.querySelector('.splash');
document.addEventListener('DOMContentLoaded', (e)=> {
setTimeout(function()=> {
splash.classList.add('display-none');
}, 10000);
})
The bottom code breaks the top code (which works and runs the slideshow).
.splash {
position: fixed;
top: 0;
left: 0;
width: auto;
height: auto;
z-index: 200;
}
.splash.display-none {
position: fixed;
opacity: 0;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: -10;
transition: all 6s;
}
#keyframes fadeIn {
to{
opacity: 0;
visibility: hidden;
}
}
#-webkit-keyframes fadeIn {
to{
opacity: 0;
visibility: hidden;
}
}
.splash {
opacity: 1;
animation: fadeIn 2s ease-in forwards;
-webkit-animation: fadeIn 2s ease-in forwards;
animation-delay: 0.75s;
}
.fade-in {
height: 100vh;
width: 100%;
}
This is my CSS, and the animation works. My only problem with it is that if I went back to homepage, the animation would happen again. This is why I want to use Javascript so it only happens on a new instance of loading the website.
Use localStorage to see if splash screen has been shown already. Set them to display:none immediately so they are completely hidden. I'm not sure what you actually want to happen with the splash, so I'm just hiding them completely. I think it would be more pleasant to just have a very short opacity transition instead.
You can use localStorage.removeItem to clear the splashed flag.
You may want to use a unique ID for the localStorage name for this specific splash, and not just "splashed".
document.addEventListener('DOMContentLoaded', (e)=> {
const splashed = localStorage.getItem('splashed')
const splash = document.querySelector('.splash');
const splasher = () => {
splash.classList.add('display-none');
localStorage.setItem('splashed',1)
};
splashed ? splash.forEach(x=>x.style.display='none') : setTimeout(splasher, 10000);
})
I'm working on a project that is using Intersection Observer to add animation to an element's style upon entry. However, what I'm noticing is that the : hover attribute no longer works when I apply the style. Am I doing this wrong, or, are these two not compatible? On the JS Fiddle, I've commented out the hover attribute by default. Try uncommenting it and see what happens.
I've tried banner.classList.add(/new class in here/) but that method also took away the :hover as well.
DEMO:
Demo
disable animation on hover because animations has a higher specificity
const options = {
root: null,
threshold: 1,
};
const banner = document.querySelector('.product-banner');
const observerAnim = new IntersectionObserver(function(entries, observer) {
entries.forEach(entry => {
if (!entry.isIntersecting) {
return;
}
banner.style.animation = '1s ease-in-out home-page-fade';
banner.style.animationFillMode = 'forwards';
observer.unobserve(banner);
});
}, options);
observerAnim.observe(banner);
body {
background-color: #fff;
min-height: 2000px;
}
img.product-banner {
opacity:0;
position: relative;
top: 1000px;
-moz-transition: all ease 0.3s;
-webkit-transition: all ease 0.3s;
transition: all ease 0.3s;
}
#keyframes home-page-fade {
0% {
transform: translateY(50%);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
img.product-banner:hover {
animation: none !important;
opacity: 0.8;
transform: scale(0.9);
-moz-transition: all ease 0.3s;
-webkit-transition: all ease 0.3s;
transition: all ease 0.3s;
}
<h1>
Scroll Effect
</h1>
<img class="product-banner" src="https://cdn.mos.cms.futurecdn.net/bQgcMwEnyhFu6ASuUFrtsn-1024-80.jpg" width="300">
So, I have created a CSS3 animation that is supposed to fade out an element by setting its opacity from 1 to 0 and at the last frames change the position to absolute and display to none. But on Safari it will only maintain the opacity, position and display are not set to the final values.
#-webkit-keyframes impressum-fade-out {
0% {
opacity: 1;
display: block;
position: relative;
}
99% {
opacity: 0;
position: relative;
}
100% {
opacity: 0;
display: none;
position: absolute;
}
}
It seems to work on Chrome but not on Safari (I tried version 8). Apparently, position and display do not work properly with animation-fill-mode: forwards...
JSFiddle: http://jsfiddle.net/uhtL12gv/
EDIT For Bounty: I am aware of workarounds with Javascript and transitionend events. But I am wondering why Browsers lack support for this? Does the specification state that fillmode forwards doesnt apply to some attributes like position or is this a bug in the browsers? Because I couldnt find anything in the bug trackers.. If anybody has some insight, I would really appreciate it
As Suggested in the comments, you can adjust the height.
EDIT: Animation Reference Links Added.
Display property is not animatable.
Position property is not
animatable.
List of all CSS properties and if and how they are
animatable.
$('.block').click(function() { $(this).toggleClass('active') });
#-webkit-keyframes impressum-fade-out {
0% {
opacity: 1;
}
99% {
opacity: 0;
}
100% {
opacity: 0;
height:0;
}
}
.block {
width: 100px;
height: 100px;
background: blue;
}
.block2 {
width: 100px;
height: 100px;
background: red;
}
.block.active {
-webkit-animation-name: impressum-fade-out;
animation-name: impressum-fade-out;
-webkit-animation-duration: 500ms;
animation-duration: 500ms;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="block"></div>
<div class="block2"></div>
I would suggest you the cross-browser solution based on CSS3 Transitions and transitionend event:
JSFiddle
$('.block').one('click', function() {
var $this = $(this);
$this.one('webkitTransitionEnd transitionend', function() {
$this.addClass('block_hidden');
$this.removeClass('block_transition');
});
$this.addClass('block_transition');
});
.block {
width: 100px;
height: 100px;
background: blue;
-webkit-transition: opacity 0.5s;
transition: opacity 0.5s;
}
.block_2 {
background: red;
}
.block_transition {
opacity: 0;
}
.block_hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="block"></div>
<div class="block block_2"></div>
I am trying to animate a div element (slide and fade) with a button click. At first, the element is not visible to a user. When the button is clicked, it will slide to right and fade in. Once the button is clicked again, it will slide to left and fade out. I come up with two solutions, with css and with JQuery.
In the first one, I used JQuery. You can find the example in this JSFiddle 1.
HTML
<button id="my-button">Click me!</button>
<div id="my-modal"></div>
CSS
#my-modal {
opacity: 1;
position: fixed;
top: 50px;
left: 0;
left: -250px;
width: 250px;
height: 100%;
background-color: red;
}
JQuery
$("#my-button").click(function () {
var $modal = $("#my-modal");
$modal.stop(true, true).animate({
left: "toggle",
opacity: "toggle"
}, 1000);
});
Here, everything seems working but it does directly opposite of what I want. It first fades out, and with the second click, it fades in. It is because that the opacity of the element is 1, but if I turn it to 0, nothing happens.
Secondly, I tried to do that with css animation by using key-frames (changing opacity from 0 to 1) but it has also problem. It starts the animation exactly the way I want. However, when I click the button again, it disappears immediately. Here is the JSFiddle 2.
HTML
<button id="my-button">Click me!</button>
<div id="my-modal"></div>
CSS
#my-modal {
opacity: 0;
position: fixed;
top: 50px;
left: 0;
left: -250px;
width: 250px;
height: 100%;
background-color: red;
-moz-transition: all 1s ease;
-webkit-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
}
.move-my-modal {
-moz-transform: translate(250px, 0px);
-webkit-transform: translate(250px, 0px);
-ms-transform: translate(250px, 0px);
-o-transform: translate(250px, 0px);
}
.animate-opacity {
-webkit-animation: toggle-opacity 1s ease;
-moz-animation: toggle-opacity 1s ease;
-o-animation: toggle-opacity 1s ease;
animation: toggle-opacity 1s ease;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-o-keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes toggle-opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
JQuery
$("#my-button").click(function () {
var $modal = $("#my-modal");
$modal.toggleClass("move-my-modal");
$modal.toggleClass("animate-opacity");
});
To this end, I have these questions;
1) What are the problems with these two approaches? Is there something that I missed or forgot to use? How can I correct them to meet the requirements that I mentioned at the beginning.
2) Which one is the better way to make this action? Is there any cons or pros of these approaches?
3) Is there any other way to make this action? I am new on this area and I might not notice a simpler way.
You can toggle an .active class to the element and use CSS transitions.
This way, if the browser is old enough to not support animations, it will still work but it won't slow down computers that do not handle animations well.
$("#my-button").click(function () {
$("#my-modal").toggleClass('active');
});
#my-modal.active {
opacity: 1;
left: 0;
}
$("#my-button").click(function () {
$("#my-modal").toggleClass('active');
});
#my-modal {
opacity: 0;
position: fixed;
top: 50px;
left: -250px;
width: 250px;
height: 100%;
background-color: red;
transition: all 1s linear;
}
#my-modal.active {
opacity: 1;
left: 0;
}
<button id="my-button">Click me!</button>
<div id="my-modal"></div>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>