Div flashing when removing class with visibility - javascript

I'm having an issue with a notification system I am building.
All works fine till the end where my javascript is triggered to remove the show class from the notification div. When the class is removed, there is a brief flash to the start position of the div.
Example here
JS to show notification:
function showNotification() {
notificationRef.current.classList.add("nShow");
setTimeout(() => {
notificationRef.current.classList.remove("nShow");
}, 4000);
}
Notification CSS has general positioning and styling with visibility: hidden and top: 85px set.
nShow (class to show notification):
.notification.nShow {
visibility: visible;
animation: fadeNotiIn 1s, fadeNotiOut 1s 3s;
}
#keyframes fadeNotiIn {
from {
top: 0;
opacity: 0;
}
to {
top: 85px;
opacity: 1;
}
}
#keyframes fadeNotiOut {
from {
top: 85px;
opacity: 1;
}
to {
top: 0;
opacity: 0;
}
}
It seems that visibility: hidden is being set after opacity: 1 so there is a flash when removing the show class.
Thanks

Here is a sample. I would not advise you to use animation here. Between the two animations you plan, your element goes back to its default state and that's making things ugly.
Instead, what I would do is use a short transition to smooth a bit the thing between the two states, and keep handling it through JS.
const notification = document.querySelector('.notification');
function startNotification() {
notification.classList.add("nShow");
setTimeout(() => {
notification.classList.remove("nShow");
}, 3000);
}
.notification {
opacity: 0;
position: absolute;
top: 0px;
transition: all 1s;
}
.notification.nShow {
top: 85px;
opacity: 1;
}
.root {
position: relative;
}
<button onclick="startNotification()">Start notification</button>
<div class="root">
<div class="notification">Hello</div>
</div>
As said in the first version, I don't think you should go for visibility and opacity at the same time, and since you are already using opacity, let's use it completely.

Related

Text Animation Flickering Problem in CSS and React

I managed to achieve this animation through CSS animations and React. but go stuck in flickering problem. I don't know why this is happening maybe 'cause I used setInterval or there is some problem with my css animations keyframes. help me to solve this problem. the flicker only occurs after some time. and after refreshing the page the animation works perfectly fine without flicker problem.
this is how the animation looks after refreshing the page and this is what I want too. (ignore the screen recorder watermark).
animation I want
but after sometime the animation starts flickering like this.
Flickering problem
here are the code snippets I wrote
jsx snippet
<div className="relative w-[280px] md:w-[350px] lg:w-[500px]">
<span>{"[ "}</span>
<p className="text_animate ml-2">
{dev ? "for" : "by"} Developers
</p>
<span className="absolute right-0 ">{" ]"}</span>
</div>
css snippet
.text_animate {
color: orange;
margin: 0 auto;
display: inline-block;
position: relative;
letter-spacing: .15em;
text-align: start;
animation: text-up 6s linear infinite;
cursor: none;
}
#keyframes text-up {
0% {
top:45px;
opacity: 0;
}
20% {
top:0;
opacity: 1;
}
35% {
top: 0;
opacity: 1;
}
50% {
top: -45px;
opacity: 0;
}
52% {
top: 45px;
opacity: 0;
}
70% {
top: 0;
opacity: 1;
}
85% {
top: 0;
opacity: 1;
}
100% {
top: -45px;
opacity: 0;
}
}
useState changing text
const [dev, setDev] = useState(true);
setInterval(() => {
setDev(!dev);
}, 3000);
If there is any better way to achieve this I would really love to learn so let me know that too.
Maybe you should put setInterval to useEffect, and remember to clear timer. Like this:
useEffect(() => {
const timer = setInterval(() => {
setDev(!dev);
}, 3000);
return () => {
clearInterval(timer);
}
}, []);
And there is a solution only using css to implement this, I will write a demo later.
EDIT:
Explain the above code:
useEffect with [] as second param will make sure run setInterval once when mount the component.
The clearInterval in return function will make sure engine GC the variables in setInterval callback functions when unmount the component, or the setInterval will still work even though you needn't it.
CSS only solution:
ul {
margin: 0;
padding: 0;
list-style-type: none;
}
li {
margin: 0;
padding: 0;
}
.scroll-container {
overflow: hidden;
height: calc(var(--line-h) * 1px);
line-height: calc(var(--line-h) * 1px);
font-size: 18px;
}
.scroll-container ul {
animation-name: move;
animation-duration: calc(var(--speed) * var(--lines));
animation-timing-function: steps(var(--lines));
animation-iteration-count: infinite;
}
.scroll-container ul li {
animation-name: li-move;
animation-duration: var(--speed);
animation-iteration-count: infinite;
}
#keyframes move {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(0, calc(var(--lines) * var(--line-h) * -1px));
}
}
#keyframes li-move {
0% {
transform: translate(0, 0);
}
50%,
100% {
transform: translate(0, calc(var(--line-h) * -1px));
}
}
<div
class="scroll-container"
style="--lines: 2; --line-h: 26; --speed: 3s"
>
<ul>
<li>For Developers</li>
<li>By Developers</li>
<!-- repeat first in tail for infinity -->
<li>For Developers</li>
</ul>
</div>
I leaned this from Chokcoco on CodePen but forget which post.

