I am trying to use the fade out animation in CSS and it works at first but then at the last minute the element pops back. JSFiddle: https://jsfiddle.net/eqb02w5u/
HTML Code:
<head>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"
/>
</head>
<div class='fade-in'>Fading In</div>
<div class='fade-out'>Fading Out</div>
CSS Code:
.fade-in {
background-color: red;
animation:fadeIn 3s linear;
}
#keyframes fadeIn {
0% {
opacity:0
}
100% {
opacity:1;
}
}
.fade-out {
background-color: green;
animation:fadeOut 3s linear;
}
#keyframes fadeOut {
100% {
opacity:0
}
0% {
opacity:1;
}
}
This is a really old question but you can add:
animation-fill-mode: forwards;
in each class where you want the animation to stay faded out.
I am new to CSS3 and working on a CSS3 code for blinking images. I just need to show an image with it blinking continually. I can't use a GIF image since the images come dynamically.
it's very simple... just use a CSS3 animation on opacity of the image
I hope this helps..
here is a working fiddle http://jsfiddle.net/rameezrami/27754r4f/1/ or use following html
<html>
<head>
<style>
/* Firefox old*/
#-moz-keyframes blink {
0% {
opacity:1;
}
50% {
opacity:0;
}
100% {
opacity:1;
}
}
#-webkit-keyframes blink {
0% {
opacity:1;
}
50% {
opacity:0;
}
100% {
opacity:1;
}
}
/* IE */
#-ms-keyframes blink {
0% {
opacity:1;
}
50% {
opacity:0;
}
100% {
opacity:1;
}
}
/* Opera and prob css3 final iteration */
#keyframes blink {
0% {
opacity:1;
}
50% {
opacity:0;
}
100% {
opacity:1;
}
}
.blink-image {
-moz-animation: blink normal 2s infinite ease-in-out; /* Firefox */
-webkit-animation: blink normal 2s infinite ease-in-out; /* Webkit */
-ms-animation: blink normal 2s infinite ease-in-out; /* IE */
animation: blink normal 2s infinite ease-in-out; /* Opera and prob css3 final iteration */
}
</style>
</head>
<body>
<img class="blink-image" src="http://www.chicagoexcelclasses.com/wp-content/uploads/2014/04/css31-180x180.jpg">
</body>
</html>
I'm coding a CSS3 effect fired on mouseover; this effect simply animate an inner div scaling it endlessly.
All works great, but when I move the mouse away the div suddenly return to its original size. I would like to add a smooth effect to scale the div back.
I already checked the suggestion of this post:
Make CSS Hover state remain after "unhovering"
Unfortunately the code posted doesn't work :(
In my opinion my issue could be related with the "infinite" loop of the scale effect.
THe goal I would like to gain is the on mouse-out the image could return to its original size smoothly.
Here's the code: https://jsfiddle.net/9dtqpsLa/1/
CSS
#keyframes imageZoom{
0% { transform: scale(1); }
50% { transform: scale(1.24); }
100% { transform: scale(1);}
}
#-moz-keyframes imageZoom{
0% { -moz-transform: scale(1);}
50% { -moz-transform: scale(1.24); }
100% { -moz-transform: scale(1); }
}
#-webkit-keyframes imageZoom{
0% { -webkit-transform: scale(1); }
50% {-webkit-transform: scale(1.24); }
100% { -webkit-transform: scale(1); }
}
#-ms-keyframes imageZoom{
0% { -ms-transform: scale(1); }
50% { -ms-transform: scale(1.24); }
100% { -ms-transform: scale(1); }
}
.article:hover .imageWrapper {
animation: imageZoom linear 10s;
animation-iteration-count: infinite;
-webkit-animation: imageZoom linear 10s;
-webkit-animation-iteration-count: infinite;
-moz-animation: imageZoom linear 10s;
-moz-animation-iteration-count: infinite;
-ms-animation: imageZoom linear 10s;
-ms-animation-iteration-count: infinite;
transform-origin: 50% 80%;
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
}
HTML
<div class="article">
<div class="imageWrapper">
</div>
</div>
Please, could you help me?
Thanks so much
GOALS:
1. Have the image animate expansion and contraction on hover
2. Have the image animate to original state on mouseleave
PROBLEMS:
With CSS, I don't know how to use both an animation and a transition. The animation is the pulsing on hover. The transition is the return to default animation. The only way I could envision doing it is with JS. See each section for notes
https://jsfiddle.net/Bushwazi/9dtqpsLa/5/
HTML:
notes: same as example provided
<div class="article">
<div class="imageWrapper"></div>
</div>
CSS:
notes:
1. animation removed.
2. The scale is only fired with the existence of [data-dir='expand'].
3. transform-origin and transition moved into the default state of .imageWrapper
4. need to add prefixes
.article[data-dir='expand'] .imageWrapper {
transform:scale(1.24)
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
transform-origin: 50% 80%;
transition:all 10.0s linear 0.0s;
}
JAVASCRIPT:
notes:
1. all new
/*
1. on hover aka 'mouseenter' start the animation
2. 10 seconds in, change direction of the animation based on the `isHovering` variable
3. on exit aka 'mouseleave', return to default
*/
var thisArticle = document.querySelector('.article'),
thisTimer = '',
isHovering = false;
thisArticle.addEventListener('mouseenter', function(){
console.log('mouseenter');
thisArticle.setAttribute('data-dir', 'expand');
thisTimer = setInterval(fireAnimation, 10000);
isHovering = true
}, false);
thisArticle.addEventListener('mouseleave', function(){
console.log('mouseleave');
thisArticle.removeAttribute('data-dir');
isHovering = false;
clearInterval(thisTimer);
}, false);
var fireAnimation = function(){
if(isHovering){
if(thisArticle.getAttribute('data-dir') === 'expand'){
thisArticle.removeAttribute('data-dir');
} else {
thisArticle.setAttribute('data-dir', 'expand');
}
} else {
clearInterval(thisTimer);
}
alert('change direction');
}
MORE IDEAS
1. I used a data attribute, but I would prefer to use classList. Wasn't sure how to incorporate that into the fiddle in 30 seconds, so skipped it.
2. The return to default animation has no awareness of the scale when you leave, so it takes 10 seconds no matter what. I'm sure there is a way to make this better.
Once you the mouse is moved away from the element, the styles in the :hover pseudo class gets removed from your element, effectively putting it back where it started.
What you want to do is start and pause the animation:
Here is your fiddle, I edited it a bit and exploded the short-hand and removed -webkit, -ms, etc:
https://jsfiddle.net/9dtqpsLa/4/
#keyframes imageZoom {
100% {
transform: scale(4);
}
}
.article:hover .imageWrapper {
animation-play-state: running;
}
.article {
background-color: #e6e6e6;
overflow: hidden;
width: 300px;
height: 300px;
}
.imageWrapper {
background-image: url('http://www.astutegraphics.com/images/blog/tutorials/widthscribe_patterns_18_mar_2013/floral-seamless-pattern.png');
width: 300px;
height: 300px;
transform-origin: 50% 80%;
animation-name: imageZoom;
animation-duration: 2s;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: both;
animation-timing-function: ease-in;
animation-fill-mode: forwards;
animation-play-state: paused;
}
Notice that all the animation logic has moved to the base class, and the :hover only kicks off the animation.
I have a div in which I animate the content:
#container {
position: relative;
width: 100px;
height: 100px;
border-style: inset;
}
#content {
visibility: hidden;
-webkit-animation: animDown 1s ease;
position: absolute;
top: 100px;
width: 100%;
height: 100%;
background-color: lightgreen;
}
#container:hover #content {
-webkit-animation: animUp 1s ease;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes animUp {
0% {
-webkit-transform: translateY(0);
visibility: hidden;
opacity: 0;
}
100% {
-webkit-transform: translateY(-100%);
visibility: visible;
opacity: 1;
}
}
#-webkit-keyframes animDown {
0% {
-webkit-transform: translateY(-100%);
visibility: visible;
opacity: 1;
}
100% {
-webkit-transform: translateY(0);
visibility: hidden;
opacity: 0;
}
}
<div id="container">
<div id="content"></div>
</div>
On hover, the content slides into the container div.
When I refresh the page and the page loads, the #content's animDown animation will run, and I'd prefer it to run only after a hover event.
Is there a way to do this pure CSS, or I have to figure something out in JS?
http://jsfiddle.net/d0yhve8y/
I always set preload class to body with animation time value 0 and its working pretty well. I have some back going transitions so I have to remove load animation to them too. I solved this by temporary setting animation time to 0. You can change transitions to match yours.
HTML
... <body class="preload">...
CSS is setting animation to 0s
body.preload *{
animation-duration: 0s !important;
-webkit-animation-duration: 0s !important;
transition:background-color 0s, opacity 0s, color 0s, width 0s, height 0s, padding 0s, margin 0s !important;}
JS will remove class after some delay so animations can happen in normal time :)
setTimeout(function(){
document.body.className="";
},500);
Solution 1 - Add down animation on first hover
Probably the best option is to not put the down animation on until the user has hovered over the container for the first time.
This involves listening to the mouseover event then adding a class with the animation at that point, and removing the event listener. The main (potential) downside of this is it relies on Javascript.
;(function(){
var c = document.getElementById('container');
function addAnim() {
c.classList.add('animated')
// remove the listener, no longer needed
c.removeEventListener('mouseover', addAnim);
};
// listen to mouseover for the container
c.addEventListener('mouseover', addAnim);
})();
#container {
position:relative;
width:100px;
height:100px;
border-style:inset;
}
#content {
position:absolute;
top:100px;
width:100%;
height:100%;
background-color:lightgreen;
opacity:0;
}
/* This gets added on first mouseover */
#container.animated #content {
-webkit-animation:animDown 1s ease;
}
#container:hover #content {
-webkit-animation:animUp 1s ease;
animation-fill-mode:forwards;
-webkit-animation-fill-mode:forwards;
}
#-webkit-keyframes animUp {
0% {
-webkit-transform:translateY(0);
opacity:0;
}
100% {
-webkit-transform:translateY(-100%);
opacity:1;
}
}
#-webkit-keyframes animDown {
0% {
-webkit-transform:translateY(-100%);
opacity:1;
}
100% {
-webkit-transform:translateY(0);
opacity:0;
}
}
<div id="container">
<div id="content"></div>
</div>
Solution 2 - play animation hidden
Another way around this is to initially hide the element, make sure the animation plays while it is hidden, then make it visible. The downside of this is that the timing could be slightly off and it is made visible too early, and also the hover isn't available straight away.
This requires some Javascript which waits for the length of the animation and only then makes #content visible. This means you also need to set the initial opacity to 0 so it doesn't appear on load and also remove the visibility from the keyframes - these aren't doing anything anyway:
// wait for the animation length, plus a bit, then make the element visible
window.setTimeout(function() {
document.getElementById('content').style.visibility = 'visible';
}, 1100);
#container {
position:relative;
width:100px;
height:100px;
border-style:inset;
}
#content {
visibility:hidden;
-webkit-animation:animDown 1s ease;
position:absolute;
top:100px;
width:100%;
height:100%;
background-color:lightgreen;
opacity:0;
}
#container:hover #content {
-webkit-animation:animUp 1s ease;
animation-fill-mode:forwards;
-webkit-animation-fill-mode:forwards;
}
#-webkit-keyframes animUp {
0% {
-webkit-transform:translateY(0);
opacity:0;
}
100% {
-webkit-transform:translateY(-100%);
opacity:1;
}
}
#-webkit-keyframes animDown {
0% {
-webkit-transform:translateY(-100%);
opacity:1;
}
100% {
-webkit-transform:translateY(0);
opacity:0;
}
}
<div id="container">
<div id="content"></div>
</div>
Solution 3 - Use transitions
In your scenario, you can make this CSS only by replacing the keyframes with a transition instead, so it starts with opacity:0 and just the hover has a change in opacity and the transform:
#container {
position:relative;
width:100px;
height:100px;
border-style:inset;
}
#content {
position:absolute;
top:100px;
width:100%;
height:100%;
background-color:lightgreen;
/* initial state - hidden */
opacity:0;
/* set properties to animate - applies to hover and revert */
transition:opacity 1s, transform 1s;
}
#container:hover #content {
/* Just set properties to change - no need to change visibility */
opacity:1;
-webkit-transform:translateY(-100%);
transform:translateY(-100%);
}
<div id="container">
<div id="content"></div>
</div>
Is there a way to do this pure CSS ?
Yes, absolutely : See the fork http://jsfiddle.net/5r32Lsme/2/
There is really no need for JS.
and I'd prefer it to run only after a hover event.
So you need to tell CSS what happens when it is NOT a hover event as well - in your example :
#container:not(:hover) #content {
visibility: hidden;
transition: visibility 0.01s 1s;
}
But there are two things to note:
1) The transition delay above should match your animation duration
2) You can't use the property which you use to hide the animation onLoad in the animation.
If you do need visibility in the animation, hide the animation initially like e.g.
#container:not(:hover) #content {
top: -8000px;
transition: top 0.01s 1s;
}
A sidenote:
It is recommended to put native CSS properties after prefixed ones, so it should be
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
and now there is a native transform
-webkit-transform: translateY(0);
transform: translateY(0);
If you're looking at this after 2019, a better solution is this:
let div = document.querySelector('div')
document.addEventListener('DOMContentLoaded', () => {
// Adding timeout to simulate the loading of the page
setTimeout(() => {
div.classList.remove('prevent-animation')
}, 2000)
document.querySelector('button').addEventListener('click', () => {
if(div.classList.contains('after')) {
div.classList.remove('after')
} else {
div.classList.add('after')
}
})
})
div {
background-color: purple;
height: 150px;
width: 150px;
}
.animated-class {
animation: animationName 2000ms;
}
.animated-class.prevent-animation {
animation-duration: 0ms;
}
.animated-class.after {
animation: animation2 2000ms;
background-color: orange;
}
#keyframes animationName {
0% {
background-color: red;
}
50% {
background-color: blue;
}
100% {
background-color: purple;
}
}
#keyframes animation2 {
0% {
background-color: salmon;
}
50% {
background-color: green;
}
100% {
background-color: orange;
}
}
<div class="animated-class prevent-animation"></div>
<button id="btn">Toggle between animations</button>
Having had to solve a similar challenge, a neat CSS-only trick morewry posted already back in 2013 is to create an animation that initially is in a paused play-state on a keyframe hiding the element:
#content {
animation:animDown 1s ease, hasHovered 1ms paused;
animation-fill-mode: forwards; /* for both animations! */
}
#container:hover #content {
animation:animUp 1s ease, hasHovered 1ms;
}
/* hide #content element until #container has been hovered over */
#keyframes hasHovered {
0% { visibility: hidden; } /* property has to be removed */
100% { visibility: visible; } /* from the other animations! */
}
When hovering, the very brief animated transformation is applied and stays in the 100%-keyframe-state even after mouse-leave thanks to the animation-fill-mode.
For how to set animation sub-properties with multiple animations, see https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Using_CSS_animations#setting_multiple_animation_property_values
This is not pure CSS but maybe someone will stumble across this thread as I did:
In React I solved this by setting a temporary class in ComponentDidMount() like so:
componentDidMount = () => {
document.getElementById("myContainer").className =
"myContainer pageload";
};
and then in css:
.myContainer.pageload {
animation: none;
}
.myContainer.pageload * {
animation: none;
}
If you are not familiar the " *" (n.b. the space) above means that it applies to all descendents of the element as well. The space means all descendents and the asterisk is a wildcard operator that refers to all types of elements.
It's always better a solution without relying on javascript.
The ones with CSS mentioned here are ok. The idea of hiding when not on mouse hover is fine for some situations, but I noticed that if I wanted the animation to happen when the mouse moves out of the element, it wouldn't happen because of the :not(:hover) rule.
The solution I came up worked best for me, by adding a animation to the parent element, that only adds opacity at the end with the same duration. Easier shown than explain:
I grabbed the fiddle made by #sebilasse and #9000 and I added the below code there:
https://jsfiddle.net/marcosrego/vqo3sr8z/2/
#container{
animation: animShow 1s forwards;
}
#keyframes animShow {
0% {
opacity: 0;
}
99% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Rotation animation that (appears) not to run until needed.
The CSS below allows for up and down arrows for showing menu items.
The animation does not appear to run on page load, but it really does.
#keyframes rotateDown {
from { transform: rotate(180deg); }
to { transform: rotate(0deg); }
}
#keyframes rotateUp {
from { transform: rotate(180deg); }
to { transform: rotate(0deg); }
}
div.menu input[type='checkbox'] + label.menu::before {
display :inline-block;
content : "▼";
color : #b78369;
opacity : 0.5;
font-size : 1.2em;
}
div.menu input[type='checkbox']:checked + label.menu::before {
display : inline-block;
content : "▲";
color : #b78369;
opacity : 0.5;
font-size : 1.2em;
}
div.menu input[type='checkbox'] + label.menu {
display : inline-block;
animation-name : rotateDown;
animation-duration : 1ms;
}
div.menu input[type='checkbox']:checked + label.menu {
display : inline-block;
animation-name : rotateUp;
animation-duration : 1ms;
}
div.menu input[type='checkbox'] + label.menu:hover {
animation-duration : 500ms;
}
div.menu input[type='checkbox']:checked + label.menu:hover {
animation-duration : 500ms;
}
From top to bottom:
Create the rotations. For this there are two... one for the down arrow and one for the up arrow. Two arrows are needed, because, after the rotation, they return to their natural state. So, the down arrow starts up and rotates down, while the up arrow starts down and rotates up.
Create the little arrows. This is a straight forward implementation of ::before
We put the animation on the label. There is nothing special, there, except that the animation duration is 1ms.
The mouse drives the animation speed. When the mouse hovers over the element, the animation-duration is set to enough time to seem smooth.
Working on my site
Building off of Tominator's answer, in React, you can apply it per component like so:
import React, { Component } from 'react'
export default class MyThing extends Component {
constructor(props) {
super(props);
this.state = {
preloadClassName: 'preload'
}
}
shouldComponentUpdate(nextProps, nextState) {
return nextState.preloadClassName !== this.state.preloadClassName;
}
componentDidUpdate() {
this.setState({ preloadClassName: null });
}
render() {
const { preloadClassName } = this.state;
return (
<div className={`animation-class ${preloadClassName}`}>
<p>Hello World!</p>
</div>
)
}
}
and the css class:
.preload * {
-webkit-animation-duration: 0s !important;
animation-duration: 0s !important;
transition: background-color 0s, opacity 0s, color 0s, width 0s, height 0s, padding 0s, margin 0s !important;
}
I'm trying to create a CSS3 sliding animation. The slideDown part works, but the going up part doesn't seem to trigger instantly and I can't figure out why.
.slideUp{
-webkit-animation:slideUpFrames 1s;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes slideUpFrames{
0%{
max-height:1000px;
}
100%{
max-height:0px;
}
}
.slideDown{
-webkit-animation:slideDownFrames 1s;
-webkit-animation-fill-mode: forwards;
}
.slidable{
overflow: hidden;
}
#-webkit-keyframes slideDownFrames{
0%{
max-height: 0px;
}
100%{
max-height:1000px;
}
}
I've created a fiddle (webkit only): http://jsfiddle.net/5E7YQ/
How could I fix this?
The slideUp animation is triggering immediately you just can't see the first 940px of the animation, because your <ul class="slidable"> is only 60px tall.
So now that we know what's going on here's how it can be fixed:
Working Example
.slideUp {
-webkit-animation:slideUpFrames .5s; /* shorten time */
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes slideUpFrames {
0% {
max-height:60px; /* change 1000px to the height of the element */
}
100% {
max-height:0px;
}
}
.slideDown {
-webkit-animation:slideDownFrames .5s; /* shorten time */
-webkit-animation-fill-mode: forwards;
}
.slidable {
overflow: hidden;
}
#-webkit-keyframes slideDownFrames {
0% {
max-height: 0px;
}
100% {
max-height:60px; /* change 1000px to the height of the element */
}
}
Or if you would like you can shorten the whole thing and use .slideUp(); and .slideDown();
Working Example 2