Vue Js transition only works when entering, not leaving - css

I'm trying to apply a bottom to top, and top to bottom vue js transition. The bottom to top works on enter, but I get no transition on leave.
Here is my css transition:
.slide-details-mobile-enter-active {
#include transition(all 0.5s ease-in);
}
.slide-details-mobile-enter-active {
#include transition(all 0.5s cubic-bezier(0, 1, 0.5, 1));
}
.slide-details-mobile-enter-to, .slide-details-mobile-leave {
transform: translateY(0vh);
}
.slide-details-mobile-enter, .slide-details-mobile-leave-to {
transform: translateY(100vh);
}
The vue template looks like this:
<transition :name="detailsTransition">
<sc-fcst-details
v-if="viewDetails"
#changeactiveday="changeActiveFcstDay($event)">
</sc-fcst-details>
</transition>
The first element in the vue template has the following css:
#fcst-details {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
overflow-y: hidden;
z-index: 4;
}
Any suggestions on why the leave transition does not work?
Also, I was hoping to use the top style instead of transform, but that wasn't working at all.

This seems to be working fine for me:
.details-transition-enter-active, .details-transition-leave-active {
transform: translateY(0vh);
transition: all 0.4s ease-in-out;
}
.details-transition-enter, .details-transition-leave-to {
transform: translateY(100vh);
}
Give it a go 🙂
Later edit (using top instead of transform):
.details-transition-enter-active, .details-transition-leave-active {
top: 0vh;
transition: all 0.4s ease-in-out;
}
.details-transition-enter, .details-transition-leave-to {
top: 100vh;
}
And then remove the top: 0 from #fcst-details.

Related

scale() from a high value to low distorts transition

I am trying to make a transition so when I click I button two divs are scaled from a small circle to a large circle. Basically that looks something like this when expanded:
This has gone from scale(1) to scale(20) and scale(25). When I click the button, the circles shrink with no problem. However, if I increase the scaling to for example scale(40) and scale(45) the result I get when clicking the button again (to shrink everything) looks like this:
So this happens right after I click. In this case I just have a transition-delay on so I could screenshot it.
The SCSS for the circles are like this:
.inner-circle-bg {
display: none;
width: 30px;
height: 30px;
border-radius: 100%;
position: fixed;
background: $primaryRed;
bottom: 35px;
right: 35px;
z-index: 999999;
transform: scale(1);
transition: transform 0.3s ease-in;
transition-delay: 4.1s;
&.is-active {
transform: scale(40);
transition: transform 0.3s ease-in;
transition-delay: 0.1s;
}
}
.outer-circle-bg {
display: none;
width: 30px;
height: 30px;
border-radius: 100%;
position: fixed;
background: $primaryRedDark;
bottom: 35px;
right: 35px;
z-index: 99999;
transform: scale(1) ;
transition: transform 0.3s ease-in;
transition-delay: 4.2s;
&.is-active {
transform: scale(45) ;
transition: transform 0.3s ease-in;
}
}
And then I just have some JS to toggle the is-active state when a button is clicked.
So yeah, any idea what might be causing this, and if there is a way to fix it ?
EDIT:
I now have a working JSfiddle illustrating the problem (although with a hover effect instead):
https://jsfiddle.net/47znjxwo/

:hover rotation CSS keep position on uncover

