VueJs no animation trigger on variable classname - css

I have a VueJs component and 2 classes with animations.
I have a v-bind:class on a div, but when the class changes, the animation doesn't run.
When the update_page computed property changes, the class changes as well.
What am I doing wrong?
The div:
<div
class="top-0 right-0 bottom-0
absolute h-full bg-primary"
:class="update_page ? 'detail-header-hide' : 'detail-header'"
></div>
The css class:
.detail-header {
width: 0;
animation: fadeIn 1500ms;
}
.detail-header-hide {
width: 100%;
animation: fadeIn 1500ms;
animation-direction: reverse;
}
#keyframes fadeIn {
0% {
width: 100%;
}
60% {
width: 100%;
}
100% {
width: 0;
}
}

I know snippet looks bad, but i mean problem will be at reusing one animation. Try to add one more to your project like me at snippet ('fadeOut')
let x = document.querySelector('div')
function toggle(){
x.classList.toggle('detail-header-hide')
x.classList.toggle('detail-header')
}
.detail-header {
width: 0;
animation: fadeIn 1500ms;
}
.detail-header-hide {
width: 100%;
animation: fadeOut 1500ms;
}
#keyframes fadeIn {
0% {
width: 100%;
}
60% {
width: 100%;
}
100% {
width: 0;
}
}
#keyframes fadeOut {
0% {
width: 0%;
}
60% {
width: 0%;
}
100% {
width: 100%;
}
}
<div
class="detail-header-hide"
>Some text Some text Some text Some text Some text</div>
<button onClick='toggle()'> btn </button>

Related

I'm trying to correct the animation duration and timeline of infinite flip, rotation, spin and disappearance of three images in pure CSS

I tested with the following answers:
Pure CSS rotate animation broken while in infinite loop
Stop infinite CSS3 animation and smoothly revert to initial state
CSS Image Fade Animation Only Runs First Time,
but the animation duration and timeline (for example, from step by step, from start to end) did not work. The three images need to be in the same place at once.
I wanted to use https://codepen.io/jay-bee-why/pen/Htejl, but unfortunately I do not want to use jQuery. I am CSS and JavaScript purist.
An image is worth a thousand words. You will understand easily the image. I also provide very small snippet code box.
.flipping-images
{
align-items: center;
display: flex;
flex-flow: row nowrap;
height: 80%;
justify-content: center;
/* opacity: 0; */
position: relative;
transform: translateX(100%);
width: 22%;
}
.show-l
{
animation: show-image 5s ease-in-out 300ms infinite;
left: 0;
position: absolute;
transform-origin: left;
}
.hide-l
{
animation: hide-image 5s ease-in-out 800ms infinite;
position: absolute;
transform-origin: left;
}
.hide-l2
{
animation: hide-image 5s ease-in-out 600ms infinite;
position: absolute;
transform-origin: right;
}
#keyframes hide-image
{
0%
{
left: 0;
transform: rotateY(0deg);
}
30%
{
left: 10%;
transform: rotateY(0deg);
}
50%
{
opacity: 1;
}
100%
{
left: -100%;
opacity: 0;
transform: rotateY(90deg);
}
}
#keyframes show-image
{
0%
{
left: 100%;
transform: rotateY(90deg);
}
30%
{
left: 110%;
transform: rotateY(90deg);
}
100%
{
left: 0%;
transform: rotateY(0deg);
}
}
<div class="flipping-images">
<img class="show-l" src="https://via.placeholder.com/432x864/fdc34f/FEFEFE?text=1">
<img class="hide-l2" src="https://via.placeholder.com/432x864/3e72ff/FEFEFE?text=2">
<img class="hide-l" src="https://via.placeholder.com/432x864/222222/FEFEFE?text=3">
</div>
I'm not sure I understand your image since it says the second image should disappear but it also says the animation is infinite. I hope it's working as you intended, if not just leave a comment on what needs to be fixed.
I'm using the animationend event to control the animations.
var counter = 1;
var div = document.querySelector('.flipping-images');
var images = document.querySelectorAll('.flipping-images img');
var showNext = function () {
counter++;
if (counter > 3) counter = 1;
div.classList.remove('image1', 'image2', 'image3')
div.classList.add('image'+counter);
};
for (var img of images) {
img.addEventListener('animationend', showNext);
img.addEventListener('click', showNext);
}
document.querySelector('#next').addEventListener('click', showNext);
.flipping-images {
perspective: 300px;
}
.flipping-images img {
display: none;
animation: rotate 5s linear 1;
}
.flipping-images.image1 img:nth-child(1),
.flipping-images.image2 img:nth-child(2),
.flipping-images.image3 img:nth-child(3) {
display: block;
}
.flipping-images.image2 img:nth-child(2) {
animation: rotate 5s linear infinite;
}
#keyframes rotate {
0% { transform: rotateY(-45deg); }
100% { transform: rotateY(45deg); }
}
button {
margin: 1em;
}
<div class="flipping-images image1">
<img src="https://via.placeholder.com/100x100/fdc34f/FEFEFE?text=1">
<img src="https://via.placeholder.com/100x100/3e72ff/FEFEFE?text=2">
<img src="https://via.placeholder.com/100x100/222222/FEFEFE?text=3">
</div>
<button id="next">Next</button>

