:active transition ended by :hover - css

I have these 3 rules:
.thingy{
display:inline-block;
position:relative;
width: 5em;
height: 5em;
background-color:#FF0000;
left:0em;
transition: left 4s linear, background-color 4s;
}
.thingy:active{
left:10em;
transition: left 0s linear;
}
.thingy:hover{
background-color:#00FF00;
transition: background-color 0s linear;
}
and this bit of basic HTML:
<div class="thingy"></div>
When the <div> is clicked, it will move to the right, as expected. However, whenever it is hovered over while it is returning to it's original position, it will snap back immediately.
I want it to, while returning to it's original position from being clicked, to be able to swap it's background-color (or any other property) then fade back to it's normal values without overriding any other transition currently going on.
For the purposes of the code, I can only use pure CSS, and I cannot utilize #key-frames or any property associated to it, such as animation-duration.

You can use CSS variable for this task
.thingy {
display: inline-block;
position: relative;
width: 5em;
height: 5em;
background-color: #FF0000;
left: 0em;
transition:
var(--t-left,left 4s linear),
var(--t-back,background-color 4s);
}
.thingy:active {
left: 10em;
--t-left: left 0s;
}
.thingy:hover {
background-color: #00FF00;
--t-back: background-color 0s
}
<div class="thingy"></div>

Related

CSS transition ignores width

I have an tag which is displayed as a block. On page load, its width is increased by a css animation from zero to some percentage of the containing div (the fiddle contains a MWE, but there is more than one link in this div, each with a different width). On hover, I want it to change colour, change background colour, and also expand to 100% of the div, using a CSS transition. The colour and background colour bit is working, but it seems to ignore the width transition.
Snippet:
.home-bar {
text-decoration: none;
background-color: white;
color: #5e0734;
display: block;
-webkit-animation-duration: 1.5s;
-webkit-animation-timing-function: ease-out;
-webkit-animation-fill-mode: forwards;
animation-duration: 1.5s;
animation-fill-mode: forwards;
transition: color, background-color, width 0.2s linear;/*WIDTH IGNORED*/
border: 2px solid #5e0734;
overflow: hidden;
white-space: nowrap;
margin-right: 0;
margin-left: 5px;
margin-top: 0;
margin-bottom: 5px;
padding: 0;
}
.home-bar:hover {
background-color: #5e0734;
color: white;
width: 100%;/*WIDTH IGNORED*/
text-decoration: none;
}
#bar0 {
-webkit-animation-name: grow0;
animation-name: grow0;
}
#keyframes grow0 {
from {
width: 0%;
}
to {
width: 75%;
}
}
LINK
Note - I've tested it with changing the height of the link on hover, and it worked. Only the width does not work. Perhaps it has something to do with the animation on page-load.
When you set width using animation you will override any other width defined with CSS inluding the one defined by hover. The styles inside a keyframes is more specific than any other styles:
CSS Animations affect computed property values. This effect happens by
adding a specified value to the CSS cascade ([CSS3CASCADE]) (at the
level for CSS Animations) that will produce the correct computed value
for the current state of the animation. As defined in [CSS3CASCADE],
animations override all normal rules, but are overridden by !important
rules. ref
A workaround is to consider both width/max-width properties to avoid this confusion:
.home-bar {
text-decoration: none;
background-color: white;
color: #5e0734;
display: block;
animation: grow0 1.5s forwards;
transition: color, background-color, max-width 0.2s linear;
border: 2px solid #5e0734;
max-width: 75%; /*Set max-wdith*/
}
.home-bar:hover {
background-color: #5e0734;
color: white;
max-width: 100%; /* Update the max-width of hover*/
text-decoration: none;
}
/*Animate width to 100%*/
#keyframes grow0 {
from {
width: 10%;
}
to {
width: 100%;
}
}
LINK

CSS Transition after animation ends

