Combination of Animation and Transition Not Working Properly

Combination of animation and transition not working properly

This is sort of a known behavior with Chrome. Firefox does seem to be able to handle the removal of animation smoothly with transition but Chrome doesn't do so. I had seen this behavior happen earlier also in this thread.

Why does removal of an animation not work with transition in Chrome?

While I cannot provide a 100% fool-proof explanation of why this happens, we can decode it to some extent based on this HTML5Rocks article about Accelerated rendering in Chrome and this one about GPU accelerated compositing in Chrome.

What seems to happen is that the element gets its own rendering layer because it has explicit position property set on it. When a layer (or part of it) gets invalidated due to animation, Chrome only repaints that layer which is affected by the change. When you open the Chrome Developer Console, switch on "Show Paint Rects" option, you would see that when the animation is happening Chrome only paints the actual element that is getting animated.

However, at the start and end of animation a whole page repaint is happening which puts the element back into its original position immediately and thus overriding the transition behavior.

$('button').click(function(){

$('div').toggleClass('clicked');

});
div{

background-color: #ccc;

height: 100px;

width: 100px;

transition-property: top, left;

transition-duration: 1s;

transition-timing-function: linear;

position: relative;

top: 0;

left: 0;

}

.clicked{

animation-name: clicked;

animation-duration: 1s;

animation-timing-function: linear;

animation-fill-mode: forwards;

}

@keyframes clicked{

0% {top: 0; left: 0;}

100% {top: 100px; left: 100px;}

}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button type="button">Click Me!</button>

<div></div>

CSS Transitions Not working after toggle between classes

TL;DR. See the code snippet below which is slightly tweaked from your original code.

A few notes:

  1. Consider using button instead of a tag. It's a button that does something when clicked as opposed to a hyperlink that directs to a link when clicked.
  2. Be careful with overly specific CSS rules. div.button-dropdown-options (i.e. element name + class name) is more specific than .button-dropdown-options (i.e. class name only), and can trump other less specific selectors. It is what makes you overly rely on !important in multiple places. Over specificity and !important in combination will make it very hard to debug styling.
  3. visibility as part of transition property as well. That is, something like transition: opacity 2s, visibility 2s;

function showDropDown() {
const variantButton = document.getElementById('showdropdown');
const variantMenu = document.getElementById('variantMenu');
const animate_arrow = document.querySelector('.btn-dropdown-caret');
const options = document.querySelector('.btn-dropdown-options');
const over = document.querySelector('.swiper-container');
const calculatedOptions = window.getComputedStyle(options);

variantButton.addEventListener('click', function(event) {
variantMenu.classList.toggle('dropdownShow');
animate_arrow.classList.toggle('animate-arrow');
});

}
showDropDown();
.btn-dropdown {
display: block;
position: relative;
white-space: nowrap;
margin-top: 5px;
margin-left: 2px;
}

@media screen and (min-width: 768px) {
.btn-dropdown {
z-index: 4;
}
}

.btn-dropdown .btn-dropdown-link {
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 100%;
}

.form-btn.outlined.btn-dropdown-link {
font-family: "Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 20px;
/* -webkit-transition: color 200ms ease;
transition: color 200ms ease; */
border: 1px solid #dddddd;
box-shadow: none;
-webkit-touch-callout: none;
/* iOS Safari */
-webkit-user-select: none;
/* Safari */
-khtml-user-select: none;
/* Konqueror HTML */
-moz-user-select: none;
/* Old versions of Firefox */
-ms-user-select: none;
/* Internet Explorer/Edge */
user-select: none;
/* Non-prefixed version, currently */
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) !important;
color: #6e6d7a;
}

.form-btn.outlined.btn-dropdown-link:hover,
.form-btn.outlined.btn-dropdown-link:focus {
border: 1px solid #e4b29b;
color: #1b1b1b;
box-shadow: 0 0 0 2px rgb(228 178 155 / 10%);
}

.form-btn.outlined.btn-dropdown-link:hover svg,
.form-btn.outlined.btn-dropdown-link:focus svg {
fill: #666666;
}