CSS animation - revert on mouseout

I'm sure this must have been asked before and I've found related questions but I can't quite seem to crack this.
I have an element which receives a class and, on doing so, expands. Later, when that class is removed, it should revert (animate) back to its original width.
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 75px;
background: red;
position: fixed;
left: 0;
top: 0;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#side-bar:not(.contracted) {
animation: .5s side-bar-expand forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
to {
width: 75px;
}
}
<div id='side-bar' class='contracted'></div>
The expansion animation works fine. But the reversion animation doesn't happen; it just snaps back to its original properties, no anim.
Fiddle
What am I doing wrong?
[ EDIT ]
OK I should obviously have mentioned why I'm not doing this with transition. This is part of a wider set of dependent animations which run in a sequence, one after another. My understanding is that this sort of chronologically non-trivial situation is better for animation rather than transition.
UPDATE: (Removing the animation at the beginning)
let init = 0,
el = document.querySelector('#side-bar');
el.addEventListener('click', function() {
if (init < 1) {
init++;
el.classList.remove("init");
el.classList.add('contracted');
}
el.classList.toggle('contracted');
});
#side-bar {
height: 100%;
width: 75px;
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
}
#side-bar:not(.init) {
animation: .5s side-bar-expand forwards;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
from {
width: 350px;
}
}
<div id='side-bar' class='init'>Click me</div>
Just change to to from in side-bar-contract
#keyframes side-bar-expand { to { width: 350px; } }
#keyframes side-bar-contract { from { width: 350px; } }
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 75px;
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
}
#side-bar:not(.contracted) {
animation: .5s side-bar-expand forwards;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
from {
width: 350px;
}
}
<div id='side-bar' class='contracted'>Click me</div>
Why not just use a transition animation:
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 350px; /* have width at 350px when not contracted */
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
transition: width .5s; /* animate the width */
}
#side-bar.contracted {
width: 75px;
}
<div id='side-bar' class='contracted'>Click me</div>
If you need to use keyframes then you need to start the second one off at 350px - you start it at 75 to 75 which is why it doesn't animate:
let el = document.querySelector('#side-bar');
el.addEventListener('click', evt => el.classList.toggle('contracted'));
#side-bar {
height: 100%;
width: 75px;
background: #d4653c;
position: fixed;
left: 0;
top: 0;
padding: .8rem;
}
#side-bar:not(.contracted) {
animation: .5s side-bar-expand forwards;
}
#side-bar.contracted {
animation: .5s side-bar-contract forwards;
}
#keyframes side-bar-expand {
to {
width: 350px;
}
}
#keyframes side-bar-contract {
0% {
width: 350px;
}
100% {
width: 75px;
}
}
<div id='side-bar' class='contracted'>Click me</div>
First, I would recommend you do this with hover styles and css transition instead of an animation for something as simple as animating a single property.
.class {
width: 400px;
transition: width 1500ms ease-in-out;
}
.class:hover {
width: 100px;
}
CSS transition will actually stop part way through the transition and reverse to the initial size for you.
Second, I would recommend that you do not animate or transition the width property in CSS. Here's a great article about what properties you should avoid animating.
If you need to delay a transition from happening on other elements, you can use the transition-delay property. This property can also be applied in hover effects... including with hover effects on parent elements. So you may potentially have multiple hover effects in play at a given time to accomplish your desired effect.

