CSS animation, play and then reverse animation on hover - html

I have multiple divs zero width on page load, they are then extended (just after page load) by a keyframe transition like so (for example). Each of these divs has a different final width.
#keyframes growN {
from {width: 0px;}
to {width: 21vw;}
}
I would like to add a second animation that extends the div further (to a fixed value) on hover, and sets it back to its original (post page load animation) width on de-hover (un-hover?). Something like this:
#keyframes hover_grow {
from {width: element.width;}
to {width: 50vw;}
}
Since there are many divs, I'd rather not do the maths myself (separate animation for each div, with its own width in place of element.width).
I have tried the following:
bar:hover {
-webkit-animation-name: hover_grow;
-webkit-animation-duration: 0.1s;
-webkit-animation-timing-function: ease-out;
-webkit-animation-direction: alternate;
animation-name: grow;
animation-duration: 1s;
animation-timing-function: ease-out;
animation-direction: alternate;
}
#-webkit-keyframes hover_grow {
from {width: initial;}
to {width: 25vw;}
}
#keyframes hover_grow {
from {width: initial;}
to {width: 25vw;}
}
This works on hover - the div extends further, but on de-hover, it returns it to its page load, pre animation value (i.e. 0), and its page load animation triggers again. Also, the timing seems to be ignored.
JSFiddle: https://jsfiddle.net/an1o4brL/3/

one way to work this around is to use a wrapper, animate the initial appearance then grow and shrink the wrapper on hover, the child will follow its parent's width,
other wise use js
#bar4 {
height: 30px;
transition: width .5s linear;
display: block;
animation-name: grow4;
animation-duration: .5s;
animation-timing-function: ease-out;
animation-iteration-count: 1;
background-color: white;
border: 2px solid #5e0734;
margin-top: 0.15vh;
margin-bottom: 0.15vh;
margin-left: 0.5vh;
overflow: hidden;
}
#keyframes grow4 {
from {
width: 0;
}
to {
width: 100%;
}
}
#bar4Wrap {
width: 21vw;
transition: width .5s linear;
}
#bar4Wrap:hover {
width: 100%;
}
<div id="bar4Wrap">
Link
</div>

Related

CSS background-color pulse animation for unknow background color

I have a list of divs with a background color determined by a knockout.js observable. The background color of the first div should pulse slightly to make clear, that this is the active element. I created a pulse animation with css and keyframes, but this seems to only work with a fixed color known at "compile time". Can I somehow make that more dynamic? I already tried to use the inherit keyword, but that doesn't work
<div class="cch-current-storage" data-bind="style: { 'background-color': storageType.color }">Bla</div>
<div data-bind="style: { 'background-color': storageType.color }">Next</div>
<style>
.cch-current-storage {
animation-name: color;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction:alternate-reverse;
animation-timing-function:ease
}
##keyframes color {
from {background-color: red;}
to {background-color: inherit;}
}
</style>
First of all there is a typo... css-current-storage vs .ccs-current-storage
I made fiddle you can look here (https://jsfiddle.net/z9modqt4/)
css
div{
width: 100px;
height: 100px;
}
.css-current-storage {
animation-name: color;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate-reverse;
animation-timing-function: ease;
}
#keyframes color {
to {
background-color: blue;
}
}
html
<div class="css-current-storage" style='background-color: yellow' >Bla</div>
it seems to work if I left empty space in from (delete from completly)
Its counter intuitive because that way it works from to to from. So it works in other direction (because of animation-direction: alternate-reverse like Temani said in comment)

Setting a keyframe value as an offset?

Let's say I have a div with a specified height of 100px and I want to animate it so it grows by a fixed 20px height.
The snippet below shows how I implemented it, successfully.
#keyframes foo {
0% {
height: 100px;
}
50% {
height: 120px;
}
100% {
height: 100px;
}
}
#foo1 {
background-color:blue;
width:100px;
height:100px;
animation-name: foo;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in-out;
}
<div id='foo1'>
But what if I need to set the height property outside the CSS, so that it's not a specific value of 100px and it can be changed to any other value, but still, I want to animate an increasing height of a fixed 20px ?
Is there a way to set the animaton value as an offset of the original element value?
Increase the padding if you will not have any content and it's a simple visual animation:
#keyframes foo {
0%,100% {
padding-bottom: 0px;
}
50% {
padding-bottom: 20px;
}
}
#foo1 {
background-color:blue;
width:100px;
height:100px;
animation-name: foo;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in-out;
}
<div id='foo1'>
Or use CSS variables:
#keyframes foo {
0%,100% {
height:var(--h,100px)
}
50% {
height:calc(var(--h,100px) + 20px);
}
}
#foo1 {
background-color:blue;
width:100px;
height:var(--h,100px);
display:inline-block;
animation-name: foo;
animation-duration: 1.4s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in-out;
}
<div id='foo1'></div>
<div id='foo1' style="--h:50px;"></div>
I don't think there is a direct way, but you have several workarounds:
use padding (e.g. padding-bottom) to extend the element's height – only applicable if the element is not supposed to have text content flowing into the padding
use border – same as above
use an extra element, e.g. ::after
use JavaScript – if you are already setting the height "outside" of CSS, it may be that you are setting it with JS?