I have a css transition that moves an element on hover and an animation that rotates the element on hover too. There's a delay on the animation equal to the transition duration so that after it's transitioned to it's correct position, the animation starts. And it works nice, however, when we mouse off, the animation stops but it doesn't transition back down.
Is it possible to get it to transition back after we mouse off and the animation ends?
You can see an example here: http://codepen.io/jhealey5/pen/zvXBxM
Simplified code here:
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
&:hover {
span {
transform: translateY(-60px);
animation-name: rotate;
animation-duration: 1s;
animation-delay: .5s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
}
}
span {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
bottom: 10px;
left: 0;
right: 0;
margin: auto;
transition: .5s;
}
#keyframes rotate {
from {
transform: translateY(-60px) rotate(0);
}
to {
transform: translateY(-60px) rotate(-90deg);
}
}
I have forked your project and adapted it so it works. You can find it here.
What I have changed is the following:
I give the white square a start position of top: 150px and let it, on hover of div, get a top: 0. The span gets a transition: top .5s and with that it goes to top: 0; on hover and back to top: 150px; when the mouse leaves.
I have removed the translateY(-60px); from the animation, because that would move it even more up when the animation would start.
Here's your new CSS:
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
&:hover {
span {
top: 0px;
animation: rotate 1s infinite .5s alternate;
animation-direction: alternate;
}
}
}
span {
position: absolute;
width: 20px;
height: 20px;
background-color: #fff;
bottom: 10px;
left: 0;
right: 0;
top: 150px;
margin: auto;
transition: top .5s;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(-90deg);
}
}
Edit: The problem is that an animation is time-based and not action-based, which means that as soon as you trigger an animation, a timer starts running and it will run through all the keyframes until the set time has passed. Hover-in and hover-out have no effect, except that the timer can be stopped prematurely, but the animation will not continue (or reversed, which you wanted) after that. transition is action-based, which means it gets triggered every time an action (for example :hover) is happening. On :hover, this means it takes .5s to go to top:0 and when the hover ends, it takes .5s to got to top:150px.
I hope the above addition makes sense :)
As you can see, I also cleaned up a bit in your animation-name: etc., since it can be combined into one line.
As Harry pointed out, the problem is that you are animating/transitioning the same property, in this case transform. It looks like the current versions of Chrome/FF will allow the animation to take control of the property, thereby breaking the transition. It seems like the only way to work around this is to transition/animation a different property. Since you need to continue rotating the element, you could translate/position the element by changing the bottom property instead. I know that doesn't produce the exact same results, but nonetheless, it does move the element (just not relative to the parent element).
Updated Example
div:hover span {
bottom: 80px;
}
As an alternative, you could also wrap the span element, and then translate that element instead.
In the example below, the .wrapper element is transitioned to translateY(-60px) on hover, and then the child span element is rotated and maintains the animation.
Example Here
div {
width: 200px;
height: 200px;
margin: 40px auto;
background-color: #b00;
position: relative;
}
div:hover .wrapper {
transform: translateY(-60px);
}
div:hover .wrapper span {
animation-name: rotate;
animation-duration: 1s;
animation-delay: .5s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
.wrapper {
display: inline-block;
transition: .5s;
position: absolute;
bottom: 10px;
left: 0;
right: 0;
text-align: center;
}
.wrapper span {
display: inline-block;
width: 20px;
height: 20px;
background-color: #fff;
}
#keyframes rotate {
from {
transform: rotate(0);
}
to {
transform: rotate(-90deg);
}
}
<div>
<span class="wrapper">
<span></span>
</span>
</div>

Angular 1.2: Animating list items in parallel using ngAnimate and CSS

