How to achieve reverse animation on mouse out using keyframes - css

I am trying to add scale up animation on a div.
I tried this using both transition and animation property.
In case of transition you can notice that when hovered out the animation is smoothly reversed. However, this doesn't happen when using animation property (the div transitions back to initial width instantly)
Can someone tell me:
Why this behaviour in case of animation only?
How can I achieve the same using animation property?
.animations {
display: flex;
padding: 80px;
width: 100vw;
height: 100vh;
background: linear-gradient(to right, #f3d2d2, white, #cee5f3);
}
.animations > div {
width: 200px;
height: 200px;
margin: 40px;
font-family: system-ui;
display: flex;
flex-direction: column;
align-items: center;
}
.animations > p {
color: black;
flex: 1;
text-align: center;
}
.animations .animated-box {
flex: 2;
width: 100%;
background: grey;
cursor: pointer;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.animated-box.scale-up {
}
.animated-box.scale-up:hover {
animation: scale-up 0.5s ease forwards;
transform: scale(1);
}
.animated-box.scale-up-with-mouseout {
transition: transform 0.5s ease-in;
}
.animated-box.scale-up-with-mouseout:hover {
transform: scale(1.2);
}
#keyframes scale-up {
100% {transform: scale(1.2)};
0%{transform: scale(1)};
}
<div class="animations">
<div>
<div class="animated-box scale-up">Hover me</div>
<p>Scale up (with keyframes)</p>
</div>
<div>
<div class="animated-box scale-up-with-mouseout">Hover me</div>
<p>Scale up (with transition)</p>
</div>
</div>

invert this part only
#keyframes scale-up {
100% {transform: scale(1.2)};
0%{transform: scale(1)};
}
and to fix the animation when mouse out add a new keyframe
#keyframes scale-down {
0% {transform: scale(1.2)};
100%{transform: scale(1)};
}
and apply it to the class .animated-box.scale-up
.animated-box.scale-up {
animation: scale-down 0.5s ease forwards;
}
.animations {
display: flex;
padding: 80px;
width: 100vw;
height: 100vh;
background: linear-gradient(to right, #f3d2d2, white, #cee5f3);
}
.animations > div {
width: 200px;
height: 200px;
margin: 40px;
font-family: system-ui;
display: flex;
flex-direction: column;
align-items: center;
}
.animations > p {
color: black;
flex: 1;
text-align: center;
}
.animations .animated-box {
flex: 2;
width: 100%;
background: grey;
cursor: pointer;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
color: white;
}
.animated-box.scale-up {
animation: scale-down 0.5s ease forwards;
}
.animated-box.scale-up:hover {
animation: scale-up 0.5s ease forwards;
}
.animated-box.scale-up-with-mouseout {
transition: transform 0.5s ease-in;
}
.animated-box.scale-up-with-mouseout:hover {
transform: scale(1.2);
}
#keyframes scale-up {
100% {transform: scale(1.2)};
0%{transform: scale(1)};
}
#keyframes scale-down {
0% {transform: scale(1.2)};
100%{transform: scale(1)};
}
<div class="animations">
<div>
<div class="animated-box scale-up">Hover me</div>
<p>Scale up (doesn't work)</p>
</div>
<div>
<div class="animated-box scale-up-with-mouseout">Hover me</div>
<p>Scale up (works)</p>
</div>
</div>

Related

CSS animation-fill-mode: forwards not working

I am trying to create a codepen where I have a circle that moves in a circular path based on its parent div getting rotated. I rotate the text inside the circle in the opposite direction at the same rate so that it create the allusion that the text does not rotate at all and stay upright. However, I would like to add an animation that pulses when I am hovering over the circle. I was able to do this, but the problem is that the text is then changing back to its original rotation (which is based on the orientation of the circle, and the text will not be upright).
Here is my code for anyone to replicate
HTML
<div class="container">
<div class="parent">
<div class="child">
<p>Word</p>
</div>
</div>
</div>
CSS
.container {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: blue;
}
.parent {
display: flex;
align-items: center;
/* justify-content: center; */
background-color: red;
width: 600px;
height: 600px;
animation: square-rotate 30s linear infinite;
pointer-events: none;
}
#keyframes square-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.child {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
background-color: white;
width: 100px;
height: 100px;
border-radius: 50%;
pointer-events: auto;
}
p {
animation: text-rotate 30s linear infinite forwards;
animation-fill-mode: forwards;
pointer-events: auto
}
#keyframes text-rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
.parent:hover {
background-color: green;
animation-play-state: paused;
}
.child:hover p {
/* animation-play-state: paused; */
animation: pulse 1s linear infinite;
}
#keyframes pulse {
0% {
transform:scale(1);
}
50% {
transform:scale(1.3);
}
100% {
transform:scale(1);
}
}
What exactly am I missing here? I need the text to not reset back to its rotation according to the white circle and just go through the pulse animation at whatever rotation it was in when my pointer hovers over the element.

