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>
Related
I want my image to start with top:0 and ends with bottom:0 with smooth animation. I am struggling to find out the solution.
To be very clear i cannot use background images for SEO purpose. JS solutions are also welcome.
.element {
height: 200px;
width: 400px;
background-color: red;
position: relative;
margin: auto;
overflow: hidden;
}
.element img {
animation: nudge 5s linear infinite alternate;
position: absolute;
top: 0;
left: 0;
}
#keyframes nudge {
0%, 100% {
top: 0;
bottom: auto;
}
50% {
bottom: 0%;
top: auto;
}
}
<div class="element">
<img src="https://www.neelnetworks.com/wp-content/uploads/2018/08/ecommerce-bg.png" alt=""></div>
Instead of trying to animate on top and bottom, you can animate on translateY and move it down with top so it doesnt go off screen
.element {
height: 200px;
width: 400px;
background-color: red;
position: relative;
margin: auto;
overflow: hidden;
}
.element img {
animation: nudge 2s linear infinite alternate;
position: absolute;
top: 0;
transform: translateY(0);
}
#keyframes nudge {
100% {
transform: translateY(-100%);
top: 100%;
}
}
<div class="element"><img src="https://www.neelnetworks.com/wp-content/uploads/2018/08/ecommerce-bg.png" alt=""></div>
#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 have a problem with CSS currently.
https://jsfiddle.net/k9cfdofv/1/
There you can see that the
stripe (parallelogram) comes from the bottom, but it goes a little bit to right before it goes in that state I want it.
So I want it come from the bottom and go to the top without this shift at the end.
CSS-Code:
.stripe {
width: 100px;
height: 100px;
margin-left: 100px;
background: red;
transform: skew(-10deg);
animation: ani 1s linear 1 forwards;
position: absolute;
bottom: 10px;
}
#keyframes ani {
0% {
height: 0px;
}
100% {
height: 700px;
}
}
It can be done by setting a transform-origin for element to be skewed to left bottom.
div {
width: 100px;
height: 100px;
margin-left: 100px;
background: red;
transform: skew(-10deg);
transform-origin: left bottom;
animation: ani 1s linear 10 forwards;
position: absolute;
bottom: 10px;
}
#keyframes ani {
0% {
height: 0px;
}
100% {
height: 700px;
}
}
<div>
</div>
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;
}
}
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"/>