I have a list and when I add an item to this list I wish to animate it into view and any existing items that are currently in view should also animate in parallel - think of a vertical conveyor belt going top to bottom.
I have the whole thing nearly working apart from the viewable items are snapping into place when adding a new item. Here's a snippet if code:
<div class="outerContainer">
<div class="container" ng-repeat="item in items">
.....
</div>
</div>
.outerContainer {
height: 200px;
overflow: hidden;
}
.container {
position: relative;
background-color: lightgray;
margin: 1px;
width: 200px;
height: 50px;
}
.container.ng-enter {
-webkit-transition: 0.5s linear all;
transition: 0.5s linear all;
}
.container.ng-enter {
top:-50px;
}
.container.ng-enter.ng-enter-active {
top:0;
}
Any helpful pointers would be greatly appreciated.
I believe your transitions have the transition property in the wrong location, it should read like this
.container.ng-enter {
-webkit-transition: all 0.5s linear;
transition: all 0.5s linear;
}

how to animate scaling an image over time via webkit

I have collection of images in a simple gallery that I want to transform from small to large smoothly on mouseover.
I am currently doing this by revealing the actual size of an image when the mouse is over but forcing it to a certain size when it is not and hiding the real size with display:none.
I want to include some webkit transformations to do this over a 1s period to improve the transitions. I understand webkit is to transform an element between two states however is there anyway I can make this happen.
I also want to avoid JavaScript.
.reveal a .preview
{
display: none;
}
.reveal a:hover .preview
{
display: block;
position: absolute;
z-index: 1;
}
.reveal img
{
background: #fff
padding: 2px;
vertical-align: top;
width: 100px;
height: 75px;
}
.reveal li
{
background: #eee;
display: inline;
float: left;
margin: 3px;
padding: 5px;
position: relative;
}
.reveal .preview
{
border-color: #000;
width: auto;
height: auto;
}
without the html (ie jsfiddle) it's hard for me to insert the solution within your code.. but here is a generic solution http://jsfiddle.net/9QVae/2/
img
{
width:100px;
height:100px;
background:red;
transition:width 1s, height 1s;
-moz-transition:width 1s, height 1s, -moz-transform 1s; /* Firefox 4 */
-webkit-transition:width 1s, height 1s, -webkit-transform 1s; /* Safari and Chrome */
-o-transition:width 1s, height 1s, -o-transform 1s; /* Opera */
}
on hover:
img:hover
{
width:200px;
height:200px;
}
so the trick is to specify the css property you want to add an effect to (ie width)
then specify the duration of the event ie transition:width 1s; then you specify the final dimension under the :hover selector
note: transition does not work on IE

Why does this div obscure this button?

I want a div to float next to my input but instead it's floating over top of it, and I'm not sure why. It's as if the div is set to use absolute positioning. I think I'm probably just overlooking something silly, but what is it?
html:
<input type="file" id="files" name="file" />
<div id="progress_bar"><div class="percent">0%</div></div>​
css:
input { float: left;}
#progress_bar {
margin: 10px 0;
padding: 3px;
border: 1px solid #000;
font-size: 14px;
//clear: both;
opacity: 0;
-moz-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-webkit-transition: opacity 1s linear;
}
#progress_bar.loading {
opacity: 1.0;
}
#progress_bar .percent {
background-color: #99ccff;
height: auto;
width: 0;
} ​
I have an example here:
http://jsfiddle.net/sWrvU/
which is based on the read files demo on html5rocks http://www.html5rocks.com/en/tutorials/file/dndfiles/
Uncomment clear:both to see the demo actually work (i.e. you can press the button because there's not a div on top of it), but then obviously the div still isn't floated next to the input.
Using display: block instead of opacity removes the transition, which I'm guessing you're trying to keep.
The Progress bar isn't "floating over top" so much as the input is floating underneath. If you float the progress bar as well, things should go a little better: http://jsfiddle.net/cjc343/sWrvU/24/
I changed it to use display instead of opacity since opacity means the element is still there even though it is transparent.
CSS
input {
float: left;
}
#progress_bar {
margin: 10px 0;
padding: 3px;
border: 1px solid #000;
font-size: 14px;
display:none;
-moz-transition: opacity 1s linear;
-o-transition: opacity 1s linear;
-webkit-transition: opacity 1s linear;
}
#progress_bar.loading {
display:block;
}
#progress_bar .percent {
background-color: #99ccff;
height: auto;
width: 0;
}​

Resources