Background:
Trying to create an esthetically pleasing linking hover for the future
Current JSFiddle:
Available here for FF Browser.
body {
color:#ffffff;
font-family:"Helvetica";
font-size:12pt;
background-color:#000000;
font-weight:bold;
}
a:link {
color:white;
text-decoration:none;
}
a:hover {
animation: myhover 1s;
transition-timing-function: ease-in-out;
font-weight: bold;
}
#keyframes myhover {
from {
background-color: black;
color: white;
}
to {
background-color: white;
color: black;
}
}
Problem:
The transition works in what concerns the effect, but for some reason, even if you remain with the cursor on top of the link, it reverts to the FROM state without even a fade back from TO to FROM.
Need:
What code change is needed to stay at TO effect, until you take the cursor out of the hovered LINK and it reverts the effect to FROM?
Code type restrictions:
I do not wish to use JavaScript or JQuery in the solution, only CSS and HTML.
Many Thanks
Alban
There are two parts to your question:
1) How do you retain the current animation state?
Add animation-fill-mode to your CSS rule:
a:hover {
-webkit-animation: myhover 1s;
animation: myhover 1s;
transition-timing-function: ease-in-out;
font-weight: bold;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
2) How do you revert to the "From" transition
Fairly straight forward - you set the "default" animation properties of the link.
a:link {
-webkit-animation: nohover 1s;
animation: nohover 1s;
color:white;
text-decoration:none;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
The only issue you might run into is the page load. You'll notice the animations kick off before any interaction occurs (for -webkit-based-browsers). Without JavaScript, you'll need to consider this and how your animations will look.
A fiddle for demonstration: http://jsfiddle.net/6hxhxg5t/
You need to set the animation-fill-mode to forwards for the animation to retain the state as at its last keyframe.
animation: myhover 1s forwards;
or
animation-name: myhover;
animation-duration: 1s;
animation-fill-mode: forwards;
Option 1 Demo | Option 2 Demo
Note:
The demo uses -webkit- prefix as I am testing on Chrome, but the same would work with either the -moz- prefix or without any prefixes.
Achieving a reverse effect on hover out would not be possible without adding extra code as animation do not work like transition. The reverse effect would be better achieved with JavaScript/jQuery as the reverse animation cannot be kicked-off by default on the base class without it appearing once on page load also. Here is a way to achieve both the forward and reverse animation effects using jQuery. jQuery is not a must and the same can be done with vanilla JS also but I just used jQuery for doing a quick sample.
Option 3: (Using transtions instead of animations)
If your objective is only to linearly change the background-color and the color properties on mouse hover, then actually transition is a much better option to make use of instead of animation. Transitions can automatically answer both of your concerns. It can make the end state retained till the mouse is hovered out and the hover out will also cause the reverse effect to happen.
a:link {
color:white;
text-decoration:none;
transition: background-color 1s, color 1s;
/*transition: all 1s;*/ /* use this line if you wish to transition all properties */
transition-timing-function: ease-in-out;
}
a:hover {
font-weight: bold;
background-color: white;
color: black;
}
Option 3 Demo
Related
I am animating a button. A class is assigned depending on my app state. This is actually implemented in Svelte as follows:
<div class="default"
class:run-animation="{$animate === true}">
But the equivalent in vanilla javascript without Svelte is:
let element = document... (find element)
element.classList.add("run-animation")
... later ...
element.classList.remove("run-animation)
For the sake of a minimum reproducible example, the classes I'm trying to animate/transition between look like this:
.default {
top: 20px;
color: white;
}
#keyframes button-animation {
from {
top: 20px;
color: white;
}
20% {
top: 23px;
color: white;
}
25% {
color: red;
}
100% {
top: 23px;
color: red;
}
}
.run-animation {
animation-name: button-animation;
animation-duration: 2s;
/* Preserve the effect of the animation at ending */
animation-fill-mode: forwards;
}
I add the class to the element, and the button animates just like I want it to. My problem arises when I remove the class. I want the button to transition smoothly back to the default CSS. I have tried adding the animation to the run-animate class:
.run-animation {
animation-name: ... ;
top: 23px;
color: red;
}
I have come across many people stating the transition upon class removal will apply if I add a transition property to the default class. I have tried this as follows:
.default {
...
transition: all 3s linear;
}
But it isn't working. The animation runs smoothly when it is added but the styling immediately reverts to the default when the class is removed (no smooth transition).
MY GOAL: I want to smoothly transition away from the end-state of the animation to the default class when the animate class is removed. Is this possible?
Ideally, I'm adding the class with the Svelte logic at the top so the animation should not be triggered in javascript but rather naturally occur as a result of class assignment.
(My code in practice is a little more complicated than shown, the button has another class with styles not being animated at all and the animation includes more styles such as box-shadow and text-shadow. Still, I don't see why this should be more problematic than just color and top included above)
// JS only toggles '.animation'
document.querySelector("button").addEventListener("click", () => {
document.querySelector("div.default").classList.toggle("animation");
});
body {display: flex}
button {position: absolute; left: 120px}
div.default {
position: absolute;
width: 100px;
height: 100px;
background: darkgreen;
}
/* Above code to make a visible working example */
div.default {
top: 20px;
color: white;
transition: top 0.4s, color 0.1s 0.4s;
}
#keyframes define-animation {
from {
top: 20px;
color: white;
}
}
div.default.animation {
animation-name: define-animation;
animation-duration: 2s;
top: 24px;
color: red;
}
<div class="default">I'm colourful</div>
<button>Toggle ".animation"-class</button>
Above is a working snippet with an animation running on class addition and no reverse transition on class removal. I have tried setting animation direction to opposite values in .default and .animation. I have tried defining the .animate end state properties in the class and/or in the keyframes to attributes.
EDIT: It works now! How?
You cannot apply:
animation-fill-mode: forwards;
The end-attributes need to be defined in the animate class not in the keyframe.
The animation plays when the class is added. Transition timings are used when the class is removed (if the animation has completed).
To get a transition effect, you can use the transition-property.
The transition-property can be used here, since every property you want to animate only has a start- and end-value.
Translating animation-percentages to seconds
To translate the percentages of your CSS Animation button-animation to seconds, you just calculate 'percentage' * 'animation-duration'.
This works for both the transition-duration-property as well as for the transition-delay-property.
Example:
color is being animated from 20% to 25%, which is a duration of 5% with a delay of 20%.
All in all, the animation should take 2 seconds.
So we calculate for:
transition-duration: 5% * 2s = 0.1s
transition-delay: 20% * 2s = 0.4s
With that, we can add transition: color 0.1s 0.4s to the .default-class.
Why add it to .default, and not to .animation?
If we were to add the transition-property to .animation, the following would happen:
When adding .animation, there will be a transition-effect, since the element now has a transition-property defined.
But when removing .animation, the element would no longer have a transition-property defined, meaning there would be no transition.
Now, we want to transition on both adding and removing .animation, meaning we want to have a transition-property defined both when .animation is present and when it is not. That means, transition should not be defined in .animation.
// JS only toggles '.animation'
document.querySelector("button").addEventListener("click", () => {
document.querySelector("div.default").classList.toggle("animation");
});
body {display: flex}
button {align-self: center}
div.default {
position: relative;
border: 2px solid black;
width: 100px;
height: 100px;
background: darkgreen;
}
/* Above code to make a visible working example */
div.default {
top: 20px;
color: white;
transition: top 0.4s, color 0.1s 0.4s;
}
div.default.animation {
top: 23px;
color: red;
}
<div class="default">Some text to see the "color"-property</div>
<button>Toggle ".animation"-class</button>
Why does it behave differently...
...when placing the properties inside the to-section of the animation, than when placing them inside .animation itself?
That is, because the properties are not directly applied to the element itself, but rather the element is stopped in its animation (right at the very end), giving only the appearance of the properties being actually applied.
Removing animation-fill-mode: forwards shows the actually applied properties after the animation has played. Those actually applied properties will be the start-values for transition after .animation is removed.
When defining these properties in .animation, they will inherently be the to-values for the animation (if not defined otherwise in animation itself), and be the applied properties of the element.
That means, when removing .animation, the transition will start from there.
CSS transitions animate back to the previous state, following the transition rules in reverse. But animations don't. They just go back to the original state abruptly (eg., when :hover or the class is removed). Is there a way to make animations behave like transitions (like the code below).
.box {
width: 50px;
height: 50px;
}
.box.transition {
background-color: green;
transition: 500ms linear all;
}
.box.transition:hover {
width: 100px;
height: 100px;
}
.box.animation {
background-color: red;
animation-duration: 500ms;
animation-fill-mode: both;
animation-timing-function: linear;
}
.box.animation:hover {
animation-name: zoom;
}
#keyframes zoom {
to {
width: 100px;
height: 100px;
}
}
<!-- If I "unhover" .box.animation, it goes back to the original state abruptly -->
<div class="box transition"></div>
<div class="box animation"></div>
Animation like transitions
Yes and no you can make them behave similarly but not identical, but not with :hover.
The hover state ends when you stop hovering an element. So when you stop hovering it, the css rule that targets :hover will instantly be removed.
Transition define what to do when there are changes to different states.
Animation go from one state to another defined by an animation.
Setting the animation direction will make it look closer to a transition.
animation-direction: alternate; will loop over an animation from start to finish and backagain.
i got a little question when using the transition-effect with the property display:
I am testing on Safari:
input.input_field {
display:none;
transition-property: display;
transition-duration: 2s;
-webkit-transition-property: display; /* Safari */
-webkit-transition-duration: 2s; /* Safari */
}
input.input_field_active {
display:block;
}
But this example doesnt work for now, anybody knows why i cant use the the property : display??
Greetings!
You can only perform a transition on a scalable property, i.e. a numerically defined property (which may or may not have units of measurement) which exists within a range for which any two points are related. The reason for this is that in order to perform a transition the browser takes the starting point and ending point provided then extrapolates the interim keyframes- producing the resulting animation.
The display property is not scalable, it is simply 'on' or 'off', indeed more specifically it has a number of properties which arent related on any form of scale. As such, the interim values cannot be extrapolated. You can also look at it like this, display is also a layout and not visual style- although it does have visual connotations. You can only perform transitions on visual styles.
Depending on what your requirements are, you can perform a transition on opacity or height (or width).
Demo Fiddle of alternate transitions
You can use a combination of visibility in place of display and the use opacity as a fade effect.
visibility is transtionable although it also only has an on / off state BUT you can use a transition delay to affect it.
JSFiddle Demo
HTML
<button>Hover</button>
<div class="wrap">
</div>
CSS
.wrap {
width:100px;
height:100px;
border:1px solid grey;
background-color: #bada55;
margin-top: 25px;
visibility:hidden;
opacity:0;
transition: visibility 0s linear 0.5s,
opacity 0.35s linear;
}
button:hover + .wrap {
visibility:visible; /* show it on hover */
opacity:1;
transition-delay:0;
}
I have an image on my website. When I hover over it I want it to do a 360 spin animation.
I'm currently doing so in CSS:-
.img-responsive:hover {
transition-duration: 2s;
transform:rotate(360deg);
}
However, when the user hovers at the edge of the image, the image rotates and is no longer being hovered over at the edge causing the image to "spasm".
How can I achieve a proper looking and stable rotation? JavaScript would work too.
You can fix it by adding small delay to your transition
Working Demo
.img-responsive:hover {
transition-duration: 2s;
transform:rotate(360deg);
transition-delay: 0.5s;
}
Update:
If you can use animation, You can do this
Updated Demo
.img-responsive {
animation: rotateme;
}
.img-responsive:hover {
animation: rotateme 5s;
}
You can make the image bigger when hovered, so that it's difficult that the user accidentally unhovers
if there is no padding or margin, set
.img-responsive:hover {
transition-duration: 2s;
-webkit-transform:rotate(360deg);
-moz-transform:rotate(360deg);
transform:rotate(360deg);
padding: 50px;
margin: -50px;
}
Increasing the padding to 50px makes sure that the mouse is still on it. Changing the margin in the same amount, but in opposite sense makes it stay at the same location.
fiddle
I need to change the background-color from red to transparent.
This change should occur when I hover over a div.
The reason is why I need it transparent is so I can show an absolute positioned div under the main div, in other words, when I hover over the parent div, I need to show the child div.
When I move away the cursor from this div, I don't want a reverse-transition, I want the background to stay transparent, I want the blue div to always be there after I move away the cursor.
Since I need a PURE CSS solution (No JS/JQuery), I came into the CSS3 Transition.
<div id="parent">
<div id="child">
</div>
</div>
This is a fiddle (Firefox).
#parent
{
background:red;
-moz-transition:background 1s;
}
#parent:hover
{
background:transparent;
}
I thought about doing this with animation, since I can fake this by giving it a temporary duration to stay transparent, for example.
0% {background:red;}
1% {background:transparent;}
100% {background:transparent;}
But then animation will stop when I move the cursor away.
Note: This may sound ridiculous or stupid, but my intention is bigger than this, this is just one small example.
Take a look at the transition-delay property.
#parent { transition-delay:999999s; }
#parent:hover { transition-delay:0s; }
Fiddle
This way, the hover animation will happen instantly (0s) while the transition to the initial state will only happen after 277 hours without leaving the page. You can increase the value a bit further if necessary, though I believe this value is enough for a real world page. =]
I don't think it's possible with pure CSS. As a compromise you can use JavaScript to add a class to the element and then handle all visuals with CSS.
http://jsfiddle.net/ZvcgP/1/
HTML
<div class="effect">Hover me</div>
CSS
.effect {
background-color: red;
-webkit-transition:background 1s;
transition:background 1s;
}
.effect.anim-done {
background-color: transparent;
}
JS
$('.effect').mouseenter(function () {
$(this).addClass('anim-done');
});
use below code to transiton from red to transparent. and please change 'object' to the class of your object
.object {
background-color: red;
-webkit-transition:background-color 1s linear; /* for webkit supported browsers */
-moz-transition:background-color 1s linear; /* for old mozilla browsers */
-o-transition:background-color 1s linear; /* for opera browsers */
transition:background-color 1s linear; /* for css3 supported browsers */
}
.object:hover {
background-color: transparent;
}