I am trying to make a CSS animation (i can't use javascript) with these steps:
Have a div of which you can't know in advance its position or size (in the fiddle i have set the size for testing)
The div gets resized (width 100% height 50 pixels) and moves to the top of the page while its content disappears
The div turns into a circle and moves to the center of the page
This is what i have attempted so far:
https://jsfiddle.net/v3bt1mar/5/
.turning {
width: 80%;
height: 120px;
background-color: #00FF00;
}
.turning:active {
background: red;
animation: 10.5s;
display: block !important;
position: fixed;
content: "";
overflow: hidden;
animation: resizeList 10.5s forwards;
}
.turning:active * {
animation: fadeContent 1s forwards;
}
#keyframes fadeContent {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 0;
}
}
#keyframes resizeList {
25% {
width: 100%;
height: 50px;
top: 10px;
left: 0%;
// transform: translate(0%, 0%) rotateY(0deg);
border-radius: 0%;
}
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: calc(50% - 50px)";
// transform: translate(~"calc(50vw - 50px)", ~"calc(50vh - 50px)") rotateY(180deg);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
}
But it's still far from what i am expecting.
On Mozilla it doesn't move vertically, on Chrome it does move but not smoothly (just at every keyframe, apparently)
Then i don't know why it moves back to the left rather than to the center of the page
On top of that it works differently on Mozilla and Chrome (on Mozilla it doesn't move to the top, on Chrome it does but not smoothly)
If you add position:absolute; to .turning and remove the rotate transformation in the keyframe, the animation does what you are describing: https://jsfiddle.net/v3bt1mar/7/
Change:
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: calc(50% - 50px)";
// transform: translate(~"calc(50vw - 50px)", ~"calc(50vh - 50px)") rotateY(180deg);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
To:
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: 50%;
// transform: translate(~"calc(50vw - 50px)", ~"calc(50vh - 50px)") rotateY(180deg);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
This will keep image at center. Also try adding keyframes for 50% and 75% transition. That should smooth out the transition a bit.
The actual issue was that it was copied from a less file and it contained single line comments which are not allowed into normal CSS. On top of that i had left calc as a string so that LESS won't sum the values while parsing
With a few adjustments taken from the other answers i managed to fix the animation the way i wanted (the rotate was intended, i just didn't think it was worth mentioning)
https://jsfiddle.net/v3bt1mar/12/
.turning {
width: 80%;
height: 120px;
background-color: #00FF00;
}
.turning:active {
background: red;
display: block !important;
position:fixed;
overflow: hidden;
animation: resizeList 1s forwards;
top:calc(50% - 50px);
left: 0;
}
.turning:active * {
animation: fadeContent 1s forwards;
}
#keyframes fadeContent {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 0;
}
}
#keyframes resizeList {
25% {
width: 100%;
height: 50px;
top: 10px;
left: 0%;
border-radius: 0%;
transform: rotateY(0deg);
}
100% {
border-radius: 50%;
top: calc(50% - 50px);
left: calc(50% - 50px);
transform: rotateY(180deg);
width: 100px;
height: 100px;
}
}
Related
#keyframes scale {
0% {
transform: scale(0);
}
100% {
transform: scale(5);
}
}
div#scale {
width: 10px;
height: 10px;
border: 1px solid;
border-radius: 50%;
animation: scale 5s infinite;
}
<div id="scale"></div>
How to scale (transform) div in width and height without scaling border width? I'm trying to build this effect.
As for the workaround / alternative you can just animate its width and height:
body {padding:50px}
#scale {
border: 1px solid;
border-radius: 50%;
animation: scale 3s linear infinite;
position: relative;
top: 0;
left: 0;
}
#keyframes scale {
0% {
width: 0;
height: 0;
}
100% {
width: 50px;
height: 50px;
top: -25px;
left: -25px;
}
}
<div id="scale"></div>
To make it grow from the center use negative margins / values for the top and left properties equal to half of the change in size, so in this case that's -25px.
One option you have is to use synced elements. One that scales and another one, empty, that changes size while keeping border-width. The other element I used is the ::after of a wrapper.
#keyframes scale-div {
0% {
transform: scale(0);
}
50% {
transform: scale(1)
}
100% {
transform: scale(0);
}
}
#keyframes scale-border {
0% {
width: 0px;
height: 0px;
}
50% {
width: 100px;
height: 100px;
}
100% {
width: 0px;
height: 0px;
}
}
.scale {
animation: scale-div 5s steps(300, end) infinite ;
transition-timing-function: cubic-bezier(.4,0,.2,1);
background-color: rgba(0,0,0,.05);
border-radius: 50%;
}
.scale,.scale-wrapper {
width: 100px;
height: 100px;
}
.scale-wrapper {
position: relative;
}
.scale-wrapper::after {
position: absolute;
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
border: 1px solid black;
width: 98px;
height: 98px;
animation: scale-border 5s steps(300, end) infinite;
transition-timing-function: cubic-bezier(.4,0,.2,1);
content: '';
}
<div class="scale-wrapper">
<div class="scale"></div>
</div>
There are ton of problems with scaling transforms since it's ratio based. if you scale it, it's going to scale its layout, border even :after, :before elements and all children.
For what you're trying to do it's best if you just use svg. Svg circle element's radius property can be animated. I suggest you run browser support test on it; However, svg support is pretty wide especially with animations.
svg .circle {
cx: 50%;
cy: 50%;
r: 20px;
stroke: #dfdfdf;
stroke-width: 2px;
transform: translateZ(0);
fill: none;
animation: ping 2s infinite;
}
#keyframes ping {
from {
r: 10px;
}
to {
r: 40px;
}
}
<svg><circle r="20px" class="circle"/></svg>
#keyframes scale {
0% {
transform: scale(0); border: 1px solid;
}
100% {
transform: scale(5); border: 5px solid;
}
}
div#scale {
width: 10px;
height: 10px;
border-radius: 50%;
animation: scale 5s infinite;
}
did you try above code ?
I want to create a full CSS animated progress bar, using steps() to go through the end.
#keyframes loading {
0% {
width: 0%;
left: 50%;
}
100% {
width: 100%;
left: 0%;
}
}
div {
position: absolute;
top: 50%;
left: 50%;
width: 0%;
height: 1px;
background-color: #000;
-webkit-animation: loading 15s steps(15, end);
animation: loading 15s steps(15, end);
transition: all 0.5s ease-out;
}
My main objective is to keep the steps() and add a transition effect to smooth it.
How could I achieve that without JS ?
I think this is what you are after.
I've simplified this to 5 positions...the math for 15 stages is pretty simple though.
#keyframes loading {
0% {
width: 0%;
}
25% {
width: 25%;
}
50% {
width: 50%;
}
75% {
width: 75%;
}
100% {
width: 100%;
}
}
div {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%);
width: 0%;
height: 10px;
background-color: #000;
animation: loading 5s infinite;
}
<div></div>
I have a circle that expands using CSS keyframes, with fixed positioning. The trouble is, as the circle changes size, the centre of the circle moves (whilst the top left corner remains fixed). How do I ensure the centre is fixed during the animation? Is there a way to specify the "origin" of the div so that's it's not the top left?
<div id="circle"></div>
and
#circle {
position: fixed;
background: #07F;
border-radius: 50%;
animation: expand linear 3s infinite;
top: 10px;
left: 10px;
}
#keyframes expand {
0% {
width: 100px;
height: 100px;
}
100% {
width: 500px;
height: 500px;
}
}
See this JSFiddle
Another option, what you can do is use transform - scale property to increase dimensions and then transform-origin to keep it centered:
#circle {
position: fixed;
background: #07F;
border-radius: 50%;
animation: expand linear 3s infinite alternate;
top: 10px;
left: 10px;
transform-origin: center;
width: 100px;
height: 100px;
}
#keyframes expand {
0% {
transform: scale(1);
}
100% {
transform: scale(5);
}
}
<div id="circle"></div>
try this:
#circle {
position: fixed;
background: #07F;
border-radius: 50%;
animation: expand linear 3s infinite alternate;
top: calc(10px + 50px); /* 10px + (half of the initial height) */
left: calc(10px + 50px); /* 10px + (half of the initial width) */
transform: translate(-50%, -50%)
}
#keyframes expand {
0% {
width: 100px;
height: 100px;
}
100% {
width: 500px;
height: 500px;
}
}
<div id="circle"></div>
I am trying to build a simple CSS3 animation, a pulsing square inside a bigger square (centered).
It seems to work fine except on IE, at the end of the animation the inner square move to up-left of his parent.
I didn't find a solution, help me please. What am I doing wrong?
#foo{
position: relative;
display: table;
margin: auto;
width: 100px;
height: 100px;
top: 50px;
background: #ccf;
}
#foo::before{
content:"";
position: absolute;
display: inline-block;
width: 50%;
height: 50%;
left: 50%;
top: 50%;
background: #55a;
animation: 1s ease-in-out infinite pulse;
}
#keyframes pulse {
0% { transform: translate(-50%, -50%) scale(.2,.2); }
50% { transform: translate(-50%, -50%) scale(.8,.8); }
100% { transform: translate(-50%, -50%) scale(.2,.2); }
}
Here a JsFiddle of the code
How strange. It looks like IE and Edge are having some issue resetting the transforms on subsequent loops.
Although I couldn't find a direct solution to the browser's rendering problem (likely a bug), your sample looks like a great place to use the absolute centering trick. By not having the extra translate to center it, it works in IE, and is a bit simpler.
Working Example (jsFiddle):
#foo{
position: relative;
display: table;
margin: auto;
width: 100px;
height: 100px;
top: 50px;
background: #ccf;
}
#foo::before{
content:"";
position: absolute;
display: inline-block;
width: 50%;
height: 50%;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
background: #55a;
animation: 1s ease-in-out infinite pulse;
}
#keyframes pulse {
0% {transform: scale(.2,.2); }
50% {transform: scale(.8,.8); }
100% {transform: scale(.2,.2); }
}
<i id="foo"/>
I'm trying out a CSS3 animation on a background image. Everything's working well, the problem is that on Chrome the text ends up being blurred when the animation is in progress:
During Animation:
Turning off the animation:
As you can see the text rendering is fine when the animation is turned off, I know there's the usual issue with text rendering but I can't understand why the rendering is poor on Chrome when the animation is in progress. I'm not sure there's anything I can do about it really. I've tested the animation on Firefox and IE and it's ok. By the way I'm working on Windows.
Firefox:
IE:
EDIT
.bg-div {
position: fixed;
width: 110%;
height: 110%;
transform: translate(-5%, -5%);
-moz-transform: translate(-5%, -5%) rotate(0.02deg); /* rotation to solve choppy animation on Firefox */
-ms-transform: translate(-5%, -5%);
background-image: url('images/colour-test.jpg');
background-size: cover;
-webkit-animation: bg-animation 10s linear infinite;
-moz-animation: bg-animation 10s linear infinite;
-ms-animation: bg-animation 10s linear infinite;
}
#-webkit-keyframes bg-animation {
25% { transform: translate(-5.5%, -5.5%); }
50% { transform: translate(-5.3%, -4.9%); }
75% { transform: translate(-4.8%, -4.3%); }
}
#-moz-keyframes bg-animation {
25% { -moz-transform: translate(-5.5%, -5.5%) rotate(0.02deg); }
50% { -moz-transform: translate(-5.3%, -4.9%) rotate(0.02deg); }
75% { -moz-transform: translate(-4.8%, -4.3%) rotate(0.02deg); }
}
#-ms-keyframes bg-animation {
25% { -ms-transform: translate(-5.5%, -5.5%); }
50% { -ms-transform: translate(-5.3%, -4.9%); }
75% { -ms-transform: translate(-4.8%, -4.3%); }
}
.content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
height: 65%;
text-align: center;
}
After reading the question and answer posted in the comments I've tried to adding -webkit-font-smoothing: subpixel-antialiased; to .bg-div but that didn't make any difference.
EDIT 2
Okay so this is a bit of a weird one, during the animation apparently the position: fixed is making the text blurry. I don't know how that is possible, anyway once I removed the position: fixed and the background was animating the text was displayed correctly. It's still not what I want because I need the background to be fixed.
In my testing, the problem is fixed if the transform is not used on .content. Luckily, you don't need to use transform to position your content div.
Use this margin: auto trick to position instead
Using this method, you do not need to use transform: translate(-50%, -50%)
The content is centered with the combination of top, right, bottom, left, margin: auto and the percentage width and height.
.content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: 50%;
height: 65%;
text-align: center;
}
Working Example
body { margin: 0 auto; width: 500px }
.bg-div {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
width: 800px;
height: 800px;
transform: translate(-5%, -5%);
background: url('http://www.placehold.it/800') no-repeat;
-webkit-animation: bg-animation 2s linear infinite;
animation: bg-animation 2s linear infinite;
}
#-webkit-keyframes bg-animation {
0% {
transform: translate(-5.5%, -5.5%);
}
50% {
transform: translate(-5%, -5%);
}
100% {
transform: translate(-5.5%, -5.5%);
}
}
#keyframes bg-animation {
0% {
transform: translate(-5.5%, -5.5%);
}
50% {
transform: translate(-5%, -5%);
}
100% {
transform: translate(-5.5%, -5.5%);
}
}
.content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: 50%;
height: 65%;
text-align: center;
}
<div class="bg-div"></div>
<div class="content">
<h1>This looks better</h1>
<input value="Text" />
</div>