How to make CSS animation to do vice versa after being completed?

The code below is a part of my code :
.myBox:hover::after {
animation-name: underline;
animation-duration: 350ms;
animation-fill-mode: forwards;
}
#keyframes underline {
from { width: 0; }
to { width: 100%; }
}
It works nicley, but I want to do it vice versa when animation completed, I mean when it finished then width should be 0 again, In fact for this part I want to do it when my element is not hovered. Which property can help me ?
You need to use alternate and run 2 iterations of the animation:
.box {
height:200px;
background:red;
animation: underline 500ms alternate 2 forwards;
}
#keyframes underline {
from { width: 0; }
to { width: 100%; }
}
<div class="box">
</div>
Or consider the use of transition if you want the effect on hover:
.box {
height: 200px;
background: red;
width: 0;
transition: 500ms;
}
body:hover .box {
width: 100%;
}
<div class="box">
</div>
You can specify multiple values for animations rather then from and to using percentage:
#keyframes underline {
0%, 100% { width: 0; }
50% { width: 100%; }
}
More detailed information can be found here.
.myBox:hover::after {
animation-name: underline infinite;
animation-duration: 350ms;
animation-fill-mode: forwards;
}
#keyframes underline {
from { width: 0; }
to { width: 100%; }
}
You infinite for this

Z-index change within #keyframes animation causing a pop

I would like each <div> to stay on screen for 8 sec before it fades out.
Also I would like them to fade into each other, opposed to fading to black and then the other fades in.
This works great thanks to #giovannipds except for a pop and not on screen for 8 sec. If you remove the z-index change it transitions clean.
.slider {
line-height: 1.5;
height: 200px;
margin: 20px auto;
position: relative;
width: 300px;
}
.slide {
padding: 20px;
position: absolute;
width: 100%;
height: 100%;
}
.slide,.slide a {
color: #fff;
}
.slide1 {
animation: fade 8s infinite;
background: red;
}
.slide2 {
animation: fade2 8s infinite;
background: blue;
}
#keyframes fade
{
0% { opacity: 1 ; z-index: 2; }
33.333% { opacity: 0; z-index: 1; }
66.666% { opacity: 0; z-index: 1; }
100% { opacity: 1; z-index: 2; }
}
#keyframes fade2
{
0% { opacity: 0; z-index: 1; }
33.333% { opacity: 1; z-index: 2; }
66.666% { opacity: 1; z-index: 2; }
100% { opacity: 0; z-index: 1; }
}
<div class="slider">
<div class="slide slide1">
<ul>
<li>Google</li>
<li>Globo.com</li>
</ul>
</div>
<div class="slide slide2">
<ul>
<li>Love Mondays</li>
<li>Hotmail</li>
</ul>
</div>
</div>
Old question but I was recently confronted with the same POP problem and I managed to solve it by separating the image and caption markup on each slide and by assigning separate cross-fade animations to each:
image animation (with opacity but without z-index) => just like fade and fade2 in the snippet above but without z-index; this actually solved the POP
caption animation (with both opacity and z-index) => just like fade and fade2 in the snippet above, this would address links or any other HTML you might want on top of image

CSS animations, slide in on 'block' and out on 'none'

