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?
Related
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)
I built a preloading screen for a website with a loading bar that is animated with CSS #keyframes. Works fine on Chrome and Firefox, but on macOS Safari it gets very discrete. Here is a video demo of how it looks on Safari: https://www.youtube.com/watch?v=ODV5lN2xZSI&feature=youtu.be
As you can see, loading bar background (gray line) and the bar itself (black line) twitch instead of going smoothly from 0% width to 100%. What could be a problem, is this known bug of Safari? Latest macOS and Safari.
#keyframes loading-wrapper-anim {
0% {
width:0%;
}
100% {
width:100%;
}
}
.preloader .loading_wrapper {
position:absolute;
width:0%;
height:1px;
background:#dbdbdb;
top:12rem;
animation: loading-wrapper-anim 1s;
animation-delay: 1s;
animation-fill-mode: forwards;
align-self:flex-start; /*this one is because of the parent element*/
}
.preloader .loading_wrapper .loading_bar {
height:100%;
width:0%;
height:100%;
background:#000;
animation: loading-wrapper-anim 3s;
animation-delay: 2s;
animation-fill-mode: forwards;
}
<div class="preloader">
<div class="loading_wrapper">
<div class="loading_bar">
</div>
</div>
</div>
Smooth animation is expected.
Thank you.
You can attempt to force the hardware acceleration by adding a translateZ on the animation.
.preloader .loading_wrapper {
position:absolute;
width:0%;
height:1px;
background:#dbdbdb;
top:12rem;
animation: loading-wrapper-anim 1s;
animation-delay: 1s;
animation-fill-mode: forwards;
align-self:flex-start;
/* Add this */
-webkit-transform: translateZ(0);
}
JSFiddle
Alternatively, you can look into using the will-change method as a last resort for smoother animations.
https://developer.mozilla.org/en-US/docs/Web/CSS/will-change
The way I fixed it is instead of trying to manipulate width of an element (which causes redrawing each time the width changes), did the following:
#keyframes loading-wrapper-anim {
0% {
transform:scaleX(0);
}
100% {
transform:scaleX(1);
}
}
.preloader .loading_wrapper {
position:absolute;
width:100%;
height:1px;
background:#dbdbdb;
top:12rem;
animation: loading-wrapper-anim 1s;
animation-delay: 1s;
animation-fill-mode: forwards;
align-self:flex-start; /*this one is because of the parent element*/
transform:scaleX(0);
transform-origin:0% 0%;
}
.preloader .loading_wrapper .loading_bar {
height:100%;
width:100%;
height:100%;
background:#000;
animation: loading-wrapper-anim 3s;
animation-delay: 2s;
animation-fill-mode: forwards;
transform:scaleX(0);
transform-origin:0% 0%;
}
I used transform:scaleX() in conjunction with transform-origin:0% 0% (this one sets center of transformation to the top left corner) to emulate width change without actually changing it.
Conclusion: use transform where/when possible. They are more efficient in terms of CSS animations and transitions.
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>
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 }
}
When I insert an image into my HTML it gets positioned in the lower left corner for some reason. Even if I set position to center; it stays in that strange position. What could be causing this?
My code:
<!DOCTYPE HTML>
<html>
<header>
<title>Animation Verkefni</title>
<link type="text/css" href="stylesheet2.css" rel="stylesheet"/>
</header>
<body>
<div class="doge1">
<p>
Transitions in CSS are applied to an element and specify that when a property changes it should do so gradually over a period of time. Animations are different. When applied, they just run and do their thing. They offer more fine-grained control as you can control different stops of the animations.
</p>
</div>
<div class="doge2">
<img src="spengbab.jpg">
</div>
</body>
</html>
css:
body {
background-color:gray;
}
p {
font-size:50px;
margin-left:500px;
margin-right:500px;
text-align:center;
margin-top:250px;
font-family:impact;
}
#keyframes myfirst
{
0% {opacity:1;}
25% {opacity:2;}
50% {opacity:3;}
75% {opacity:4;}
100% {opacity:10;}
}
#-webkit-keyframes myfirst /* Safari og Chrome */
{
0% {opacity:1;}
25% {opacity:2;}
50% {opacity:3;}
75% {opacity:4;}
100% {opacity:10;}
}
.doge2 {
position:fixed center;
top:20px;
}
.doge1:hover
{
animation-name: myfirst;
animation-duration: 5s;
animation-timing-function: linear;
animation-delay: 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-play-state: running;
/* Safari og Chrome: */
-webkit-animation-name: myfirst;
-webkit-animation-duration: 5s;
-webkit-animation-timing-function: linear;
-webkit-animation-delay: 1s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-direction: alternate;
-webkit-animation-play-state: running;
}
Thanks!
Try using position:fixed; & text-align:center;
Like this:
.doge2 {
position:fixed;
top:20px;
width:100%;
text-align:center;
}
Try with
vertical-align:middle;
to keep image at center position.