Elements of my spinner also dim when I dim the entire page for a loading element

I have implemented a loading spinning icon which is overlaid on the page.
It looks fine but when I try to darken the entire page by using
background-color: rgba(0, 0, 0, 0.4);
in the .spinner-container element, the bands of the loading element dim also...
See these pictures...
I would like to keep these bright vibrant colors on top of the dimmed gray background.
Any ideas what I can implement to change this?
.spinner-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
}
#keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.three-dots span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.three-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.three-dots span:nth-child(3) {
animation-delay: 0.4s;
}
.spinner {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
}
.spinner-sector {
border-radius: 50%;
position: absolute;
width: 100%;
height: 100%;
border: 15px solid transparent;
mix-blend-mode: overlay;
}
.spinner-text {
font-size: 2em;
}
.spinner-sector-blue {
animation: rotate 2s ease-out infinite;
border-top: 15px solid lightblue;
}
.spinner-sector-red {
animation: rotate 2.5s ease-in infinite;
border-top: 15px solid lightcoral;
}
.spinner-sector-green {
animation: rotate 1.5s ease-in-out infinite;
border-top: 15px solid lightgreen;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes loading-opacity {
0%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.5;
}
50% {
opacity: 0.1;
}
}
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div class="spinner-container">
<div class="spinner">
<div class="spinner-text three-dots">Loading<span>.</span><span>.</span><span>.</span></div>
<div class="spinner-sector spinner-sector-red"></div>
<div class="spinner-sector spinner-sector-blue"></div>
<div class="spinner-sector spinner-sector-green"></div>
</div>
</div>
</body>
</html>
You are using mix-blend-mode: overlay; (documentation) on your .spinner-sector elements, which is blending the vibrant colours with the darkened page below.
Removing that gives you:
.spinner-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
}
#keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.three-dots span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.three-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.three-dots span:nth-child(3) {
animation-delay: 0.4s;
}
.spinner {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
}
.spinner-sector {
border-radius: 50%;
position: absolute;
width: 100%;
height: 100%;
border: 15px solid transparent;
}
.spinner-text {
font-size: 2em;
}
.spinner-sector-blue {
animation: rotate 2s ease-out infinite;
border-top: 15px solid lightblue;
}
.spinner-sector-red {
animation: rotate 2.5s ease-in infinite;
border-top: 15px solid lightcoral;
}
.spinner-sector-green {
animation: rotate 1.5s ease-in-out infinite;
border-top: 15px solid lightgreen;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes loading-opacity {
0%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.5;
}
50% {
opacity: 0.1;
}
}
<div class="spinner-container">
<div class="spinner">
<div class="spinner-text three-dots">Loading<span>.</span><span>.</span><span>.</span></div>
<div class="spinner-sector spinner-sector-red"></div>
<div class="spinner-sector spinner-sector-blue"></div>
<div class="spinner-sector spinner-sector-green"></div>
</div>
</div>
Alternatively, to keep the blending effect, you could switch to an option that doesn't darken the loading animation, e.g. hard-light
.spinner-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.4);
}
#keyframes blink {
0% {
opacity: 0.2;
}
20% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
.three-dots span {
animation-name: blink;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.three-dots span:nth-child(2) {
animation-delay: 0.2s;
}
.three-dots span:nth-child(3) {
animation-delay: 0.4s;
}
.spinner {
position: relative;
display: flex;
justify-content: center;
align-items: center;
width: 300px;
height: 300px;
}
.spinner-sector {
border-radius: 50%;
position: absolute;
width: 100%;
height: 100%;
border: 15px solid transparent;
mix-blend-mode: hard-light;
}
.spinner-text {
font-size: 2em;
}
.spinner-sector-blue {
animation: rotate 2s ease-out infinite;
border-top: 15px solid lightblue;
}
.spinner-sector-red {
animation: rotate 2.5s ease-in infinite;
border-top: 15px solid lightcoral;
}
.spinner-sector-green {
animation: rotate 1.5s ease-in-out infinite;
border-top: 15px solid lightgreen;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes loading-opacity {
0%,
100% {
opacity: 1;
}
25%,
75% {
opacity: 0.5;
}
50% {
opacity: 0.1;
}
}
<div class="spinner-container">
<div class="spinner">
<div class="spinner-text three-dots">Loading<span>.</span><span>.</span><span>.</span></div>
<div class="spinner-sector spinner-sector-red"></div>
<div class="spinner-sector spinner-sector-blue"></div>
<div class="spinner-sector spinner-sector-green"></div>
</div>
</div>

Unable to animate with transform functions

I've been trying to animate my image with almost all transform functions without success.
After googling it appeared that setting with: auto might be the cause.
But removing it from my style doesn't change anything at all. Still no animation.
Here you have my code :
html,
body {
height: 100%;
}
body {
margin: 0;
}
.logo-container {
display: flex;
height: 100%;
background-color: red;
justify-content: center;
align-items: center;
}
.logo {
width: auto;
transition: scale-me 1.5s ease-in;
animation-iteration-count: infinite;
}
#keyframes scale-me {
0% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
<body>
<div class="logo-container">
<img src="../images/Green-Monster-8-icon-128.png" class="logo" />
</div>
</body>
What is wrong in my code ?
Thanks in advance.
You have to use animation instead of transition
html,
body {
height: 100%;
}
body {
margin: 0;
}
.logo-container {
display: flex;
height: 100%;
background-color: red;
justify-content: center;
align-items: center;
}
.logo {
width: auto;
animation: scale-me 1.5s ease-in;
animation-iteration-count: infinite;
}
#keyframes scale-me {
0% {
transform: scale(1);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
<body>
<div class="logo-container">
<img src="https://via.placeholder.com/50" class="logo" />
</div>
</body>

CSS Transitions on menu items not working

it's the first time I'm using css transitions/transformations and it's not working out that well.
I'm simply trying to translate from bottom to position each entry of a toggled menu, but I'm getting strange results.
When I run the code within my app it executes the transition only on the first item of the list instead of all items.
When I run the same code from jsfiddle the transition doesn't work at all on any item.
Please see my jsfiddle here
I've looked at the documentation, at so many different examples and at many other solutions for similar issues. I've tried them all, defying height, removing display, but nothing seems to make any difference
<header>
<a id="menu">
<i class="fas fa-bars"></i>
</a>
</header>
<nav class="nav nav-sm">
<ul class="nav__list">
<li class="nav__item">ABOUT</li>
<li class="nav__item">SKILLS</li>
<li class="nav__item">WORKS</li>
</ul>
</nav>
header {
width: 100%;
z-index: 3;
display: flex;
align-items: center;
justify-content: right;
background-color: #68c7c1;
min-height: 56px;
transition: min-height 0.3s;
}
header #menu {
margin-left: auto;
margin-right:10px;
color: #eceeef;
font-size: 2em;
}
.nav {
width: 100%;
height: auto;
position: absolute;
z-index: 2;
display: flex;
flex-wrap: wrap;
background-color: #68c7c1;
}
.nav-sm, .nav-lg { display: none; }
.nav-sm.open {
display: flex;
flex-wrap: wrap;
align-items: center;
height: calc(100% - 56px);
margin-top: -2px;
}
.nav__list, .nav__item { width: 100%; }
.nav__list {
display: flex;
flex-wrap: wrap;
}
.nav__item {
height:50px;
display: flex;
flex-wrap: nowrap;
justify-content: center;
}
.nav__item a {
text-decoration: none;
text-align: center;
font-size: 1.2em;
color: #eceeef;
}
.nav-sm .nav__list .nav__item {
color: red;
transition: -transform 3s ease-in-out;
-moz-transition: -moz-transform 3s ease-in-out;
-webkit-transition: -webkit-transform 3s ease-in-out;
}
.nav-sm.open .nav__item {
padding-bottom: 80px;
font-size: 2em;
transform: translate(0,-50px);
-moz-transform: translate(0,-50px);
-webkit-transform: translate(0,-50px);
}
An example of what I'm trying to achieve is something similar to the menu of this portfolio.
What are you exactly trying to do ? animation ? transition when clicked ?
here is an example of how to write animation via css :
div {
width: 100px;
height: 100px;
background-color: red;
animation-name: example;
animation-duration: 4s;
}
/* Standard syntax */
#keyframes example {
from {background-color: red;}
to {background-color: yellow;}
}
The way they did it in the example you provided is with js with some animation library, if you'd inspect their code you can see it happening.
To achieve this animation we'll have to make use of the delay property either way using animation or transition and you will have to add a delay on every item, so when you add a new item to the menu you'll have to add a delay to that item, we can automate this using js
Here's a demo using transition, the timing function, delay and the duration will need extra care, i'll leave that you to adjust to your desired end result.
var menu = document.querySelector("#menu");
var nav = document.querySelector(".nav-sm");
function openMenu(e) {
nav.classList.toggle("open");
e.stopPropagation();
};
function closeMenu(e) {
nav.classList.remove("open");
};
menu.addEventListener("click", openMenu);
#menu {
font-size: 2rem;
margin: 30px;
display: flex;
flex-direction: column;
align-items: flex-end;
}
ul {
border: 1px solid;
list-style: none;
padding: 10px;
margin: 30px;
}
li {
opacity: 0;
transform: translateY(5px);
margin: 20px 0;
text-align: center;
}
a {
text-decoration: none;
padding: 5px 30px;
background: dodgerblue;
color: white;
}
.open li:nth-child(1) {
transition: all .4s linear;
}
.open li:nth-child(2) {
transition: all .4s .2s linear;
}
.open li:nth-child(3) {
transition: all .4s .4s linear;
}
.open li {
opacity: 1;
transform: translateY(0px);
}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<div id="menu">
<i class="fas fa-bars"></i>
</div>
<ul class="nav-sm">
<li>ABOUT</li>
<li>SKILLS</li>
<li>WORKS</li>
</ul>
So, I managed to achieve what I wanted by mixing both suggestions :)
Please see the result in this jsfiddle.
The reason why the transition wasn't working it's because I'm using display:none on the .nav. This problem is resolved by using animation instead and applying a delay on each list element.
Thank you for both answers!
header {
width: 100%;
z-index: 3;
display: flex;
align-items: center;
justify-content: right;
background-color: #68c7c1;
min-height: 56px;
transition: min-height 0.3s;
}
header #menu {
margin-left: auto;
margin-right:10px;
color: #eceeef;
font-size: 2em;
}
.nav {
width: 100%;
height: auto;
z-index: 2;
display: flex;
flex-wrap: wrap;
background-color: #68c7c1;
}
.nav-sm, .nav-lg { display: none; }
.nav-sm.open {
display: flex;
flex-wrap: wrap;
align-items: center;
height: calc(100% - 56px);
margin-top: -2px;
}
.nav__list, .nav__item { width: 100%; }
.nav__list {
display: flex;
flex-wrap: wrap;
}
.nav__item {
height:50px;
display: flex;
flex-wrap: nowrap;
justify-content: center;
}
.nav__item a {
text-decoration: none;
text-align: center;
font-size: 1.2em;
color: #eceeef;
}
.nav-sm.open {
-webkit-animation: slide-down .3s linear;
-moz-animation: slide-down .3s linear;
}
.nav-sm.open .nav__item{
padding-bottom: 80px;
font-size: 2em;
}
.nav-sm.open .nav__item:nth-child(1) {
-webkit-animation: slide-down .3s .1s linear;
-moz-animation: slide-down .3s .1s linear;
}
.nav-sm.open .nav__item:nth-child(2) {
-webkit-animation: slide-down .3s .2s linear;
-moz-animation: slide-down .3s .2s linear;
}
.nav-sm.open .nav__item:nth-child(3) {
-webkit-animation: slide-down .3s .3s linear;
-moz-animation: slide-down .3s .3s linear;
}
#-webkit-keyframes slide-down {
0% { opacity: 0; -webkit-transform: translateY(-100%); }
100% { opacity: 1; -webkit-transform: translateY(0%); }
}
#-moz-keyframes slide-down {
0% { opacity: 0; -moz-transform: translateY(-100%); }
100% { opacity: 1; -moz-transform: translateY(0%); }
}