I am rotating an object with CSS upon hovering, and would like for it to remain in it's new position as you unhover it. I have searched around, but the only thing I could find is css :hover rotate element and keep the new position, which seems to go above and beyond.
Is this effect possible to achieve purely with CSS? I want the icon to remain at the 180 position once you stop hovering.
I used this code:
i.fa.fa-globe:hover {
color: #e9204f;
transition: 0.9s;
transform: rotatey(180deg);
}
Also it's a font-awesome icon if this makes any difference.
Edit - The easy CSS solution for everyone else who needs it (taken from the comments):
.lovernehovermarket i.fa.fa-rocket {
transform: rotate(0deg);
transition: transform 999s;
}
I had a circular icon that I wanted to rotate on every hover, not just the first, and not rotate when un-hovered.
Original
I saw this problem when I had CSS that looked like this
.icon {
transition: transform 0.5s;
}
.icon:hover {
transform: rotate(90deg);
}
Solution
The simple solution was to put the transition inside the :hover psuedo class
.icon:hover {
transition: transform 0.5s;
transform: rotate(90deg);
}
Boom, done!
This works because I was originally setting the transition to be 0.5s by default. In this case, that means both forward and backward. By putting the transition property inside the hover, I have a 0.5s transition when hover is activated, but a 0s transition (the default) when the icon is un-hovered. Having a 0s hover means it just instantly snaps back to position, invisibly to the viewer.
I you want a pure CSS solution, you can set a transtion time to go back to the base state quite high.
It's not for ever, but it's pretty close for most users:
.test {
display: inline-block;
margin: 10px;
background-color: tomato;
transform: rotate(0deg);
transition: transform 999s 999s;
}
.test:hover {
transform: rotate(90deg);
transition: transform 0.5s;
}
<div class="test">TEST</div>
You also need an initial transform state in the regular CSS of your element, so that it can transform between two defined states:
.rotate {
width: 20px;
height: 100px;
background: blue;
transition: 0.9s;
transform: rotate(0deg);
}
.rotate:hover {
transform: rotate(180deg);
}
body {
padding: 100px;
}
<div class="rotate"></div>
If you want to maintain the rotated state, you may have to use a little JQuery to check when the transition ends and change the class so it doesn't revert back to its original state on blur.
This way the div is rotated once and then its class is changed to maintain the rotated state.
$('.rotate').hover(function () {
$(this).addClass("animate");
$(this).one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',
function(e) {
$(this).removeClass('rotate').addClass('rotated');
});
});
.rotate {
width: 100px;
height: 100px;
background: gold;
transition-property: transform;
transition-duration: 1.5s;
transition-timing-function: linear;
}
.animate {
animation: rotate 1s linear;
transform: rotate(180deg);
animation-play-state: running;
}
.rotated
{
width: 100px;
height: 100px;
background: gold;
transform: rotate(180deg);
}
body {
padding: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="rotate">some text</div>
Use an animation, and apply it using JS event listener, when the element is hovered (mouseover event). When the element is hovered for the 1st time, remove the event listener:
var rect = document.querySelector('.rectangle')
function rotate() {
this.classList.add('rotate');
rect.removeEventListener('mouseover', rotate);
}
rect.addEventListener('mouseover', rotate);
.rectangle {
width: 100px;
height: 100px;
background: gold;
}
.rotate {
animation: rotate 0.5s linear;
}
#keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(180deg);
}
}
body {
padding: 30px;
}
<div class="rectangle"></div>
What worked for me was to put the transform not on hover but on the main css.
not:
#gear {
width: 3vh;
height: auto;
cursor: pointer;
&:hover {
transform: rotate(45deg);
transition: transform 200ms;
}
}
but
#gear {
width: 3vh;
height: auto;
cursor: pointer;
transition: transform 200ms;
&:hover {
transform: rotate(45deg);
}
}

CSS Overlay not displaying

