How to play an animation on hover and pause when hover is not active
Use animation
instead of transition
and make use of animation-play-state
MDN
button{
animation: rotate360 1.2s linear infinite; /* animation set */
animation-play-state: paused; /* ...but paused */
}
button:hover{
animation-play-state: running; /* Run on hover! */
}
@keyframes rotate360 {
to { transform: rotate(360deg); }
}
<button>X</button>
Play CSS animation on hover, pause on hover out
example jsfiddle
set the animation on #tech
with play state paused
#tech {
-webkit-animation-play-state:paused;
-webkit-animation: moveSlideshow 10s linear infinite;
}
then change play-state to running on hover
#tech:hover{
-webkit-animation-play-state:running;
}
Pause a WebKit animation on hover
Instead of:
.quote:nth-child(1):hover
{
-webkit-animation-play-state: paused;
-moz-animation-play-state: paused;
-o-animation-play-state: paused;
animation-play-state: paused;
}
use:
.quote-wrapper:hover .quote
{
-webkit-animation-play-state: paused;
-moz-animation-play-state: paused;
-o-animation-play-state: paused;
animation-play-state: paused;
}
DEMO: http://jsfiddle.net/j4Abq/2/
CSS start and pause animation on hover
Oh, you are really close to it. Just need to add the keyframe for the 100%
state as well.
.pers { margin-bottom: -4px; width: 300px; height: 300px; display: inline-block; background-color: green; clip-path: polygon(50% 52%, 100% 0, 100% 100%, 0% 100%);}
.pers:hover { animation: polygons 1s; animation-fill-mode: forwards;}
@keyframes polygons { 75%,100% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }}
<div class="thisUs"> <div class="pers"> </div>
Keep item animated after unhover
You need some way of the element 'remembering' that it has to carry on rotating.
For that you'll need a bit of Javascript to sense when the mouse is hovering over the element and to sense when the transition has ended. These events will add and remove a class respectively.
const div = document.querySelector('.header .logo img');
function addRotate() {
div.classList.add('rotate');
}
function removeRotate() {
div.classList.remove('rotate');
}
div.addEventListener('mouseover', addRotate);
div.addEventListener('transitionend', removeRotate);
.header .logo img {
transform: rotate(0deg);
transition: transform 0s 0s;
}
.header .logo img.rotate {
transform: rotate(360deg);
transition: transform 1.2s;
}
<div class="header">
<div class="logo">
<img src="https://picsum.photos/id/1015/200/300">
</div>
</div>
css3 animation on :hover; force entire animation
I'm afraid that the only way to solve this is with a bit of javascript, you must add the animation as a class and then remove it when the animation finishes.
$(".box").bind("webkitAnimationEnd mozAnimationEnd animationend", function(){
$(this).removeClass("animated")
})
$(".box").hover(function(){
$(this).addClass("animated");
})
http://jsfiddle.net/u7vXT/
Animation not stopping on hover using webkit-animation-play-state
There is no way to achieve a one-time hover without JavaScript or jQuery:
CSS:
.one_time {
-webkit-animation-play-state: paused;
}
JavaScript:
function hoverOnce(target, type, listener) {
target.addEventListener(type, function fn(event) {
target.removeEventListener(type, fn);
listener(event);
});
};
hoverOnce(document.getElementById("myelement"), "mouseover", function (event) {
document.getElementById("myelement").className = "one_time";
});
jQuery:
$(".button-color-2").one("mouseenter", function(e){
$("#myelement").addClass("one_time");
});
How can I make Animation Play State paused to work in React on hover
The problem
1. There is a difference between transition and animation in CSS
concepts, between them, there is the definition of "pause" (so to
speak) is only available in animations
It is noticed that it
is possible to imitate this functionality (pause an transition)
using javascript, but if we depend only on CSS, this is impossible.
Reference: How do I pause CSS transition?
2. You are using a CSS property that is meant for animations, and there no transitions, which is: animation-play-state
Importante note
It is important to note that it is possible to remove a css transition, simply removing the transition property, or overwriting it, example: transition: none !important, but when removing a transition, it is not possible to resume it and the "animation" is lost in this process.
The solution
1. Create a function capable of restarting an animation, note that this is importante because at the end of the first animation (onAnimationEnd) it is necessary to restart the count of x seconds for the progress bar, otherwise, it would only work once.
Note: The key to restarting a CSS animation is to set the animation-name of an animation to 'none' and then setting it back to the original animation
Example:
const startAnimation = () => {
if (!progressRef.current) return;
const progress = progressRef.current;
progress.style.animationName = "none";
progress.style.width = "100%";
setTimeout(() => {
progress.style.animationName = "width";
progress.style.animationDuration = `${slideShowDelay}s`;
}, 50);
}
2. Call this function on every slide change, whether it's forward or previous, example:
First option:
const prevButtonHandler = () => {
startAnimation(); // <<- HERE
setCurrentSlide((prev) => {
const result = prev - 1;
if (result < 0) {
return images.length - 1;
}
return result;
});
};
const nextButtonHandler = useCallback(() => {
startAnimation(); // <<- HERE
setCurrentSlide((prev) => {
const result = prev + 1;
if (result >= images.length) {
return 0;
}
return result;
});
}, [images.length]);
OR
Second option:
Or better yet, we can put the startAnimation
function inside useEffect
which will capture every slide change, so no matter the slide is coming back or forward, the application will work normally.
Example:
useEffect(() => {
startAnimation();
}, [currentSlide, slideShowDelay]);
3. Create the animation frame in CSS:
@-webkit-keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}
@keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}
In the example above we have specified when the style will change by using the keywords "from" and "to" (which represents 0% (start) and 100% (complete)).
4. Change using onTransitionEnd to onAnimationEnd, example:
<div
onAnimationEnd={animationEndHandler}
ref={progressRef}
role={"progressbar"}
className={classes}
/>
The code
Typescript
import { Fragment, useEffect, useState, useCallback, useRef } from "react";
import "./Slider.css";
type Props = {
images: string[];
slideShowDelay?: number;
};
export default function Slider({
images,
slideShowDelay = 5
}: Props): JSX.Element {
const [currentSlide, setCurrentSlide] = useState<number>(0);
const progressRef = useRef<HTMLDivElement | null>(null);
const [animationState, setAnimationState] = useState("animate");
const startAnimation = () => {
if (!progressRef.current) return;
const progress = progressRef.current;
progress.style.animationName = "none";
progress.style.width = "100%";
setTimeout(() => {
progress.style.animationName = "width";
progress.style.animationDuration = `${slideShowDelay}s`;
}, 50);
}
const prevButtonHandler = () => {
setCurrentSlide((prev) => {
const result = prev - 1;
if (result < 0) {
return images.length - 1;
}
return result;
});
};
const nextButtonHandler = useCallback(() => {
setCurrentSlide((prev) => {
const result = prev + 1;
if (result >= images.length) {
return 0;
}
return result;
});
}, [images.length]);
useEffect(() => {
startAnimation();
}, [currentSlide, slideShowDelay]);
const slides = images.map((image, i) => {
const styles = {
transform: `translateX(${(i - currentSlide) * 100}%)`
};
return (
<Fragment key={i}>
<div className="slide" style={styles}>
<img src={image} alt="random" />
</div>
</Fragment>
);
});
const mouseHandler = () => {
setAnimationState("paused");
};
const mouseHandlerLeave = () => {
setAnimationState("animate");
};
const animationEndHandler = nextButtonHandler;
const classes = `progress-bar ${animationState}`;
const containerClasses = `slider-container ${animationState}`;
return (
<>
<div className="container">
<div
className={containerClasses}
onMouseEnter={mouseHandler}
onMouseLeave={mouseHandlerLeave}
>
{slides}
<button className="btn btn-prev" onClick={prevButtonHandler}>
{" "}
{"<"}{" "}
</button>
<button className="btn btn-next" onClick={nextButtonHandler}>
{" "}
{">"}{" "}
</button>
<div
onAnimationEnd={animationEndHandler}
ref={progressRef}
role={"progressbar"}
className={classes}
/>
</div>
</div>
</>
);
}
CSS
/* Safari 4.0 - 8.0 */
@-webkit-keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}
@keyframes width {
from {
width: 100%;
}
to {
width: 0%;
}
}
.container {
width: 100vw;
display: grid;
place-items: center;
}
.container .slider-container {
width: 100%;
max-width: 600px;
height: 400px;
position: relative;
overflow: hidden;
}
.container .slider-container .slide {
position: absolute;
width: 100%;
max-width: 600px;
height: 400px;
transition: all 0.5s;
}
.container .slider-container .slide:hover {
animation-play-state: paused;
}
.container .slider-container .slide img {
object-fit: cover;
width: 600px;
height: 400px;
}
.container .slider-container .progress-bar {
position: absolute;
height: 10px;
bottom: 0;
left: 0;
width: 100%;
background-color: #61dafb;
}
.container .slider-container .progress-bar.animate {
animation-play-state: running;
}
.container .slider-container .progress-bar.paused {
animation-play-state: paused;
}
.container .slider-container .btn {
height: 40px;
width: 40px;
position: absolute;
border-radius: 50%;
top: calc(50% - 20px);
z-index: 1;
background-color: #ffffff;
font-size: 18px;
}
.container .slider-container .btn:hover {
cursor: pointer;
transform: scale(1.1);
}
.container .slider-container .btn.btn-prev {
left: 10px;
}
.container .slider-container .btn.btn-next {
right: 10px;
}
Try this:
Demo URL:https://codesandbox.io/s/nifty-meninsky-pkijf0
Remarks
If this answer was not satisfactory, or confusing, or did not answer what was asked, please comment so I can edit it.
It's worth mentioning that I'm using google translator to answer, I apologize for any inconvenience
Related Topics
Center Wrapped Items in a Space-Between Flexbox
How to Change Font-Size of a Tag Using Inline CSS
Why Does Firefox Treat Helvetica Differently from Chrome
Using CSS Mix-Blend-Mode with a Child of a Position Fixed Element
Unbalanced CSS Columns in Chrome
Twitter Bootstrap Accordion and Button Dropdown Overflow Issue
Run CSS File Through Twig When Using {% Stylesheets %} Tag in Twig with Symfony2
How to Use CSS3: :Selection Without Changing The Default Color and Background Color
CSS Sprite Techniques, CSS Background or Img's Clip
Why Am I Unable to Apply a Border to an Angular Mat-Table Row
Pixel Border and Percentage Width in Proportion
Systematically Resolve Conflicting Styles in CSS
Styling Links Inside a Div with a Specific Class
CSS Pseudo-Element: :Before(2);: Before and: :Before
How to Make a Flexbox Container That Stretches to Fit Wrapped Items