How do I get Javascript to run animation instead of CSS

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);
})

Random animation on Simple Image Slideshow

I want to apply a random animation on my slideshow image. First, I tried adding an animation such as scale but it didn't work as I wanted it to.
Things I want to fix:
Smoothness on fadein
Random animation (can be anything at this point, I just want to see how it's done)
Fiddle: http://jsfiddle.net/jzhang172/e7cLtsg9/1/
$(function() {
$('img').hide();
function anim() {
$("#wrap img").first().appendTo('#wrap').fadeOut(3500).addClass('transition').addClass('scaleme');
$("#wrap img").first().fadeIn(3500).removeClass('scaleme');
setTimeout(anim, 3700);
}
anim();
});
body,
html {
margin: 0;
padding: 0;
background: black;
}
#wrap img {
position: absolute;
top: 0;
display: none;
width: 100%;
height: 100%;
}
.transition {
transition: 10s;
}
.scaleme {
transition: 10s;
transform: scale(1.3);
}
.box {
height: 300px;
width: 500px;
position: relative;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box">
<div id="wrap">
<img src="http://elegantthemes.com/preview/InStyle/wp-content/uploads/2008/11/s-1.jpg" />
<img src="http://elegantthemes.com/preview/InStyle/wp-content/uploads/2008/11/s-5.jpg" />
<img src="http://elegantthemes.com/preview/InStyle/wp-content/uploads/2008/11/s-3.jpg" />
</div>
</div>
Here is a sample using CSS animations and jQuery (for achieving the randomness of animations). If you don't wish to use CSS animations and want to stick to transitions + jQuery effects (like fadeIn), you can still adapt this code to support it because the base idea will still remain the same. I am not too comfortable with jQuery effects and have hence stuck to using CSS animations.
Below is an overview of how it is being done (refer inline comments for more details):
Inside a wrapper there are a group of images that are part of the slide-show (like in your demo).
Using CSS #keyframes, a list of animations (one of which would be used randomly) is created in addition to the default fade-in-out animation. This list is also maintained in an array variable (in JS for picking up a random one from the list).
On load, the default fade-in-out animation and one random animation is added to the 1st element.
An animationend event handler is added to all of the images. This event handler will be triggered when the animation on an element ends. When this is triggered, animation on the current element is removed and the default fade-in-out + a random animation is added to the next element.
The animations are added using inline styles because if we add multiple CSS classes each with one different animation, then the animation in the latest class will override the others (that is, they will not happen together).
A loop effect is achieved by checking if the current element has any other img sibling elements. If there are none, the animation is added back to the 1st element.
$(window).load(function() {
$img = $('img'); // the images
var anim = ['zoom', 'shrink', 'move-down-up', 'move-right-left']; // the list of random animations
var rand = Math.floor(Math.random() * 4) + 1; // random number
$img.each(function() { // attach event handler for each image
$(this).on('animationend', function(e) { // when animation on one image has ended
if (e.originalEvent.animationName == 'fade-in-out') { // check the animation's name
rand = Math.floor(Math.random() * 4) + 1; // get a random number
$(this).css('animation-name', 'none'); // remove animation on current element
if ($(this).next('img').length > 0) // if there is a next sibling
$(this).next('img').css('animation-name', 'fade-in-out, ' + anim[rand - 1]); // add animation on next sibling
else
$img.eq(0).css('animation-name', 'fade-in-out, ' + anim[rand - 1]); // else add animation on first image (loop)
}
});
});
$img.eq(0).css('animation-name', 'fade-in-out, ' + anim[rand - 1]); //add animation to 1st element on load
})
#wrapper {
height: 250px;
width: 300px;
position: relative;
}
img {
position: absolute;
z-index: 1;
bottom: 20px;
left: 10px;
opacity: 0;
transform-origin: left top; /* to be on the safe side */
animation-duration: 3s; /* increase only if you want duration to be longer */
animation-fill-mode: backwards; /* fill mode - better to not change */
animation-iteration-count: 1; /* no. of iterations - don't change */
animation-timing-function: ease; /* better to leave as-is but can be changed */
}
#keyframes fade-in-out {
0%, 100% {
opacity: 0;
}
33.33%, 66.66% { /* duration is 3s, so fade-in at 1s, stay till 2s, fade-out from 2s */
opacity: 1;
}
}
#keyframes zoom {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
}
#keyframes shrink {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(.5);
}
}
#keyframes move-down-up {
0%, 100% {
transform: translateY(0px);
}
50% {
transform: translateY(50px);
}
}
#keyframes move-right-left {
0%, 100% {
transform: translateX(0px);
}
50% {
transform: translateX(50px);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<img src="https://placehold.it/200/000000/ffffff" />
<img src="https://placehold.it/200/ff0000/ffffff" />
<img src="https://placehold.it/200/00ff00/ffffff" />
<img src="https://placehold.it/200/0000ff/ffffff" />
</div>

Immediately reverse CSS3 animation

When I add the .shown class to my #overlay I would like the opacity to fade in for 2secs, then immediately reverse and fade out for 2 seconds, creating a sort of "flashing" effect.
I tried just removing the class but that doesn't show any animation at all. This is my sample markup/CSS:
HTML:
<div id="outer">
This is some text
<div id="overlay"></div>
</div>
CSS:
#overlay {
...
opacity: 0;
transition: opacity 2s ease-in-out;
}
#overlay.shown {
opacity: 0.3;
}
Attemped JS:
// Wait 2 seconds from page load...
setTimeout(function() {
// Add shown class to trigger animation
document.getElementById("overlay").classList.add("shown");
// Want to remove the class and hoped this would reverse the animation...
// it doesn't
document.getElementById("overlay").classList.remove("shown");
}, 2000);
jsFiddle
use css animation with keyframes
#keyframes myFlash
{
0% {opacity:0;}
50% {opacity:0.3;}
100% {opacity:0;}
}
#-webkit-keyframes myFlash /* Safari and Chrome */
{
0% {opacity:0;}
50% {opacity:0.3;}
100% {opacity:0;}
}
#overlay {
...
opacity: 0;
}
#overlay.shown {
animation:myFlash 2s;
-webkit-animation:myFlash 2s; /* Safari and Chrome */
}
It looks like you could use a second timeout after the first animation completes..
// Wait 2 seconds from page load...
setTimeout(function() {
// Animate Forward
document.getElementById("overlay").classList.add("shown");
setTimeout(function(){
// Animate Back
document.getElementById("overlay").classList.remove("shown");
},2000);
}, 2000);
There are lots of changes i have done to achieve your out put please check following code
Your css
#outer {
width: 100px;
height: 100px;
position: relative;
}
#overlay {
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
background: #336699;
opacity: 0;
transition: opacity 2s ease-in-out;
}
#overlay.shown {
display: block;
opacity: 0.5;
}
Your js
setTimeout(function() {
$("#overlay").addClass("shown");
var def = $('#overlay').promise();
def.done(
function () {
$('body').stop().delay(5000).queue(function(){
$("#overlay").removeClass("shown");
});
});
}, 2000);
There was no delay between first and second so how it will show animation which you have done
Please check working demo.....Demo