CSS3 Transition [Pause and Different Speeds]

I wish to create a simple animation.
First Step: I wish to animate my div from 0% to 100% with 1s speed.
Second Step: I wish to create a pause of 2s.
Final Step: I wish to animate my div from left to right with 0.5s speed.
.effect {
-webkit-animation:.effect 1s ease both;
animation:effect 1s ease both;
background-color:#1c1f26;
display:block;
height:100%;
left:0;
overflow:hidden;
position:absolute;
top:0;
width:100%;
}
#-webkit-keyframes effect {
0% {
-webkit-animation-timing-function:ease-in;
width:0%;
}
100% {
-webkit-animation-timing-function:ease-out;
width:100%;
}
}
<div class="effect"></div>
For the first step it's done. ( You can see with my code to the top.)
But I can't create a pause and play with different speeds for the next steps.
Thanks for your help.
You can chain your animations.
.effect {
animation: animation-1 1s ease,animation-2 2s ease 1s,animation-3 0.5s ease 3s;
background-color:#1c1f26;
display:block;
height:100%;
left:0;
overflow:hidden;
position:absolute;
top:0;
width:0%;
}
#keyframes animation-1 {
from {width: 0%;}
to {width: 100%;}
}
#keyframes animation-2 {
from {width: 100%;}
to {width: 100%;}
}
#keyframes animation-3 {
from {width: 100%; left:0;}
to {width: 0%; left: 100%}
}
<div class="effect"></div>
This way, first it plays the animation-1, then the 2nd and then the 3rd.
I don't say it's the best way, but it does the job in this case.
You can also convert your timing 1s, 2s, 0.5s in percentage and do the keyframes according to this percentage. This way, you would have one animation only.
In short, you don't play it at different speeds. Instead, you just set things at appropriate percentages and do a little math to figure out where things should go.
You have three steps:
Step 1: 1s
Step 2: 2s
Step 3: .5s
You have 3.5s of total animation, so that should be your duration.
Step 1, percentage-wise, goes from 0% to (1s / 3.5s) * 100%, or about 28.6%.
Step 2, percentage-wise, takes 57.2%, so it goes from 28.6% to 85.7%.
Finally, Step 3 goes from 85.7% to 100%.
For the pause, you just have both its start and stop keep the same value. Nothing will move for that duration of time, so it's essentially paused.
.effect {
-webkit-animation: effect 3.5s ease both;
animation: effect 3.5s ease both;
background-color: #1c1f26;
display: block;
height: 100%;
left: 0;
overflow: hidden;
position: absolute;
top: 0;
width: 100%;
}
#-webkit-keyframes effect {
0% {
-webkit-animation-timing-function:ease-in;
width: 0%;
}
28.6% {
width: 100%;
}
85.7% {
width: 100%;
margin-left: 0;
}
100% {
margin-left: 100%;
width: 0;
}
}
<div class="effect"></div>

is there a way to set caret height in contenteditable div in html