.animate-arrow {
transition: transform 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
transform: translateY(-50%) rotate(180deg) !important;
}

.form-btn.outlined,
a.form-btn.outlined {
background-color: transparent;
-webkit-box-shadow: 0px 0px 0px 1px #e7e7e9 inset;
box-shadow: 0px 0px 0px 1px #e7e7e9 inset;
color: #0d0c22;
}

.btn-dropdown .btn-dropdown-link {
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding-right: 35px;
text-align: left;
}

.form-btn,
a.form-btn {
background: #f3f3f4;
color: #0d0c22;
}

.form-btn,
a.form-btn {
display: inline-block;
position: relative;
-webkit-box-sizing: border-box;
box-sizing: border-box;
height: 40px;
padding: 10px 16px;
-webkit-transition: color 200ms ease;
transition: color 200ms ease;
border: none;
border-radius: 10px;
outline: none;
background: #ea4c89;
text-align: center;
text-decoration: none;
cursor: pointer;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
font-family: "Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: 500;
line-height: 20px;
}

/* Variant Selector --Span */

.btn-dropdown.btn-dropdown-neue svg.btn-dropdown-caret {
fill: #9e9ea7;
}

.btn-dropdown svg.btn-dropdown-caret {
position: absolute;
top: 50%;
right: 15px;
width: 10px;
height: 10px;
margin: 0;
-webkit-transform: translateY(-50%) rotate(0deg);
-ms-transform: translateY(-50%) rotate(0deg);
transform: translateY(-50%) rotate(0deg);
-webkit-transition: -webkit-transform 0.2s ease-in-out;
transition: -webkit-transform 0.2s ease-in-out;
transition: transform 0.2s ease-in-out;
transition: transform 0.2s ease-in-out, -webkit-transform 0.2s ease-in-out;
fill: currentColor;
}

.form-btn svg,
button.form-btn svg {
width: 13px;
height: 13px;
margin-top: -3px;
margin-right: 2px;
fill: currentColor;
vertical-align: middle;
}

/* DropDown */

.btn-dropdown .btn-dropdown-options {
right: 0;
}

.btn-dropdown div.btn-dropdown-options {
z-index: 2;
}

.btn-dropdown-options {
font-family: "Haas Grot Text R Web", "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 20px;
position: absolute;
z-index: 1;
top: calc(100% + 8px);
left: 0;
min-width: 180px;
margin-top: 4px;
overflow: auto;
border: 1px solid rgba(0, 0, 0, 0.05);
border-radius: 8px;
background: #fff;
visibility: hidden;
opacity: 0;
transition: opacity 2s, visibility 2s;
box-shadow: 0px 1px 2px rgba(128, 138, 157, 0.12), 0px 8px 32px rgba(128, 138, 157, 0.24);
}

.btn-dropdown-options ul {
padding: 8px 0;
list-style: none;
}

.btn-dropdown-options li.active a {
color: #ea4c89;
font-weight: 500;
text-decoration: none;
}

.btn-dropdown-options a {
display: block;
padding: 8px 15px;
color: #6e6d7a;
font-size: 13px;
text-decoration: none;
}

.btn-dropdown-options.dropdownShow {
/* animation: 0.3s ease 0s 1 normal forwards running dropdownAnimation !important; */
visibility: visible;
opacity: 1;
}

.visuallyhidden {
opacity: 0;
}
<span class="btn-dropdown btn-dropdown-neue">
<button id="showdropdown" class="form-btn outlined btn-dropdown-link" data-dropdown-state="closed">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" role="img" class="icon btn-dropdown-caret">
<path d="M21.5265 8.77171C22.1578 8.13764 22.1578 7.10962 21.5265 6.47555C20.8951 5.84148 19.8714 5.84148 19.24 6.47555L11.9999 13.7465L4.75996 6.47573C4.12858 5.84166 3.10492 5.84166 2.47354 6.47573C1.84215 7.10979 1.84215 8.13782 2.47354 8.77188L10.8332 17.1671C10.8408 17.1751 10.8486 17.183 10.8565 17.1909C11.0636 17.399 11.313 17.5388 11.577 17.6103C11.5834 17.6121 11.5899 17.6138 11.5964 17.6154C12.132 17.7536 12.7242 17.6122 13.1435 17.1911C13.1539 17.1807 13.1641 17.1702 13.1742 17.1596L21.5265 8.77171Z"></path>
</svg>
<span data-prompt="Variant" data-fade-default="true" class="default-option">
Sandle Brown
</span>
</button>

