Is it possible to use CSS transitions to animate something between a position set as left: 0px to right: 0px so it goes all the way across the screen? I need to accomplish the same thing with top to bottom. Am I stuck calculating the screen width / object-size?
#nav {
position: absolute;
top: 0px;
left: 0px;
width: 50px;
height: 50px;
-webkit-transition: all 0.5s ease-out;
}
.moveto {
top: 0px;
right: 0px;
}
and then I use jQuery's .addClass
You can animate the position (top, bottom, left, right) and then subtract the element's width or height through a CSS transformation.
Consider:
$('.animate').on('click', function(){
$(this).toggleClass("move");
})
.animate {
height: 100px;
width: 100px;
background-color: #c00;
transition: all 1s ease;
position: absolute;
cursor: pointer;
font: 13px/100px sans-serif;
color: white;
text-align: center;
}
/* ↓ just to position things */
.animate.left { left: 0; top: 50%; margin-top: -100px;}
.animate.right { right: 0; top: 50%; }
.animate.top { top: 0; left: 50%; }
.animate.bottom { bottom: 0; left: 50%; margin-left: -100px;}
.animate.left.move {
left: 100%;
transform: translate(-100%, 0);
}
.animate.right.move {
right: 100%;
transform: translate(100%, 0);
}
.animate.top.move {
top: 100%;
transform: translate(0, -100%);
}
.animate.bottom.move {
bottom: 100%;
transform: translate(0, 100%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Click to animate
<div class="animate left">left</div>
<div class="animate top">top</div>
<div class="animate bottom">bottom</div>
<div class="animate right">right</div>
And then animate depending on the position...
For elements with dynamic width it's possible to use transform: translateX(-100%); to counter the horizontal percentage value. This leads to two possible solutions:
1. Option: moving the element in the entire viewport:
Transition from:
transform: translateX(0);
to
transform: translateX(calc(100vw - 100%));
#viewportPendulum {
position: fixed;
left: 0;
top: 0;
animation: 2s ease-in-out infinite alternate swingViewport;
/* just for styling purposes */
background: #c70039;
padding: 1rem;
color: #fff;
font-family: sans-serif;
}
#keyframes swingViewport {
from {
transform: translateX(0);
}
to {
transform: translateX(calc(100vw - 100%));
}
}
<div id="viewportPendulum">Viewport</div>
2. Option: moving the element in the parent container:
Transition from:
transform: translateX(0);
left: 0;
to
left: 100%;
transform: translateX(-100%);
#parentPendulum {
position: relative;
display: inline-block;
animation: 2s ease-in-out infinite alternate swingParent;
/* just for styling purposes */
background: #c70039;
padding: 1rem;
color: #fff;
font-family: sans-serif;
}
#keyframes swingParent {
from {
transform: translateX(0);
left: 0;
}
to {
left: 100%;
transform: translateX(-100%);
}
}
.wrapper {
padding: 2rem 0;
margin: 2rem 15%;
background: #eee;
}
<div class="wrapper">
<div id="parentPendulum">Parent</div>
</div>
Demo on Codepen
Note: This approach can easily be extended to work for vertical positioning. Visit example here.
This worked for me on Chromium. The % for translate is in reference to the size of the bounding box of the element it is applied to so it perfectly gets the element to the lower right edge while not having to switch which property is used to specify it's location.
topleft {
top: 0%;
left: 0%;
}
bottomright {
top: 100%;
left: 100%;
-webkit-transform: translate(-100%,-100%);
}
In more modern browsers (including IE 10+) you can now use calc():
.moveto {
top: 0px;
left: calc(100% - 50px);
}
Related
Please help, when I'm trying to play animation with moving ball in position X and Y at the same time it doesn't work, some strange behaviour. I would like to look like a batted and falling ball
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball-x 2s, fly-ball-y 2s;
}
#keyframes fly-ball-x {
100% {
transform: translateX(300px);
}
}
#keyframes fly-ball-y {
100% {
transform: translateY(100px);
}
}
<div class="ball"></div>
**The result I'm expecting is like the code below:**
#keyframes fly-ball-x {
100% {
left: 300px;
}
}
#keyframes fly-ball-y {
100% {
bottom: 0;
}
}
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball-x 2s cubic-bezier(0.17, 0.67, 0.6, 1), fly-
ball-y 2s;
}
<div class="ball"></div>
.ball {
position: absolute;
left: 18%;
bottom: 100px;
width: 40px;
height: 40px;
background-color: cadetblue;
border-radius: 50%;
animation: fly-ball 2s
}
#keyframes fly-ball {
100% {
transform: translateX(300px) translateY(100px);
}
}
<div class="ball"></div>
It is because you weren't running the animations concurrently. Here both translations are just being run at the same time. You just had a bit more than you needed.
EDIT
Check out this blog post. It gives explanations on the kinds of curves it seems you are going for Curved Path Animations In CSS
I'm trying to fill this nos bottle then slowly empty it up with css so first the "fill" goes up then slowly slowly drains down, I tried but came with a very terrible result
#bottle, #fill {
position: fixed;
top: 50%;
left: 50%;
}
.box {
width: 96px;
height: 195px;
border-radius: 10px;
text-align: center;
color: #ddd;
font-size: 25px;
font-weight: 600;
position: relative;
overflow: hidden;
top: 50%;
left: 50%;
}
.box:before {
content: "";
position: absolute;
width: 400px;
height: 400px;
background: #00acee;
left: 50%;
transform: translateX(-50%);
border-radius: 40%;
animation: fill 1s cubic-bezier(0, 1.62, 0.27, -0.67) infinite;
z-index: -1;
}
#keyframes fill {
from {
top: 250px;
transform: translateX(-50%) rotate(0deg);
}
to {
top: -50px;
transform: translateX(-50%) rotate(360deg);
}
}
<div class="box">
<img id="bottle" src="https://cdn.discordapp.com/attachments/350561379234873354/813833593084313650/bottle.png" width=100 height=200>
</div>
If anyone could point how can i achieve this would be awesome.
You can try something like that, but you should consider just left backgroung transparent inside bottom image, outside put a solid color, like black.
#bottle, #fill {
top: 50%;
left: 50%;
}
.box {
width: 96px;
height: 195px;
border-radius: 10px;
text-align: center;
color: #ddd;
font-size: 25px;
font-weight: 600;
position: relative;
overflow: hidden;
top: 50%;
left: 50%;
}
.box:before {
content: "";
position: absolute;
width: 400px;
height: 400px;
background: #00acee;
left: 50%;
transform: translateX(-50%);
border-radius: 40%;
animation: fill 7s cubic-bezier(1, 2.7, 1, -1.7) infinite;
z-index: -1;
}
#keyframes fill {
from {
top: 450px;
transform: translateX(-50%) rotate(0deg);
}
to {
top: -50px;
transform: translateX(-50%) rotate(360deg);
}
}
<div class="box">
<img id="bottle" src="https://cdn.discordapp.com/attachments/350561379234873354/813833593084313650/bottle.png" width=100 height=200>
</div>
I'm not absolutely sure what effect you want, but one thing to notice is that you can have the filling and the emptying all in the same animation, without necessarily needing to involve a cubic Bezier function, which in this case seemed to partly fill the bottle, then empty then partly fill but to a different level.
Simplifying things but introducing more detail into the keyframes here's an example of the bottle filling much faster than it empties, by having the percentage of the animation used for filling as much smaller than the emptying.
There are of course many variations on this which can be achieved by having the percentages differ. Also you could reintroduce a cubic Bezier to make the movement less uniform, but that's for your experimentation as I don't know exactly what final effect is wanted.
<head>
<style>
#bottle, #fill {
/* position: fixed; NOTE. had to change this position fixed to absolute get it to line up on Stack Overflow. Outside SO it was fine as fixed */
position: absolute;
top: 50%;
transform: translateY(-50%);
left: calc(50% - 50px);
}
.box {
width: 96px;
height: 195px;
border-radius: 10px;
text-align: center;
color: #ddd;
font-size: 25px;
font-weight: 600;
position: relative;
overflow: hidden;
top: 50%;
left: 50%;
}
.box:before {
content: "";
position: absolute;
width: 400px;
height: 400px;
background: #00acee;
left: 50%;
transform: translateX(-50%);
border-radius: 40%;
/* animation: fill 20s cubic-bezier(0, 1.62, 0.27, -0.67) infinite; */
animation: fill 20s linear infinite;
z-index: -1;
animation-fill-mode: forwards; /* added */
}
#keyframes fill {
0% {
top: 250px;
transform: translateX(-50%) rotate(0deg);
}
10% {
top: -50px;
top: 75px;
transform: translateX(-50%) rotate(360deg);
}
20% {
top: 75px;
transform: translateX(-50%) rotate(0deg);
}
22% {
top: 75px;
transform: translateX(-50%) rotate(0deg);
}
80% {
transform: translateX(-50%) rotate(360deg);
}
100% {
top: 250px;
transform: translateX(-50%) rotate(0deg);
}
}
</style>
</head>
<body>
<div class="box">
<img id="bottle" src="https://cdn.discordapp.com/attachments/350561379234873354/813833593084313650/bottle.png" width=100 height=200>
</div>
</body>
Note: in the SO snippet system the position fixed had the effect of separating the blob (liquid) from the bottle - it was fine when the code was just run as it was outside the SO system. To demo it here I have made the bottle position absolute and centered the bottle and blob, just so you can get an idea while here. You can remove the absolute and go back to fixed outside SO.
I had a question to all the css wizards out there. I came across this CSS animation effect I have not seen before and wondered if anyone knew how it was done? https://www.landr.com/en
Just curious.
Best regards,
Philippe
Use a pseudo element to draw the circle that will radiate out, then use transform: scale() and opacity to cause it to grow and fade out.
using animation
div {
width: 100px;
height: 100px;
cursor: pointer;
position: relative;
}
div::after {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
}
div:hover::after {
animation: radiate .5s;
}
div, div::after {
background: #09c;
border-radius: 50%;
}
#keyframes radiate {
to {
transform: scale(1.5);
opacity: 0;
}
}
<div></div>
Or using transition
div {
width: 100px;
height: 100px;
cursor: pointer;
position: relative;
}
div::after {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
}
div:hover::after {
transform: scale(1.5);
opacity: 0;
transition: transform .5s, opacity .5s;
}
div, div::after {
background: #09c;
border-radius: 50%;
}
<div></div>
I want to do this: -webkit-transform: translateX(300px) but from the right instead of having the origin on left.
I tried -webkit-transform-origin: 100% 100% and even top right and it didn't affect it.
Is there a way to do it?
By the power of CSS:
body {
padding: 0;
margin: 0;
}
#page {
position: absolute;
width: 100%;
height: 100%;
background-color: black;
z-index:2;
right:0;
}
#left_drawer {
background-color: #222222;
position: absolute;
top: 0;
right: 0;
width: 300px;
height: 100%;
z-index: 1;
}
#toggle {
width: 50px;
height: 50px;
background-color: red;
float: right;
}
.open_drawer {
-webkit-animation: open_drawer 300ms ease-in-out;
-webkit-animation-fill-mode: forwards;
-webkit-transform: translateX(0);
}
#-webkit-keyframes open_drawer {
to {
-webkit-transform: translateX(-300px);
}
}
This will make it slide in from the right. Fiddle.
I made a animation and here is the demo.
But the contents won't animate with the div together, any suggestions?
HTML
<div id="fdiv" align="center">
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
<h1>Hello!</h1>
</div>
CSS
#fdiv{
width: 10px;
height: 10px;
position: absolute;
margin-left: -5px;
margin-top: -5px;
left: 50%;
top: 50%;
background-color: red;
}
.go{
-webkit-animation: spinAndZoom 1s 1;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes spinAndZoom {
0% {
width: 10px;
height: 10px;
margin-left: -5px;
margin-top: -5px;
-webkit-transform: rotateZ(0deg);
}
100% {
width: 400px;
height: 400px;
margin-left: -200px;
margin-top: -200px;
-webkit-transform: rotateZ(360deg);
}
}
JS
$(function(){
$("#fdiv").delay(1000).addClass("go");
});
With not animating you mean the size of the content? Then add font-size to your animation.
#-webkit-keyframes spinAndZoom {
0% {
width: 10px;
height: 10px;
margin-left: -5px;
margin-top: -5px;
-webkit-transform: rotateZ(0deg);
font-size: 0;
}
100% {
width: 400px;
height: 400px;
margin-left: -200px;
margin-top: -200px;
-webkit-transform: rotateZ(360deg);
font-size: 16px;
}
}
As shennan mentioned, the animation of font-size is most of the time a bit jerky.
I've added ease-in to the animation, to make it appear less jerky at the end.
.go {
-webkit-animation: spinAndZoom 1s 1 ease-in;
-webkit-animation-fill-mode: forwards;
}
Updated Fiddle
You can go with Kilian's suggestion by adding font-size to the webkit animation, but the results are a little jerky.
I would either use a dynamically created image/canvas to create the text, or simply call your losses and add overflow:hidden to the #fdiv CSS block to get rid of the initial text spilling over the edge of your div:
#fdiv{
width: 10px;
height: 10px;
position: absolute;
margin-left: -5px;
margin-top: -5px;
left: 50%;
top: 50%;
background-color: red;
overflow:hidden; /* here is your eureka fix */
}