I need to deal with language like Myanmar, its characters are very much larger compare to other language like English. since then its line-height calculated by browser is even more large, that parts of the caret is out of the div border.
So I need a way to cause the caret to hold to its height unchanged from language to language. like you have Myanmar and English in same line, and the caret will hold on to 50px while moving from the left to the right. Or you can say that I'm trying to find a way to disable the browser's default behavior of calculating the height of the caret.
by the way, this only deal with opera presto, it's well performed on chrome or webkit.
I do not think I get the final perfect solution, but it's really a way to solve this problem somehow.
I use a child div with a blinking animation to simulate the browser's caret, and make the father div a pure div. here is the css code.
Here is the Github project which I think help me a lot.
https://gist.github.com/navinpai/2902229
.cursor {
width: 1px;
height: 80px;
display: block;
position: relative;
margin-left: 30px;
animation-name: see_likes;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: running;
animation-delay: 0s;
-o-animation-name: see_likes;
-o-animation-duration: 1s;
-o-animation-iteration-count: infinite;
-o-animation-timing-function: linear;
-o-animation-play-state: running;
-o-animation-delay: 0s;
}
#keyframes see_likes {
0% { background: #0a0 }
47% { background: #090 }
50% { background: transparent }
97% { background: transparent }
100% { background: #090 }
}
#-o-keyframes see_likes {
0% { background: #0a0 }
47% { background: #090 }
50% { background: transparent }
97% { background: transparent }
100% { background: #090 }
}

Set two webkit-animations to be same speed with one travelling a longer distance?

[Edit: Solution was to create two containers, with the second animation container set to left: 100%.]
I have a very basic animation to move a large gif across the page, the gif is 1536px wide.
The page can be infinitely wide and thus the animation starts at right:0px and ends at right:100%. In reality, I don't expect the page to ever be larger than the highest monitor resolutions used currently.
In order to create the feeling that the animation was occurring infinitely I have created a second animation and started this at right:-1536px and ending at right:100%.
Unfortunately, as this second animation is covering a greater distance it is moving faster than the first and my attempted seamless animation doesn't work. Is there a way to specify that animation-duration work at a constant 1px per second or something equivalent instead of a duration? I don't believe I can increase the duration to match as the browser could be any size.
Any help or ideas appreciated!
My code is as follows:
#-webkit-keyframes frontrocks-anim2 {
0%{right:-1536px;}
100%{right:100%;}
}
#-moz-keyframes frontrocks-anim2 {
0%{right:-1536px;}
100%{right:100%;}
}
.frontrocks-anim2 {
-webkit-animation:frontrocks-anim2 30s infinite;
-webkit-animation-timing-function:linear;
-webkit-animation-delay: 0s;
-moz-animation:frontrocks-anim2 30s infinite;
-moz-animation-timing-function:linear;
-moz-animation-delay: 0s;
}
UPDATE
A better solution is to adapt Oriol's comment from https://stackoverflow.com/a/21088405/603369
That provides a smoothly scrolling background, so all that is left is to animate the background element to "fly in" upon page load.
The problem is that the initial "fly-in" must be based on the width of the container (e.g., the page), while the repeating background must be based on the width of the background image. That leads to some oddities in timing, where the initial "fly-in" from the right side may be significantly faster or slower than the background animation. You might be able to adapt this solution further by using JavaScript to adjust the timing based on the width of the page, but this should give you a starting point.
header {
position: relative;
overflow-x: hidden;
width: 100%;
height: 52px;
border: 1px solid #ccc;
}
.bg {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: -1536px;
background: url(https://placehold.it/1536x50/cceecc) 0% 0% repeat;
z-index: -1;
-webkit-animation-name: slide-in, bg-anim-repeat;
-webkit-animation-duration: 5s, 5s;
-webkit-animation-timing-function: linear, linear;
-webkit-animation-iteration-count: 1, infinite;
-webkit-animation-delay: 0s, 5s;
}
#-webkit-keyframes bg-anim-repeat {
0% {-webkit-transform: translateX(0);}
100% {-webkit-transform: translateX(-1536px);}
}
#-webkit-keyframes slide-in {
0% {left: 100%;}
100% {left: 0;}
}
<header>
<div class="bg"></div>
</header>
Original
If the page is larger than 1536x2, you're going to have an odd visual look as the two gifs march across the screen. But if this is what you want to go with, try delaying the beginning of the second animation until halfway through the first animation.
Demo of the second option is below
header {
position: relative;
overflow-x: hidden;
width: 100%;
height: 52px;
border: 1px solid #ccc;
}
header img {
position: absolute;
left: 100%;
}
#-webkit-keyframes frontrocks-anim {
0%{left:100%;}
100%{left:-1536px;}
}
#image1, #image2 {
-webkit-animation:frontrocks-anim 10s infinite;
-webkit-animation-timing-function:linear;
-webkit-animation-delay: 0s;
-moz-animation:frontrocks-anim 10s infinite;
-moz-animation-timing-function:linear;
-moz-animation-delay: 0s;
}
/* Delay is 1/2 of the total animation time */
#image2 {
-moz-animation-delay: 5s;
-webkit-animation-delay: 5s;
}
<header>
<img src="https://placehold.it/1536x50/cceecc" alt="moving image 1" id="image1">
<img src="https://placehold.it/1536x50/eecccc" alt="moving image 1" id="image2">
</header>