I have an animation and I have applied it to one of the html element just fine, but then when I applied the same animation on hover to another element(img) it just keep on flickering.
My CSS
.logo-box {
position: absolute;
top: 40px;
left: 40px;
}
.logo {
height: 35px;
}
.logo-box:hover {
animation: moveInRight 1s ease-in;
}
#keyframes moveInRight {
0% {
opacity: 0;
transform: translateX(100px);
}
80% {
transform: translateX(-10px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
.logo-box is absolute to the .header class
My HTML body
<body>
<header class="header">
<div class="logo-box">
<img class="logo" src="img/logo-white.png" alt="logo" />
</div>
<div class="text-box">
<h1 class="heading-primary">
<span class="heading-primary-main">Outdoors</span>
<span class="heading-primary-sub">is where life happends</span>
</h1>
</div>
</header>
</body>
Can anybody help me out fixing this...
Add a delay to the start of the animation.
.logo-box:hover {
animation: moveInRight 1s ease-in 0.5s;
/*the 0.5s is the delay*/
}
Explanation if you want to know whats going on:
This is a well known problem that is actually related to UX. The flicker problem is because of the opacity. As soon as a :hover occurs (event triggered) the opacity goes to zero. Now as you take your pointer to the image, multiple hover events are triggered due to micro movements of pointer. One hover event ends and second is triggered. CSS stops animating as soon as hover is ended and opacity gets to 100% and the second hover event causes it to go to 0 right away which is the flicker. If you add some delay then the mouse would get stable and then the animation will be played.
CSS, yet, isn't offering any way to complete the animation once hover is triggered i.e. no matter if the pointer is no more on the element, animation must be completed.
Related
I am trying to make a loading animation. I am using css transition to transition into the loading by scaling and then using animation to scale out the x axis. But when I try to transition back to the original state it doesn't use the transition anymore it just snaps back. I could use animation for the whole thing but I want to account for the page continuing to load so I don't want to have to write extra javascript logic to handle it. It would be nice if It would just transition on its own.
When you click the following snippet the first time it works fine. But when you click it again it just snaps back to its original state and doesn't use the transition. If you use a different property like opacity in the animation part then it works fine so I'm assuming there is something with the browser not recognizing the current scaled value. Is this a bug or am I doing something wrong?
document.querySelector('.wrapper').addEventListener('click', () => {
document.querySelector('.wrapper').classList.toggle('loading')
})
.wrapper{
position:fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.wrapper > div{
color: white;
display:flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: blue;
transition: transform 500ms ease-out;
transform: scale(1);
}
.wrapper.loading > div{
transform: scale(0.2, 0.002);
animation: loading 1000ms ease-out infinite;
animation-delay: 500ms;
}
#keyframes loading {
0%{
transform: scale(0.2, 0.002)
}
50%{
transform: scale(0.5, 0.002)
}
100%{
transform: scale(0.2, 0.002)
}
}
<div class="wrapper">
<div>click me</div>
</div>
TL;DR
I believe that this happens because CSS transition eventually gives a class two states and transitions between them, when you remove your class you don't change its state, you remove it. my solution would be to add another class to set it back.
CSS transitions work by defining two states for the object using CSS. In your case, you define how the object looks when it has the class "loading" and you define how it looks when it doesn't have the class "saved" (it's normal look). When you remove the class "loading", it will transition to the other state according to the transition settings in place for the object without the "loading" class.
If the CSS transition settings apply to the object (without the "loading" class), then they will apply to both transitions.
your transition CSS settings only apply to .saved and thus when you remove it, there are no controls to specify a CSS setting. You may want to add another class ".fade" that you leave on the object all the time and you can specify your CSS transition settings on that class so they are always in effect.
I don't know a pure css fix for this.
But you can add a different class with a animation that restores to what it was before with JS
const wrapper = document.querySelector(".wrapper");
wrapper.onclick = () => {
if ([...wrapper.classList].includes("loading")) {
wrapper.classList.add("restore");
} else {
wrapper.classList.remove("restore");
}
wrapper.classList.toggle("loading");
};
.wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.wrapper>div {
color: white;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: blue;
animation: none;
transform: scale(1);
transition: transform 500ms ease-out;
}
.wrapper.restore>div {
animation: restore 500ms ease-out;
}
.wrapper.loading>div {
transform: scale(0.2, 0.002);
animation: loading 1000ms 500ms ease-out infinite;
}
#keyframes restore {
0% {
transform: scale(0.2, 0.002);
}
100% {
transform: scale(1);
}
}
#keyframes loading {
0% {
transform: scale(0.2, 0.002)
}
50% {
transform: scale(0.5, 0.002)
}
100% {
transform: scale(0.2, 0.002)
}
}
<div class="wrapper">
<div>click me</div>
</div>
You can use animation iteration count property:
div {
animation-iteration-count: 2;
}
or use fill mode to freeze the animation at the end:
-webkit-animation-fill-mode: forwards;
Can an animating element detect the actual mouse pointer position and add a hover state this way?
In the below example, there is a simple div moving left and right, if you hover over the div it will become black, however when you leave your mouse pointer in the path of the animating element, without moving it, the hover state won't be applied.
div{
width: 100px;
height: 100px;
background: red;
animation: move 1s infinite alternate;
}
div:hover {
background: black;
}
#keyframes move{
0%{ transform: translateX(0); }
100%{ transform: translateX(100px); }
}
<div></div>
The other way around works the same, when you actually hover the div and don't move your mouse, the div will remain black even if the mouse pointer is not actually hovering this element anymore.
So, is it possible to keep switching normal to hover state based on the static position of the mouse pointer?
it's not possible to do this with translate, because it has a static position. Like isherwood wrote, the translated element will always exist in its original location.
You could do this with absolute positioning, where u really move the element.
div{
width: 100px;
height: 100px;
background: red;
animation: move 1s infinite alternate;
position: absolute;
}
div:hover {
background: black;
}
#keyframes move{
0%{ left: 0; }
100%{ left: 100px; }
}
<div></div>
I have a div that is acting as a navigation bar for my webpage. The div consists of a horizontal unordered list where each list item is an image. The unordered list has a fade-in animation on load, and each list item has a hover effect where it grows in scale upon mouseover.
For some reason, whenever I load the page, either in Dreamweaver's live view screen or as a preview on the web browser, the div starts a few pixels off the position to the right, and once the fade-in animation is completed, it 'twitches' back to its proper position.
Its very frustrating because this is not complicated code. I only have the Source Code page and its CSS stylesheet loaded in the project.
This is all the HTML code related to the Navigation bar:
<div class="Nav">
<ul>
<li>
<img src="icons/filmicon.png" width="120px" height="120px" alt="Filmography"><br/>
</li>
<li>
<img src="icons/cameraicon.png" width="120px" height="120px" alt="Photography"><br/>
</li>
<li id="josh">
<img src="img/joshforsite.png" width="300px" height="300px" alt="About Me"><br/>
</li>
<li>
<img src="icons/designicon.png" width="120px" height="120px" alt="Design"><br/>
</li>
<li>
<img src="icons/brandicon.png" width="120px" height="120px" alt="Branding"><br/>
</li>
</ul>
</div>
...and this is all the CSS code related to the Navigation bar:
.Nav {
display: flex;
flex-direction: row;
justify-content: center;
list-style-type: none;
position: absolute;
width: 100%;
padding-top: 16%;
white-space: nowrap;
.Nav li {
vertical-align: middle;
display: inline-block;
padding-right: 4%;
opacity: 1;
-webkit-animation: fadein 2s;
-moz-animation: fadein 2s;
-ms-animation: fadein 2s;
-o-animation: fadein 2s;
animation: fadein 2s;
transition: all .3s ease-in-out;
.Nav li:hover {
-webkit-transform: scale(1.2);
-ms-transform: scale(1.2);
transform: scale(1.2);
#keyframes fadein { from { opacity: 0; } to { opacity: 1; }}
#-moz-keyframes fadein { from { opacity: 0; } to { opacity: 1; }}
#-webkit-keyframes fadein {from { opacity: 0; }to { opacity: 1; }}
#-o-keyframes fadein { from { opacity: 0; } to { opacity: 1; }}
Again, I am a beginner at HTML & CSS so I don't how much of a mess the coding is.
Here is a link to a YouTube video I uploaded showing the problem. It also shows towards the end a second issue I'm having whereby the growing hover effect is bugged. Any help with this would be appreciated.
Thank you!
Change the padding-right on .Nav li to a px based solution instead of a percentage and it should eliminate that jump left.
Also, you're missing your closing curly brackets for each block.
You are using images with alternative text. The glitching is probably caused by loading the images. Try to preload the images with javascript and it might help.
Hi i'm just a student I just wanna know if its possible to combine hover, transition, and transform by just using css.
How can transformed image transitioned back to it's original size and shape when hovered?
<html>
<style>
.sample {
display: inline-block;
border: 0px solid #fff;
margin: 10px;
overflow: hidden;
height: 500px;
width: 140px;
transform: rotate(0deg);
webkit-transition: 0.8s;
transition: 0.7s;
}
.sample img {
display: block;
transform: rotate(2deg);
transform-origin: 200% -600%;
}
.sample img:hover {
width: 600px;
height: 600px;
transform: rotate(0deg);
transform-origin: 0% 0%;
-webkit-transition-timing-function: ease-in-out;
}
</style>
<body>
<div class="sample">
<img src="http://www.freegreatpicture.com/files/39/1264-tree.jpg" height="600" width="600">
</div>
</body>
</html>
If you only define the CSS "transformed" rules in the hover pseudo-class, then when the image is no longer being hovered-over it will automatically transition back to its original state.
Here is a simplified example using part of your code (I changed the image to the Wikipedia logo since your image was coming up broken):
.sample img {
transform: rotate(30deg);
transition: ease-in-out 700ms;
}
.sample img:hover {
transform: rotate(0deg);
}
<div class="sample">
<img src="https://en.wikipedia.org/static/images/project-logos/enwiki.png">
</div>
The hover pseudo-class is an "active state class", meaning it only comes into play while that action is taking place (i.e., the pointer is hovered over the element).
If you want to include special easing and timing rules on the change from default state to hovered state then include the transition property in the default rule. You can specify lengths of time over which the transition takes place so the change can be more "animated". You'll notice that in the example above I stretched the rotation to 700ms so you can see it turning when hovered, then turning back when no longer hovered.
I've got not animated element as default. There's also a trigger that lets me turn on & off animation on that element. The animation itself is very simple: moves element from left to the right and back.
When I stop animation, then my element obviously goes back to initial position. But it goes back suddenly, not smoothly. So it just changes its position from the one when I turned off animation to initial one. My question is: is there a way to stop it smoothly, so when I turn off the animation it goes back to initial position but smoothly/animating.
Here's my element and animation: http://jsfiddle.net/2Lwftq6r/
HTML:
<input type="checkbox" id="anim">
<label for="anim">Start / stop animation</label>
<div></div>
CSS:
div {
margin-top: 50px;
width: 50px; height: 10px;
background: #000;
transform: translateX(0);
}
#anim:checked ~ div {
-webkit-animation: dance 2s infinite ease-in-out;
-moz-animation: dance 2s infinite ease-in-out;
}
#-webkit-keyframes dance {
0%, 100% { -webkit-transform: translateX(0); }
50% { -webkit-transform: translateX(300px); }
}
#-moz-keyframes dance {
0%, 100% { -moz-transform: translateX(0); }
50% { -moz-transform: translateX(300px); }
}
I just had the same problem and I solved it by not using animation and it works perfectly! Check out my solution:
So I had this spatula that I had to move when hovered over only, and I wanted it to transition back smoothly, so this is what I did:
#Spatula:hover{
animation-direction:alternate;
transform: translate(1.2cm,1cm);
transition: all 1.5s;
-webkit-transition: all 1.5s;
}
#Spatula{
-webkit-transition: all 1.5s;
transition: all 1.5s;
}
Good luck!
You can't archive this effect only CSS3 way, but if you really need it, you could use jQuery + CSS3 Transitions. My solution (http://jsfiddle.net/sergdenisov/3jouzkxr/10/):
HTML:
<input type="checkbox" id="anim-input">
<label for="anim-input">Start / stop animation</label>
<div class="anim-div"></div>
CSS:
.anim-div {
margin-top: 50px;
width: 50px;
height: 10px;
background: #000;
}
.anim-div_active {
-webkit-animation: moving 2s ease-in-out infinite alternate;
animation: moving 2s ease-in-out infinite alternate;
}
.anim-div_return {
-webkit-transition: -webkit-transform 0.5s ease-in-out;
transition: transform 0.5s ease-in-out;
}
#-webkit-keyframes moving {
0% { -webkit-transform: translateX(0); }
100% { -webkit-transform: translateX(300px); }
}
#keyframes moving {
0% { transform: translateX(0); }
100% { transform: translateX(300px); }
}
Javascript:
$('#anim-input').on('change', function() {
var $animDiv = $('.anim-div');
if (this.checked) {
$animDiv.removeClass('anim-div_return')
.addClass('anim-div_active');
return;
}
var transformValue = $animDiv.css('webkitTransform') ||
$animDiv.css('transform');
$animDiv.css({'webkitTransform': transformValue,
'transform': transformValue})
.removeClass('anim-div_active');
requestAnimationFrame(function() {
$animDiv.addClass('anim-div_return')
.css({'webkitTransform': 'translateX(0)',
'transform': 'translateX(0)'});
});
});
P.S.
Vendor prefixes are based on actual browsers list from http://caniuse.com.
Check out This StackOverflow question.
You aren't going to like this answer, but reality is that CSS3
animations aren't really useful to achieve this. To make this work you
would need to replicate a lot of your CSS in your Javascript which
kind of destroys the point (Like for example in this closely related
answer
Change speed of animation CSS3?).
To really make it stop smoothly your best bet would be to write the
animation on a platform like the Greensock animation library
which provides all the tools you need to make it actually smoothly
stop instead of suddenly stop.
There's also another answer below it that does make an effort at using CSS, you can look at that one.
There is also an alternate solution, it might not give you the desired effect of going back to it's original state, but since nobody mentioned it and this problem seems to have no solution, it's possible to pause the animation purely in css, locking it's state until it's started again
To pause the animation you need first to make the animation available even when the checkbox is not checked
And make use of the animation-play-state property
div {
margin-top: 50px;
width: 50px; height: 10px;
background: #000;
animation: dance 2s infinite ease-in-out paused;
}
#anim:checked ~ div {
animation-play-state: running;
}
#keyframes dance {
0%, 100% { transform: translateX(0); }
50% { transform: translateX(300px); }
}
<input type="checkbox" id="anim">
<label for="anim">Start / stop animation</label>
<div></div>