How to stop progress bar animation halfway using Keyframes

I'm trying to load the progress bar up to a certain percentage. Whatever that percentage is, the progress bar will stop at that specific color animation specified in the keyframes.
How can i get it to work.
HTML
<div class="container">
<div class="progress-bar">
<span style="width:50%">
<span class="progress-value"></span>
</span>
</div>
<span><strong>CSS</strong></span>
<br/>
</div>
CSS
.container {
display: flex;
justify-content: center;
}
.progress-bar {
background-color: lightgray;
border-radius: 1.25em;
width: 300px;
height: 16px;
width: 50vw;
}
.progress-bar > span {
display: flex;
}
.progress-value {
background-color: #673ab7;
transition: 0.3s all linear;
border-radius: 1.25em;
height: 16px;
width: 50vw;
animation: progress-color 3s linear forwards;
-webkit-animation: progress-color 3s linear forwards;
}
/* animation */
#keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background: purple;
}
100% {
background: green;
width: 100%;
}
}
#-webkit-keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background:red;
}
100% {
background: green;
width: 100%;
}
}
Here's my codepen
https://codepen.io/mingsterism/pen/xJgePK
The problem is that where you have specified the animation is 100% completed under the #keyframes , there you must specify red as the color, which you have specified as the color you wish when the bar reaches 50%, while the rest of of the code is fine. Replace your piece of code with this one below and tell, is this what you want ?
#keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background: green;
}
100% {
background: red;
width: 100%;
}
}
#-webkit-keyframes progress-color {
0% {
width: 0;
}
50% {
width: 30%;
background: green;
}
100% {
background: red;
width: 100%;
}
}

Resources