I'm building something that is using the css slide animation to have some text slide in when the text display is set to "block", but I was wondering how I would go about doing the reverse (sliding it out) when it is set to "none"? Is it possible to slide in and slide out with CSS animations, or would I have to use Javascript?
Hope that makes sense! Let me know if you have any questions!
JSfiddle of give you a better idea https://jsfiddle.net/qjwqL236/
Thanks!
And code below:
document.getElementById("in-button").onclick = function(){
document.getElementById("text-container").style.display = "block";
}
document.getElementById("out-button").onclick = function(){
document.getElementById("text-container").style.display = "none";
}
#text-container{
height: 30px;
width:300px;
color: white;
background-color: blue;
float:left;
display:none;
position: relative;
left: -300px;
animation: slide 0.5sforwards;
-webkit-animation: slide 0.5s forwards;
}
#-webkit-keyframes slide {
100% {
left: 0;
}
}
#keyframes slide {
100% {
left: 0;
}
}
#in-button{
float:left;
}
#out-button{
float:left;
}
<button id="in-button">
Make Div slide in
</button>
<button id="out-button">
Make Div slide out?
</button>
<br>
<br>
<div id="text-container">
This is some text in a div.
</div>
In your case. It's easier to use transition than animation. This is how it works.
Everytime the button is click. It changes the value of the left property.
<button id="in-button">
Make Div slide in
</button>
<button id="out-button">
Make Div slide out?
</button>
<br>
<br>
<div id="text-container">
This is some text in a div.
</div>
CSS
#text-container{
height: 30px;
width:300px;
color: white;
background-color: blue;
float:left;
position: relative;
left: -400px;
transition: all 0.3s linear
}
#in-button, #out-button{
float:left;
}
JS
var tC = document.getElementById('text-container');
document.getElementById("in-button").onclick = function(){
tC.style.left = '0';
}
document.getElementById("out-button").onclick = function(){
tC.style.left = '-400px';
}
Working fiddle: https://jsfiddle.net/qjwqL236/1/
You should use css translate because it's more performant than positioning and then you need an animation in and an animation out that you can trigger with a class change instead of the display property.
document.getElementById("in-button").onclick = function(){
document.getElementById("text-container").className = "in";
}
document.getElementById("out-button").onclick = function(){
document.getElementById("text-container").className = "out";
}
#text-container{
height: 30px;
width: 300px;
color: white;
background-color: blue;
transform: translateX(-310px);
}
#text-container.in {
animation: in 0.5s both;
-webkit-animation: in 0.5s both;
}
#text-container.out {
animation: out 0.5s both;
-webkit-animation: out 0.5s both;
}
#-webkit-keyframes in {
100% {
transform: translateX(0);
}
}
#keyframes in {
100% {
transform: translateX(0);
}
}
#-webkit-keyframes out {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-310px);
}
}
#keyframes out {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-310px);
}
}
#in-button{
float:left;
}
#out-button{
float:left;
}
<button id="in-button">
Make Div slide in
</button>
<button id="out-button">
Make Div slide out?
</button>
<br>
<br>
<div id="text-container">
This is some text in a div.
</div>
Here is what you can do using animations. You need to create a slide-out animation just like you have a slide-in.
Note that it won't slide in/out automatically when you change the display to none or block.
document.getElementById("in-button").onclick = function() {
document.getElementById("text-container").setAttribute('class', 'slide-in');
}
document.getElementById("out-button").onclick = function() {
document.getElementById("text-container").setAttribute('class', 'slide-out');
}
#text-container {
height: 30px;
width: 300px;
color: white;
background-color: blue;
float: left;
position: relative;
left: -300px;
}
.slide-in {
animation: slide-in 0.5s forwards;
-webkit-animation: slide-in 0.5s forwards;
}
.slide-out {
animation: slide-out 0.5s forwards;
-webkit-animation: slide-out 0.5s forwards;
}
#-webkit-keyframes slide-in {
100% {
left: 0;
}
}
#keyframes slide-in {
100% {
left: 0;
}
}
#-webkit-keyframes slide-out {
0% {
left: 0;
}
100% {
left: -300px;
}
}
#keyframes slide-out {
0% {
left: 0;
}
100% {
left: -300px;
}
}
#in-button {
float: left;
}
#out-button {
float: left;
}
<button id="in-button">
Make Div slide in
</button>
<button id="out-button">
Make Div slide out?
</button>
<br>
<br>
<div id="text-container">
This is some text in a div.
</div>

Resources