<div id="variantMenu" class="btn-dropdown-options sets-querystring">
<ul>
<li class="default-filter-option active"><a href="?timeframe=">Now</a></li>
<li class="default-filter-option active"><a href="?timeframe=">Now</a></li>
<li class="default-filter-option active"><a href="?timeframe=">Now</a></li>
<li class="default-filter-option"><a href="?timeframe=">Now</a></li>
<li class="default-filter-option"><a href="?timeframe=">Now</a></li>
<li class="default-filter-option"><a href="?timeframe=">Now</a></li>
</ul>
</div>
</span>

CSS Animation wont go back smoothly even with transition set

First things first, your animation will struggle once you start to add content to this layout. The reason for that is you're animating the left property, this will cause the browser to calculate the document flow each frame and this causes lag. Similarly, using transition: all; is a very bad idea, specify the individual properties you intend on transitioning.

Secondly, consider cleaning up your markup. There are a lot of very messy selectors and names, generally speaking, the more generic your code is the better.

The reason your current solution isn't moving back smoothly, or at all, is because your animation only has the keyframes to move it one way.

I've cleaned your code up a little and posted a solution to this problem here, notice how only transform is animated and the transition is set to transform only:
http://codepen.io/r_p4rk/pen/NGZZwR

Transition animation not working in SwiftUI

The problem is that when views come and go in a ZStack, their "zIndex" doesn't stay the same. What is happening is that the when "showMessage" goes from true to false, the VStack with the "Hello World" text is put at the bottom of the stack and the yellow color is immediately drawn over top of it. It is actually fading out but it's doing so behind the yellow color so you can't see it.

To fix it you need to explicitly specify the "zIndex" for each view in the stack so they always stay the same - like so:

struct ContentView: View {
@State private var showMessage = false

var body: some View {
ZStack {
Color.yellow.zIndex(0)

VStack {
Spacer()
Button(action: {
withAnimation(.easeOut(duration: 3)) {
self.showMessage.toggle()
}
}) {
Text("SHOW MESSAGE")
}
}.zIndex(1)

if showMessage {
Text("HELLO WORLD!")
.transition(.opacity)
.zIndex(2)
}
}
}

}

Transition not working correctly when element is added to the DOM

You having to use a setTimeout is because of how javascript works with the event loop. Here is a really good video explaining a basic fundamental thing that you need to know about javascript. (Hey, I've been working with web development for five years, but been using javascript for 20, and just got to know about this this summer.)

Jake Archibald: In The Loop

If you don't want to use a timeout, you can instead use an animation. The downside is that it's hard to control specific times. If you start with opacity 0 and then have opacity 1 at 15%, that will create slower fade ins for longer toast durations.

function flashToast(msg, duration) {
duration = duration || 3000;

const toastElement = document.createElement("p");
toastElement.innerHTML = msg;

toastElement.classList.add("toast");

// Added
toastElement.style.setProperty("--duration", duration + "ms");

document.body.appendChild(toastElement);

setTimeout(function() {
document.body.removeChild(toastElement);
}, duration);
}
.toast {
display: inline-block;
font-size: 1.2rem;
padding: 0.8em 1em;
border-radius: 5rem;
color: #eaeaea;
background: #606060;
background: rgba(96, 96, 96, 0.7);
position: absolute;
bottom: 2%;
left: 50%;
transform: translate(-50%, -50%);

/* NEW */
animation: fade var(--duration) linear;
}

@keyframes fade {
0% {opacity: 0;}
15% {opacity: 1;}
85% {opacity: 1;}
100% {opacity: 0;}
}
<button onclick="flashToast('Toast!')">Show toast</button>


Related Topics



Leave a reply



Submit