It is necessary that when the button is pressed, there is an animation of the appearance and hiding of the text. I wrote the following code, but when the page renders, the text hide animation is triggered.
Can I turn off the animation that fires when the page is rendered? Sample code below.
import React, { useState } from "react";
import "./styles.css";
export default function App() {
let [vision, setVision] = useState(true);
let hangler = () => {
setVision(!vision);
};
return (
<div className="App">
<h1 className={vision ? "Text hidden" : "Text shown"}>Hello World</h1>
<button onClick={hangler}>click</button>
</div>
);
}
Css:
.App {
font-family: sans-serif;
text-align: center;
}
.Text {
color: blue;
}
.hidden {
animation: fadeOut ease 1.5s;
animation-fill-mode: forwards;
}
.shown {
animation: fadeIn ease 1.5s;
animation-fill-mode: forwards;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
visibility: hidden;
}
}
This code is at this link
Your classes are inverted, it should be vision ? "Text shown" : "Text hidden".
This will still animate the header to fade in. If it's ok then you are done.
However, if you don't want the initial animation. You can set animation-duration: 0s; to short-circuit it and remove the property after the load but this is not elegant.
For something that simple I would use transitions instead.
.hidden {
opacity: 0;
visibility: hidden;
transition: opacity 1.5s, visibility 1.5s;
}
.shown {
opacity: 1;
visibility: visible;
transition: opacity 1.5s, visibility 1.5s;
}
Related
I'm struggling with creating split animation with two icons. I want to split icons with some translation in X axis after hover on container but it seems that I'm doing something wrong. On codepen its not even animating, in my app its working but icons return to their original position after animation, forwards property doesn't help.
<html>
<head>
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<div #mouseenter="showButtons()" #mouseleave="hideButtons()" class="container">
<transition name="icon-left">
<span v-show="show_buttons"> A </span>
</transition>
<transition name="icon-right">
<span v-show="show_buttons"> B </span>
</transition>
</div>
</div>
</body>
</html>
const { createApp } = Vue
createApp({
data() {
return {
show_buttons: false,
}
},
methods: {
showButtons() {
this.show_buttons = true
},
hideButtons() {
this.show_buttons = false
}
}
}).mount('#app')
.container {
display: flex;
justify-content: center;
align-items: center;
width: 800px;
height: 400px;
border: 1px black solid ;
}
.icon-left-enter-from {
opacity: 0;
transform: translate(0px);
}
.icon-left-enter-active {
transition: all 0.3s forwards;
}
.icon-left-enter-to {
opacity: 1;
transform: translate(-200px);
}
.icon-right-enter-from {
opacity: 0;
transform: translate(0px);
}
.icon-right-enter-active {
transition: all 0.3s forwards;
}
.icon-right-enter-to {
opacity: 1;
transform: translate(200px);
}
Here is live codepen https://codepen.io/dymek662/pen/bGMxJwY
Here I have it working: https://codepen.io/yoduh/pen/yLjRRRN
I slowed the left one down so you can see the opacity change more clearly. Here's all the relevant code:
<transition name="icon-left" class="left">
<span v-show="show_buttons"> A </span>
</transition>
<transition name="icon-right" class="right">
<span v-show="show_buttons"> B </span>
</transition>
.icon-left-enter-from {
opacity: 0
}
.icon-left-enter-active {
animation: left-translate 3s;
transition: opacity 3s;
}
.left {
transform: translate(-200px);
}
#keyframes left-translate {
0% {
transform: translate(0px);
}
100% {
transform: translate(-200px);
}
}
.icon-right-enter-active {
animation: right-translate 0.3s;
transition: opacity 0.3s;
}
.right {
transform: translate(200px);
}
#keyframes right-translate {
0% {
transform: translate(0px);
}
100% {
transform: translate(200px);
}
}
"forwards" is not used with transition, but with animation instead, specifically it is shorthand for animation-fill-mode. If you want to maintain the end state, you should use animation. However, animation-fill-mode: forwards only holds the final animation state for as long as the animation property exists, e.g. for as long as a hover event is ongoing. In your case, once the animation is complete the animation property is removed. There is a workaround which is to set the "default" state of your element to match the final state of your animation. That's why I added a separate left and right class to always apply the translate transformation as long as the elements are visible (and not currently animating)
I'm animating in text as below, and want an effect where the entire div shows from the top and as it translates up, the top items are shown first etc.
I assume this could be done with an animated scale on the div also, however please take a look:
const fadeIn = keyframes`
0%
{
opacity: 0;
transform: translateY(100px);
}
50%
{
opacity: 0.25;
}
100%
{
opacity: 1;
transform: translateY(0px);
}
`;
const SubTextContainerChild = styled.div`
height: 100%;
top: 0;
animation: ${fadeIn} 2s;
overflow: hidden;
`;
If I understand correctly you want the animation to be done one element after the other, in order?
if this is the case, you have to use either a library like GSAP, or indicate to each child the delay it must have to do the animation :
const SubTextContainerChild = styled.div`
height: 100%;
top: 0;
& > p {
animation: ${fadeIn} 2s forwards;
opacity: 0;
&:nth-child(1) {
animation-delay: 0.4s;
}
&:nth-child(2) {
animation-delay: 0.8s;
}
&:nth-child(3) {
animation-delay: 1.2s;
}
}
overflow: hidden;
`;
I added an opacity: 0 in order not to have the text displayed before the animation. And forwards to let the styles of 100% keyframe stay after the animation.
Display None to Display Block animation is working
but I need the animation to work this way also
- Animation Display Block to Display None
the animations is not working when action go from block to Display None
have an idea what can be the problem?
#dboldDiv,#dbnewDiv {
animation: anim .4s ease-in-out;
}
#keyframes anim {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
transform: scale(0.8);
}
100% {
opacity: 1;
transform: scale(1);
}
}
display is not animatable property
There are two category of properties animatable and not animatable
you can check animated properties list from here :
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animated_properties
display:none won't work smooth.
For fluent disappearing try using visibility:hidden, or if just keep 0 opacity and add pointer-events:none, so the object doesn't catch any mouse events.
document.getElementById('hide').addEventListener('click', function(){
document.getElementById('link').className = 'hide';
});
document.getElementById('show').addEventListener('click', function(){
document.getElementById('link').className = 'show';
});
document.getElementById('link').addEventListener('click', function(){
alert('clicked');
});
#link {
display:block;
}
#link.show {
animation: anim1 .4s;
animation-fill-mode: forwards;
}
#link.hide {
animation: anim2 .4s;
animation-fill-mode: forwards;
animation-direction: reverse;
}
#keyframes anim1 {
0% {
opacity: 0.3;
pointer-events:none;
}
100% {
opacity: 1;
pointer-events:all;
}
}
#keyframes anim2 {
0% {
opacity: 0.3;
pointer-events:none;
}
100% {
opacity: 1;
pointer-events:all;
}
}
<button id="hide">Hide</button>
<button id="show">Show</button>
hidding & showing
I'm trying to create a visual transition between content changes in a toy SPA I'm writing. To that end, I define a simple class for animating the opacity of an element.
.fade {
transition: opacity 1.5s;
}
In my render function, I now change the opacity of my outlet div after content changes like so:
function render(content) {
var outlet = document.getElementById("outlet");
outlet.classList.remove("fade");
outlet.style.opacity = 0;
outlet.innerHTML = content;
outlet.classList.add("fade");
outlet.style.opacity = 1;
}
Unfortunately, the animation never fires. When I delay changing the opacity to 1 via setTimeout for 10ms, say, it works sometimes if I don't change the content again while the animation is still running, indicating a timing issue/race condition.
I used a similar approach in the past to fade out messages, but there I intentionally delayed changing the opacity by a few seconds so users could read the message before it starts fading out.
Pure CSS animation fadeIn
li {
position: absolute;
top: 50%;
left: 50%;
margin-top: -75px;
}
.logo {
width: 300px;
height: 150px;
background: red;
margin-left: -150px;
z-index: 30;
-webkit-animation: fade-in-slogan 4s .2s ease-in forwards;
-moz-animation: fade-in-slogan 4s .2s ease-in forwards;
animation: fade-in-slogan 4s .2s ease-in forwards;
}
.menu {
width: 600px;
height: 150px;
background: blue;
margin-left: -300px;
opacity: 0;
-webkit-animation: fade-in-menu 3s 4s ease-out forwards;
-moz-animation: fade-in-menu 3s 4s ease-out forwards;
animation: fade-in-menu 3s 4s ease-out forwards;
}
#-webkit-keyframes fade-in-slogan {
0% { opacity: 0; }
30% { opacity: 1; }
50% { opacity: 1; }
70% { opacity: 1; }
100% { opacity: 0; }
}
#-webkit-keyframes fade-in-menu {
0% { display: block; opacity: 0; }
30% { display: block; opacity: .3; }
60% { display: block; opacity: .6; }
80% { display: block; opacity: .8; }
100% { display: block; opacity: 1; }
}
<ul class"main">
<li class="logo"></li>
<li class="menu"></li>
</ul>
Try this, I hope this will solve the issue
.fade{
animation-name: example;
animation-duration: 4s;}
#keyframes example {
from {opacity:1}
to {opacity:0;}
}
div{
width:200px;
height:200px;
background:#000;
}
<html>
<head>
</head>
<body>
<div class="fade"></div>
</body>
</html>
I've solved it now inspired by Muhammad's answer. I defined the fade class as follows:
.fade {
animation-name: fadein;
animation-duration: 1.25s;
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
Then in the render function, I do
function render(content) {
outlet.classList.remove("fade");
outlet.innerHTML = "";
setTimeout(() => {
outlet.classList.add("fade");
outlet.appendChild(content);
}, 100);
}
Even though this adds an additional delay before the new content actually starts to fade in, it seems the most elegant and concise solution to me.
I have a one pager that shows one page at a time and that uses animation when transitioning from one page to the next. It works like this:
The user clicks on a button
An ajax call is done and while waiting for the response the page fades out (opacity: 0)
If the server does not respond within 500 msec after the fade out finishes a spinner fades in and stays there until the ajax call finishes
When receiving the response the spinner is faded out and the new page fades in.
I currently use a CSS 3 transition animation on the opacity of the page. This issue is however that during the time the spinner is visible the user can still interact with the (invisible) form of the page that just faded out (it's not gone, it's just invisible using opacity).
So I would like to have a CSS only solution that sets the page to visibility: hidden at the end of the transition (I cannot use display: none). What would be the way to go here?
Based on the answer of #Rev I created a proof of concept. It works nicely (see fiddle).
When you add the class 'fadeOut' to the div it'll fade out and end with a visibility: hidden state. Remove the class and it fades in again. You can tell that it is really hidden by hovering your mouse over it: if hidden it will no longer give the "text selection" mouse pointer.
HTML
<div class="page">
Lorem ipsum etc etc etc.
</div>
CSS
.page {
-moz-animation-name: fadeIn;
-webkit-animation-name: fadeIn;
-ms-animation-name: fadeIn;
animation-name: fadeIn;
-moz-animation-duration: 1s;
-webkit-animation-duration: 1s;
-ms-animation-duration: 1s;
animation-duration: 1s;
-moz-animation-timing-function: ease-in-out;
-webkit-animation-timing-function: ease-in-out;
-ms-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
-ms-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
.page.fadeOut {
-moz-animation-name: fadeOut;
-webkit-animation-name: fadeOut;
-ms-animation-name: fadeOut;
animation-name: fadeOut;
}
#-moz-keyframes fadeIn { 0% { opacity: 0; visibility: hidden; } 100% { opacity: 1; visibility: visible; }}
#-webkit-keyframes fadeIn { 0% { opacity: 0; visibility: hidden; } 100% { opacity: 1; visibility: visible; }}
#-ms-keyframes fadeIn { 0% { opacity: 0; visibility: hidden; } 100% { opacity: 1; visibility: visible; }}
#-keyframes fadeIn { 0% { opacity: 0; visibility: hidden; } 100% { opacity: 1; visibility: visible; }}
#-moz-keyframes fadeOut { 0% { opacity: 1; visibility: visible; } 100% { opacity: 0; visibility: hidden; }}
#-webkit-keyframes fadeOut { 0% { opacity: 1; visibility: visible; } 100% { opacity: 0; visibility: hidden; }}
#-ms-keyframes fadeOut { 0% { opacity: 1; visibility: visible; } 100% { opacity: 0; visibility: hidden; }}
#-keyframes fadeOut { 0% { opacity: 1; visibility: visible; } 100% { opacity: 0; visibility: hidden; }}
Some additional remarks:
If you have child elements in the .page element that have explicitly visibility: visible set on them then they will react to interaction via mouse. This is because hey are not hidden just invisible due to the opacity: 0. The twitter bootstrap collapse plugin does this for instance. You can solve this by setting their visibility to inherit instead of visible. This will cause them to only be visible if their parent is. For instance the collapse plugin can be made to behave using this additional css:
.page .collapse {
visibility: inherit;
}
This does not work in IE 9 and below.
You need the browser prefixes as seen in my code to make this work. I tested this without the prefixes and both the latest chrome (42) and firefox (37) did not work without them. This is ugly but can be made easier by using something like SASS with Compass. Here's the same code using that approach:
SASS with Compass
.page {
#include animation(fadeIn 1s ease-in-out forwards);
}
.page.fadeOut {
#include animation-name(fadeOut);
}
#include keyframes(fadeIn) {
0% { opacity: 0; visibility: hidden; }
100% { opacity: 1; visibility: visible; }
}
#include keyframes(fadeOut) {
0% { opacity: 1; visibility: visible; }
100% { opacity: 0; visibility: hidden; }
}
Not completely JS-only, but when you start the fade animation, also add a class to the form container with the following CSS:
.disableMouse * {
pointer-events: none;
}
This will disable clicks (but it won't disable scrolling). Works in all current browsers, but IE support was only added in version 11. So this may not be the best option for you if you need to support IE10 and earlier.
Pretty sure I can't be done with CSS alone. You could look in to the JavaScript's transitionend.
You could look in to CSS animations rather than transitions as well. I know you can't transition visibility: hidden; but you might be able to set up an animation key frame at 100% to do this.
If your only intent is to disable interaction, you could use pointer-events: none (IE11+) on your page, or have a floating blocker over the top, like;
.page.loading {
position: relative;
}
.page.loading:after {
content: ' ';
display: block;
position: relative;
background: white;
top: 0;
right: 0;
bottom: 0;
left: 0;
}