I am starting my foray into Modals and the CSS I am using for the overlay, just doesn't seem to want to work. Any ideas what might be happening?
It is written in SCSS
#mixin transitionSupport($transition){
-webkit-transition: $transition;
-moz-transition: $transition;
-o-transition: $transition;
transition: $transition;
}
.modal-overlay{
position: fixed;
z-index: 998;
top: 0;
left: 0;
opacity: 0;
width: 100%;
height: 100%;
#include transitionSupport(1ms opacity ease);
background: rgb(0,0,0);
.modal-open{
opacity: 1;
}
}
HTML:
<div class="modal-overlay modal-open">
</div>
Link to the codepen
When I view the page itself, the page stays white. And I have no idea why.
Should the .modal-open{opacity:1} not override .modal-overlay?
Change .modal-open { to &.modal-open { to match class="modal-overlay modal-open".
As it's written currently, it's looking to match an element called .modal-open INSIDE .modal-overlay.

Transitioning from animated to not animated in Chrome vs Firefox

Firefox has a nice behavior when turning off animation in a transition enabled element, it takes the element wherever it is and transition back to original form.
In Chrome it just jumps without transitioning.
Why the inconsistency? Is there any way to replicate in Chrome without using too much JS?
.wrapper {
width: 400px;
height: 200px;
}
.move {
width: 100px;
height: 100px;
position: absolute;
background-color: #f66;
transition: 1s;
cursor: pointer;
}
.move {
animation: move 2s linear infinite;
}
.wrapper:hover .move {
animation: none;
}
#keyframes move {
50% {
transform: translateX(200px);
}
}
<div class="wrapper">
<div class="move"></div>
</div>
$(".spinny").bind("webkitAnimationEnd mozAnimationEnd animationEnd", function(){
$(this).removeClass("spin")
})
$(".spinny").hover(function(){
$(this).addClass("spin");
})
div {
width: 100px;
height: 100px;
background-color: #f66;
transition: 1s;
cursor: pointer;
}
.spin {
animation: spin 1s linear 1;
}
#keyframes spin {
100% {
transform: rotate(180deg);
}
}
<script src="https://code.jquery.com/jquery-3.1.0.js"></script><div class="spinny"></div>
Taken from this answer, JS can be used to add and remove classes on hover and animation finish, respectively. jQuery is used in this example, but it is not necessary for the functionality.
EDIT: Now without jQuery, this will play the animation whenever hovered over by remembering the state and checking after the end of every animation.
hover = 0;
s = document.getElementById("spinny");
s.addEventListener("animationend", function(){
s.className = "";
if (hover)
setTimeout(function(){s.className = "spin"},0);
})
s.onmouseover = function(){
s.className = "spin";
hover = 1;
}
s.onmouseout = function(){
hover = 0;
}
div {
width: 100px;
height: 100px;
background-color: #f66;
transition: 1s;
cursor: pointer;
}
.spin {
animation: spin 1s linear 1;
}
#keyframes spin {
100% {
transform: rotate(180deg);
}
}
<div id="spinny"></div>
Add transition along side your transform
.rotate {
width: 200px;
height: 200px;
transform: rotate(0deg);
transition: 0.5s ease all;
background-color: #222;
}
.rotate:hover {
transform: rotate(20deg);
transition: 0.5s ease all;
}
This should prevent it from jumping.

Transition a property after it has been animated

I have an element that comes in from the left when it's added to the page (from an XHR call):
.flyin:not(.animation_done) {
-webkit-animation: flyin .5s ease forwards;
margin-left: -210px;
opacity: 0;
}
#-webkit-keyframes flyin {
to {
margin-left: 0;
opacity: 1;
}
}
But I would like to animate the margin-left property on hover:
.element_im_animating.animation_done {
margin-left: 0;
transition: margin-left .4s ease;
}
.element_im_animating.mod.animation_done:hover {
margin-left: 10px;
}
To accomplish this I am adding a class when the animation finishes:
$(document).on("animationend webkitAnimationEnd", function(e) {
$(e.target).addClass("animation_done");
});
Strangely, adding animation_done is triggering the flyin animation a second time straight after it finishes. Can I stop this happening? Is there a simpler no-javascript way to do what I need to do? Thanks!
The animation isn't running a second time.
What is really happening is the following:
Your element has the margin set like this:
.flyin:not(.animation_done) {
margin-left: -210px;
}
And the end of the animation has a margin-left of 0px because of this
.flyin:not(.animation_done) {
-webkit-animation: flyin 5s ease forwards;
}
#-webkit-keyframes flyin {
to {
margin-left: 0px;
}
}
When you remove the animation, no longer applies the forwards rule above, and the margin is now the default one (-210px). Since this property is transitioned (not animated !), it will move to the new value:
.animation_done {
margin-left: 0px;
}
in a similar way to the animation. Solve it setting the base margin to the final one, and not using forwards
.flyin:not(.animation_done) {
-webkit-animation: flyin 5s ease;
margin-left: 0px;
opacity: 0;
}
#-webkit-keyframes flyin {
from {
margin-left: -210px;
opacity: 1;
}
to {
margin-left: 0px;
opacity: 1;
}
}
.animation_done {
margin-left: 0px;
transition: margin-left 4s ease;
}
.animation_done:hover {
margin-left: 10px;
}
fiddle

Resources