How to delay basic HTML tooltip?

I was wondering if there was any way to delay just the classic HTML tooltip (no jQuery plugins like qTip, please). It's just a button as:
<input type="button" title="Click" value="My Button">
I want to know if there is any way to delay the title using pure JavaScript or client-side scripting. From what I have researched, it doesn't seem possible as it is part of the actual OS' GUI programming, which is impossible to access via browser scripting, but if there is any way that I just haven't come across yet, I would love to know! Thanks!
The browser controls the tool tip. If you want to make any changes you will have to create your own. Maybe by using the plug ins your refered to.
I'm 7+ years late, but just stumbled across the same desire and wrote a simple solution to delay tooltips using CSS.
Simply use transition-delay or animation keyframes for opacity. While the transition-delay is easiest, it has the trouble of delaying both reactions in and out of hover, afaik. Animation bypasses that and will only delay the start, for example:
/* Tooltip container */
.tooltip {
position: relative;
display: inline-block;
}
/* Tooltip text */
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: #444;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
/* Position the tooltip */
position: absolute;
z-index: 1;
top: 0;
left: 105%;
opacity: 1;
transition: opacity 1s;
}
.tooltip .tooltiptext::after {
content: " ";
position: absolute;
top: 50%;
right: 100%;
/* To the left of the tooltip */
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent #545 transparent transparent;
}
/*this is the IMPORTANT bit: hover with animation*/
.tooltip:hover .tooltiptext {
visibility: visible;
animation: tooltipkeys 1s 1; //here just change the 1s to you desired delay time!
opacity: 1;
}
#-webkit-keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-o-keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<div class="tooltip"><span class="tooltiptext">delayed tip</span>Example</div>
For more tips on tooltips you should check w3 schools for plenty of good advice.
This is a feature of the system which you cannot manipulate with HTML, CSS or JavaScript.
Keep in mind that different Operating Systems have different set of delays and styling to these tooltips, the best option to consider for better control (delay,styling,animation,etc) would be to implement your own tooltip.

Categories

Resources