Transform-origin problem while resizing div in an animation - html

While trying to make a small css animation I encountered a small problem with the transform-origin property of css.
To illustrate what I'm talking about I designed what I wanted with a cms here's what I want to get but using a cms the code is more complicated:
.main {
margin:30px;
box-sizing: border-box;
border-width: 1px;
border-style: solid;
background-color: rgb(230, 60, 60);
border-color: transparent;
width: 68px;
height: 25px;
transform-style: preserve-3d;
transform: translate3d(-8.93274px, -0.0896834px, 0px);
transform-origin: 33.9995px 12.5px 0px;
}
#keyframes gwd-gen-1wa0gwdanimation_gwd-keyframes {
0% {
width: 68px;
height: 25px;
transform-origin: 33.9995px 12.5px 0px;
transform: translate3d(-8.93274px, -0.0896834px, 0px);
animation-timing-function: cubic-bezier(0.415, 0.189, 0, 1.079);
}
14.2857% {
width: 185px;
height: 25px;
transform-origin: 33.9995px 12.5px 0px;
transform: translate3d(-8.93274px, -0.0896834px, 0px);
animation-timing-function: ease-out;
}
28.5714% {
width: 185px;
height: 25px;
transform-origin: 33.9995px 12.5px 0px;
transform: translate3d(-8.93274px, -0.0896834px, 0px);
animation-timing-function: cubic-bezier(0.255, 0.269, 0.445, 0.879);
}
42.8571% {
width: 68px;
height: 25px;
transform-origin: 12.4211px 12.5px 0px;
transform: translate3d(108px, 0px, 0px);
animation-timing-function: ease-out;
}
57.1429% {
width: 68px;
height: 25px;
transform-origin: 12.5035px 12.5px 0px;
transform: translate3d(108px, 0px, 0px);
animation-timing-function: cubic-bezier(0.415, 0.189, 0, 1.079);
}
71.4286% {
width: 185px;
height: 25px;
transform-origin: 34.0926px 12.5px 0px;
transform: translate3d(-9px, 0px, 0px);
animation-timing-function: ease-out;
}
85.7143% {
width: 185px;
height: 25px;
transform-origin: 34.0926px 12.5px 0px;
transform: translate3d(-9px, 0px, 0px);
animation-timing-function: ease;
}
100% {
width: 68px;
height: 25px;
transform-origin: 12.5583px 12.5px 0px;
transform: translate3d(-9px, 0px, 0px);
animation-timing-function: linear;
}
}
.main {
animation: gwd-gen-1wa0gwdanimation_gwd-keyframes 1.2s linear 0s 1 normal forwards running;
}
I tried to reproduce it without using 3d properties as when using the cms but my problem is that when the div resizes it moves at its ends and then changes orientation when it should behave like with the css. So here's what I got by doing just the first part of the animation (where my div grows from the right and shrinks on the left side) But it moves during the resizing:
.main{
animation: resize 2s ease 1 normal forwards;
height:30px;
width:200px;
background-color:red;
transform-origin:left;
margin-left:100px;
}
#keyframes resize {
0%{
}
50%{
transform-origin:left;
transform:scalex(2);
}
100%
{
transform-origin:right;
transform:scalex(0.8);
}
}
<html>
<head>
</head>
<body>
<div class="main"></div>
</body>
</html>

Simply change the scale is not correct! You should combine the position and the scale. Since the scale does not change the actual position. Similarly, to your 3D animation, you should also combine several animations together. Here is my solution.
.main{
animation: resize 2s ease 1 normal forwards;
height:30px;
width:200px;
background-color:red;
transform-origin:left;
margin-left:100px;
}
#keyframes resize {
0%{
}
50%{
transform-origin:left;
transform:scalex(2) ;
}
100%{
transform: translateX(100%);
}
}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div class="main"></div>
</body>
</html>

Related

Facebook playable ads in Google Web Designer

(Coding is very new to me, and I don't know much about it at all!)
I am attempting to make a playable facebook ad in Google Web Designer - it will be super simple.
I'm having trouble with this specification - 'FbPlayableAd.onCTAClick() implementation required.' I'm not really sure where to add it in the code. Every time I upload the .html file to facebook, that's the only bit that's missing.
Is someone able to tell me where to add it in the code view? Is it even possible? A step-by-step would be really useful.
Bonus points if there's a better platform to use for a super duper beginner!
EDIT: as per John's comment, I've attached an image of what the code looks like below:
(if im correct, then it looks like Google Web Designer's event code is gwd-taparea. This all gets uploaded as a .html file here: https://developers.facebook.com/tools/playable-preview/)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="Google Web Designer 11.0.2.0415">
<meta name="template" content="Banner 3.0.0">
<meta name="environment" content="gwd-dv360">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="gwdpage_style.css" rel="stylesheet" data-version="13" data-exports-type="gwd-page">
<link href="gwdpagedeck_style.css" rel="stylesheet" data-version="14" data-exports-type="gwd-pagedeck">
<link href="gwdgooglead_style.css" rel="stylesheet" data-version="8" data-exports-type="gwd-google-ad">
<link href="gwdimage_style.css" rel="stylesheet" data-version="16" data-exports-type="gwd-image">
<link href="gwdtaparea_style.css" rel="stylesheet" data-version="7" data-exports-type="gwd-taparea">
<style type="text/css" id="gwd-lightbox-style">
.gwd-lightbox {
overflow: hidden;
}
</style>
<style type="text/css" id="gwd-text-style">
p {
margin: 0px;
}
h1 {
margin: 0px;
}
h2 {
margin: 0px;
}
h3 {
margin: 0px;
}
</style>
<style type="text/css">
html, body {
width: 100%;
height: 100%;
margin: 0px;
}
.gwd-page-container {
position: relative;
width: 100%;
height: 100%;
}
.gwd-page-content {
background-color: transparent;
transform: perspective(1400px) matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
transform-style: preserve-3d;
position: absolute;
}
.gwd-page-wrapper {
background-color: rgb(255, 255, 255);
position: absolute;
transform: translateZ(0px);
}
.gwd-page-size {
width: 1080px;
height: 1080px;
}
.gwd-image-1n37 {
position: absolute;
width: 500px;
height: 500px;
left: 86px;
top: 108px;
transform-style: preserve-3d;
transform: translate3d(0px, 0px, 0px);
}
.gwd-rect-4vdd {
position: absolute;
left: 206.53px;
top: 823.633px;
width: 74.6495px;
height: 74.6495px;
box-sizing: border-box;
border-width: 1px;
border-style: solid;
border-color: rgb(0, 0, 0);
background-color: transparent;
transform-style: preserve-3d;
transform: translate3d(0px, 0px, 0px);
}
#keyframes gwd-gen-ubpsgwdanimation_gwd-keyframes {
0% {
width: 74.6495px;
height: 74.6495px;
background-color: transparent;
transform: translate3d(0px, 0px, 0px);
animation-timing-function: linear;
}
16.6667% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
33.3333% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
50% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
66.6667% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
83.3333% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
100% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
}
#page1.gwd-play-animation .gwd-gen-ubpsgwdanimation {
animation: 3s linear 0s 1 normal forwards running gwd-gen-ubpsgwdanimation_gwd-keyframes;
}
#keyframes gwd-gen-2ljmgwdanimation_gwd-keyframes {
0% {
width: 74.6495px;
height: 74.6495px;
background-color: transparent;
transform: translate3d(-64.8412px, 14.8877px, 0px);
animation-timing-function: linear;
}
16.6667% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
33.3333% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
50% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
66.6667% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
83.3333% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
100% {
width: 500px;
height: 100px;
background-color: rgb(216, 6, 6);
transform: translate3d(129px, 52px, 0px);
animation-timing-function: linear;
}
}
#page1.gwd-play-animation .gwd-gen-2ljmgwdanimation {
animation: 3s linear 0s 1 normal forwards running gwd-gen-2ljmgwdanimation_gwd-keyframes;
}
.gwd-svg-1fha {
transform: translate3d(-64.8412px, 14.8877px, 0px);
}
.gwd-taparea-1c0t {
position: absolute;
left: 472.78px;
top: 838.563px;
width: 200px;
height: 140px;
transform-style: preserve-3d;
transform: translate3d(0px, 0px, 0px);
}
#keyframes gwd-gen-1loygwdanimation_gwd-keyframes {
0% {
transform: translate3d(0px, 0px, 0px);
animation-timing-function: linear;
}
16.6667% {
transform: translate3d(0px, 17px, 0px);
animation-timing-function: linear;
}
33.3333% {
transform: translate3d(0px, 17px, 0px);
animation-timing-function: linear;
}
50% {
transform: translate3d(0px, 17px, 0px);
animation-timing-function: linear;
}
66.6667% {
transform: translate3d(0px, 17px, 0px);
animation-timing-function: linear;
}
83.3333% {
transform: translate3d(0px, 17px, 0px);
animation-timing-function: linear;
}
100% {
transform: translate3d(0px, 17px, 0px);
animation-timing-function: linear;
}
}
#page1.gwd-play-animation .gwd-gen-1loygwdanimation {
animation: 3s linear 0s 1 normal forwards running gwd-gen-1loygwdanimation_gwd-keyframes;
}
#keyframes gwd-gen-4zx8gwdanimation_gwd-keyframes {
0% {
transform: translate3d(0px, 0px, 0px);
animation-timing-function: linear;
}
16.6667% {
transform: translate3d(0px, 0px, 0px);
animation-timing-function: linear;
}
33.3333% {
transform: translate3d(250px, 57px, 0px);
animation-timing-function: linear;
}
50% {
transform: translate3d(281.103px, -119.122px, 0px);
animation-timing-function: linear;
}
66.6667% {
transform: translate3d(-13px, 79px, 0px);
animation-timing-function: linear;
}
83.3333% {
transform: translate3d(487px, 54px, 0px);
animation-timing-function: linear;
}
100% {
transform: translate3d(-46px, -51px, 0px);
animation-timing-function: linear;
}
}
#page1.gwd-play-animation .gwd-gen-4zx8gwdanimation {
animation: 3s linear 0s 1 normal forwards running gwd-gen-4zx8gwdanimation_gwd-keyframes;
}
</style>
<script data-source="googbase_min.js" data-version="4" data-exports-type="googbase" src="googbase_min.js"></script>
<script data-source="gwd_webcomponents_v1_min.js" data-version="2" data-exports-type="gwd_webcomponents_v1" src="gwd_webcomponents_v1_min.js"></script>
<script data-source="gwdpage_min.js" data-version="13" data-exports-type="gwd-page" src="gwdpage_min.js"></script>
<script data-source="gwdpagedeck_min.js" data-version="14" data-exports-type="gwd-pagedeck" src="gwdpagedeck_min.js"></script>
<script data-source="https://s0.2mdn.net/ads/studio/Enabler.js" data-exports-type="gwd-google-ad" src="https://s0.2mdn.net/ads/studio/Enabler.js"></script>
<script data-source="gwdgooglead_min.js" data-version="8" data-exports-type="gwd-google-ad" src="gwdgooglead_min.js"></script>
<script data-source="gwdimage_min.js" data-version="16" data-exports-type="gwd-image" src="gwdimage_min.js"></script>
<script data-source="gwdtaparea_min.js" data-version="7" data-exports-type="gwd-taparea" src="gwdtaparea_min.js"></script>
<script type="text/javascript" gwd-events="support" src="gwd-events-support.1.0.js"></script>
<script type="text/javascript" gwd-events="handlers">
gwd.auto_Gwd_taparea_1Action = function(event) {
// GWD Predefined Function
gwd.actions.gwdGoogleAd.exit('gwd-ad', 'CTA', 'https://www.google.com/', true, true, 'page1');
};
</script>
<script type="text/javascript" gwd-events="registration">
// Support code for event handling in Google Web Designer
// This script block is auto-generated. Please do not edit!
gwd.actions.events.registerEventHandlers = function(event) {
gwd.actions.events.addHandler('gwd-taparea_1', 'action', gwd.auto_Gwd_taparea_1Action, false);
};
gwd.actions.events.deregisterEventHandlers = function(event) {
gwd.actions.events.removeHandler('gwd-taparea_1', 'action', gwd.auto_Gwd_taparea_1Action, false);
};
document.addEventListener("DOMContentLoaded", gwd.actions.events.registerEventHandlers);
document.addEventListener("unload", gwd.actions.events.deregisterEventHandlers);
</script>
</head>
<body>
<gwd-google-ad id="gwd-ad" polite-load="">
<gwd-metric-configuration>
<gwd-metric-event source="gwd-taparea_1" event="tapareaexit" metric="" exit="Exit"></gwd-metric-event>
</gwd-metric-configuration>
<gwd-pagedeck class="gwd-page-container" id="pagedeck">
<gwd-page id="page1" class="gwd-page-wrapper gwd-page-size gwd-lightbox" data-gwd-width="1080px" data-gwd-height="1080px">
<div class="gwd-page-content gwd-page-size">
<gwd-image id="how_to" source="assets/how to.png" scaling="stretch" class="gwd-image-1n37 gwd-gen-4zx8gwdanimation"></gwd-image>
<svg data-gwd-shape="rectangle" class="gwd-rect-4vdd gwd-gen-ubpsgwdanimation"></svg>
<svg data-gwd-shape="rectangle" class="gwd-rect-4vdd gwd-gen-2ljmgwdanimation gwd-svg-1fha"></svg>
<gwd-taparea id="gwd-taparea_1" class="gwd-taparea-1c0t gwd-gen-1loygwdanimation"></gwd-taparea>
</div>
</gwd-page>
</gwd-pagedeck>
<gwd-exit metric="CTA" url="https://www.google.com/"></gwd-exit>
</gwd-google-ad>
<script type="text/javascript" id="gwd-init-code">
(function() {
var gwdAd = document.getElementById('gwd-ad');
/**
* Handles the DOMContentLoaded event. The DOMContentLoaded event is
* fired when the document has been completely loaded and parsed.
*/
function handleDomContentLoaded(event) {
}
/**
* Handles the WebComponentsReady event. This event is fired when all
* custom elements have been registered and upgraded.
*/
function handleWebComponentsReady(event) {
// Start the Ad lifecycle.
setTimeout(function() {
gwdAd.initAd();
}, 0);
}
/**
* Handles the event that is dispatched after the Ad has been
* initialized and before the default page of the Ad is shown.
*/
function handleAdInitialized(event) {}
window.addEventListener('DOMContentLoaded',
handleDomContentLoaded, false);
window.addEventListener('WebComponentsReady',
handleWebComponentsReady, false);
window.addEventListener('adinitialized',
handleAdInitialized, false);
})();
</script>
</body>
</html>
Thanks!

How to do 2+ rotations while resetting the origin between each during a keyframe?

I try to do an animated box that will unfold itself on the page load.
I have a panel lifted up. I try to rotate it 90deg to the ground, and after, I would want to lift it up again based on the other edge 90deg.
I tried to change the origin (transform-origin: top) but it change the origin to the original origin. I had to add 2 translation to position it at the right place but it create a bump. The edge on the ground don't stick on the ground.
Here's my current fiddle: https://jsfiddle.net/hbnta1uj/2/
I also tried without modifying the origin but I still get a bump:
#keyframes slideFront2 {
0% {
transform: rotateX(-0deg);
}
50% {
transform: rotateX(-90deg);
}
100% {
transform: rotateX(-180deg) translateZ(-100px) translateY(100px);
}
}
I have another idea where I position the second panel flat already and I hide it (opacity 0) and at 50% when the first panel is flat I show the second and just 90deg it.
But I would want to know for more complex animations if there's a way to do it the way I describe it, by always start at the new position the new transformation?
Thanks
I would consider an animation on the container to make it easier where you only need one keyframe:
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.container {
width: 90%;
margin: auto;
height: 100vh;
background-color: rgb(194, 194, 194);
}
.progressbar-wrapper {
width: 300px;
height: 100px;
top: calc(50% - 50px);
left: calc(50% - 150px);
position: absolute;
transform-style: preserve-3d;
transform: rotateX(-20deg) rotateY(-30deg);
}
.progressbar {
width: 100%;
height: 100%;
transform-origin: bottom;
animation: 0.5s ease-out 1 slideFront forwards;
transform-style: preserve-3d;
}
.side {
width: 100%;
height: 100%;
background-color: rgba(254, 254, 254, 0.3);
position: absolute;
top: 0;
left: 0;
}
#keyframes slideFront {
100% {
transform: rotateX(-90deg);
}
}
.bottom {
box-shadow: 10px 10px 50px 5px rgba(90, 90, 90, 0.7);
}
.back {
animation: 1s ease-out 0.5s 1 slideFront forwards;
transform-origin: top;
}
<div class="container">
<div class="progressbar-wrapper">
<div class="progressbar">
<div class="side back">
</div>
<div class="side bottom">
</div>
</div>
</div>
</div>
The thing I discover is that the order matter in the translate function. Everything is executed left to right so the origin of the rotation will be relative to the current position of the element if you execute everything left to right (Here's 2 boxes getting the same rotation translation but the order differ: https://codepen.io/anon/pen/oOQGPp)
So in my example, if you do:
50.001% {
transform: rotateX(90deg) translateZ(00px) translatey(100px) ;
transition-timing-function: linear;
}
100% {
transform: rotateX(0deg) translateZ(100px) translatey(00px) ;
transition-timing-function: linear;
}
The rotation will be applied before the translation so the rotation origin will not be the bottom line after the translation but it will be the position without the origin based on the translated part (So it will be the 0% position origin.) CSS will fail to make the path of the animation and it will add a little bump.
But if you do transform: TRANSLATE ROTATE, the rotation will be applied after the translation so the origin of the rotation will be related to the position with the translation. This is how I was able to rotate the item without getting the little bump bug.
Here's the full fixed css. You can run it in my original jsfiddle to see the result
* {
box-sizing: inherit;
margin: 0;
}
html {
box-sizing: border-box;
}
.container {
width: 90%;
margin: auto;
height: 100vh;
background-color: rgb(194, 194, 194);
}
.progressbar-wrapper {
width: 300px;
height: 100px;
top: 50%;
left: 50%;
position: absolute;
transform: translate(-50%, -50%);
}
.progressbar {
width: 100%;
height: 100%;
transform-style: preserve-3d;
transform: rotateX(-20deg) rotateY(-30deg);
}
.side {
width: 100%;
height: 100%;
background-color: rgba(254, 254, 254, 0.3);
position: absolute;
top: 0;
left: 0;
}
#keyframes slideBottom {
0% {
transform: rotateX(-0deg);
}
100% {
transform: rotateX(-90deg);
}
}
#keyframes slideFront {
0% {
transform: rotateX(-0deg);
}
50% {
transform: rotateX(-90deg);
}
50.001% {
transform: translateZ(100px) rotateX(90deg);
transition-timing-function: linear;
}
100% {
transform: translateZ(100px) rotateX(0deg) ;
transition-timing-function: linear;
}
}
.bottom {
animation: 0.5s ease-out 0s 1 slideBottom forwards;
box-shadow: 10px 10px 50px 5px rgba(90, 90, 90, 0.7);
transform-origin: bottom;
}
.back {
animation: 1s ease-out 0s 1 slideFront forwards;
transform-origin: bottom;
}

How to make a ring/hoop flip as a ball passes through it?

I am trying to make something like this:
but the ball doesn't seem to pass through the ring, but rather passes across the ring. How can I fix this issue?
body {
height: 50em;
}
.ring {
position: relative;
width: 200px;
height: 100px;
border-radius: 50%;
border: 10px solid #ffcf82;
z-index: 9
}
#keyframes spinner {
0% {
transform: rotateZ(0deg);
}
30% {
transform: rotateZ(0deg);
}
60% {
transform: rotateZ(180deg);
}
}
#keyframes translate {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-370px);
}
}
.ring {
animation-name: spinner;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 5s;
transform-style: preserve-3d;
}
.ball {
width: 50px;
height: 50px;
border-radius: 50%;
background: #14e78e;
margin: 100px;
}
.ball {
animation-name: translate;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 8s;
transform-style: preserve-3d;
}
<div class="ring"></div>
<div class="ball"></div>
I would create the ring using two elements (the bottom and the top part) to be able to adjust the z-index of each one differently:
.ring {
margin-top:80px;
position: relative;
width: 200px;
height: 100px;
}
.ring:before,
.ring:after{
content:"";
position:absolute;
left:0;
right:0;
height:100%;
border: 10px solid #ffcf82;
border-radius:50%;
box-sizing:border-box;
}
.ring:before {
z-index:-1;
clip-path: polygon(0 0, 100% 0, 100% 50%, 0 50%);
}
.ring:after {
z-index:1;
clip-path: polygon(0 100%, 100% 100%, 100% 50%, 0 50%);
}
#keyframes spinner {
0%,50% {
transform: rotate(0deg);
}
100% {
transform: rotate(-180deg);
}
}
#keyframes translate {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-300px);
}
}
.ring:before,
.ring:after{
animation: spinner infinite alternate 4s;
}
.ball {
width: 50px;
height: 50px;
border-radius: 50%;
background: #14e78e;
margin: 60px 80px;
position:relative;
z-index:0;
animation: translate 8s infinite linear;
}
<div class="ring"></div>
<div class="ball"></div>
Another idea in case you need better support than clip-path. The trick is to play with transparent color:
.ring {
margin-top:80px;
position: relative;
width: 200px;
height: 100px;
}
.ring:before,
.ring:after{
content:"";
position:absolute;
left:0;
right:0;
height:100%;
border: 10px solid #ffcf82;
border-radius:50%;
box-sizing:border-box;
}
.ring:before {
z-index:-1;
}
.ring:after {
z-index:1;
border-bottom-color:transparent;
border-right-color:transparent;
}
#keyframes spinner {
0%,50% {
transform: rotate(0deg);
}
100% {
transform: rotate(-180deg);
}
}
#keyframes translate {
0% {
transform: translateY(10px);
}
50% {
transform: translateY(-310px);
}
}
.ring:before,
.ring:after{
animation: spinner infinite alternate 4s;
}
.ball {
width: 50px;
height: 50px;
border-radius: 50%;
background: #14e78e;
margin: 60px 80px;
position:relative;
z-index:0;
animation: translate 8s infinite linear;
}
<div class="ring"></div>
<div class="ball"></div>
You can try to change z-index of ball inside of animation
body {
height: 50em;
}
.ring {
position: relative;
width: 200px;
height: 100px;
border-radius: 50%;
border: 10px solid #ffcf82;
z-index: 9
}
#keyframes spinner {
0% {
transform: rotateZ(0deg);
}
30% {
transform: rotateZ(0deg);
}
60% {
transform: rotateZ(180deg);
}
}
#keyframes translate {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-370px);
z-index: 10;
}
}
.ring {
animation-name: spinner;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 5s;
transform-style: preserve-3d;
}
.ball {
width: 50px;
height: 50px;
border-radius: 50%;
background: #14e78e;
margin: 100px;
position: relative;
}
.ball {
animation-name: translate;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 8s;
transform-style: preserve-3d;
}
<div class="ring"></div>
<div class="ball"></div>
You can use a 3d transform to get automatically this effect.
Rotate the circle in the X axis. Then, there is one part of it that is behind the plane, and another part that is in front of it. The ball is still in the 0 z plane, so it will naturally appear to cross through the circle:
body {
height: 50em;
transform-style: preserve-3d;
}
.ring {
position: relative;
width: 200px;
height: 100px;
border-radius: 50%;
border: 10px solid #ffcf82;
z-index: 9;
margin-top: 100px;
transform: rotateX(50deg) rotateY(0deg) ;
transform-style: preserve-3d;
}
#keyframes spinner {
0%, 30% {
transform: rotateX(50deg) rotateY(0deg);
}
60%, 100% {
transform: rotateX(50deg) rotateY(180deg);
}
}
#keyframes translate {
0% {
transform: translateY(0px);
}
50% {
transform: translateY(-370px);
}
}
.ring {
animation-name: spinner;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 5s;
transform-style: preserve-3d;
}
.ball {
width: 50px;
height: 50px;
border-radius: 50%;
background: #14e78e;
margin: 100px;
}
.ball {
animation-name: translate;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-duration: 8s;
transform-style: preserve-3d;
}
<div class="ring"></div>
<div class="ball"></div>

Keep rotating CSS animation level

I have this:
div {
position: relative;
width: 20px;
height: 100px;
border-radius: 10px;
background: green;
margin: 0 auto;
transform-origin: 10px 10px;
animation: rotate 1s ease-in-out infinite alternate;
}
#keyframes rotate {
from {transform: rotate(-30deg);}
to {transform: rotate(30deg);}
}
hr {
position: relative;
top: -10px;
}
<div></div>
<hr>
But I want something like this:
div {
position: relative;
width: 20px;
height: 100px;
border-radius: 10px;
background: green;
margin: 0 auto;
transform-origin: 10px 10px;
animation: rotate 1s ease-in-out infinite alternate, translate 0.5s ease-in-out infinite alternate;
}
#keyframes rotate {
from {transform: rotate(-30deg);}
to {transform: rotate(30deg);}
}
#keyframes translate {
from {top: 10px;}
to {top: 0px;}
}
hr {
position: relative;
top: -10px;
}
<div></div>
<hr>
EDIT: I probably didn't explain this well enough. What I meant is, is there a way to keep the bottom of the div touching the line witout using any sort of animation to move it up and down? I want it to be dynamic, so that if I change the value of the rotation, I won't have to calculate and change the value of the translation.
EDIT2: Simply put: I just want the div to do what the second example is doing without needing a specific value for the vertical movement.
You should play with values to get it perfect but this is the idea:
div {
position: relative;
width: 20px;
height: 100px;
border-radius: 10px;
background: green;
margin: 0 auto;
transform-origin: 10px 10px;
animation: rotate 1s ease-in-out infinite alternate;
}
#keyframes rotate {
0% {transform: rotate(-30deg); top: 10px;}
50% {top: 0px;}
100% {transform: rotate(30deg); top: 10px;}
}
hr {
position: relative;
top: -10px;
}
<div></div>
<hr>
I'm not sure that this is what do you expect, but I will give it a try.
* {
margin: 0;
padding: 0;
}
div {
width: 20px;
height: 100px;
border-radius: 10px;
background: green;
margin: 0 auto;
transform-origin: 10px 10px;
animation: rotate 1s ease-in-out infinite alternate, stretch 1s ease-in-out infinite;
}
hr {
position: absolute;
top: 99px;
width: 99%;
}
#keyframes rotate {
from {
transform: rotate(-30deg);
}
to {
transform: rotate(30deg);
}
}
#keyframes stretch {
0% {
height: 112px;
}
50% {
height: 100px;
}
100% {
height: 112px;
}
}
<div></div>
<hr>

Creating a Starry Background in CSS

I am making a solar system website in pure code with no images used. The problem is that I can't figure out how to get stars in the background. I'm trying to get something like a yellow spread-out polka dot pattern on a black background. This is my code (repeat div and styling for every other planet).
html,
body {
width: 100%;
height: 100%;
background-color: black;
}
#sun {
position: absolute;
top: 50%;
left: 50%;
height: 200px;
width: 200px;
margin-top: -100px;
margin-left: -100px;
border-color: orange;
border-width: 2px;
border-style: solid;
border-radius: 50%;
box-shadow: 0 0 64px yellow;
background-color: yellow;
}
#mercury {
position: absolute;
top: 0;
left: 50%;
height: 10px;
width: 10px;
margin-left: -5px;
margin-top: -5px;
border-radius: 50%;
background-color: #ffd9b3;
}
#mercury-orbit {
position: absolute;
top: 50%;
left: 50%;
width: 260px;
height: 260px;
margin-top: -130px;
margin-left: -130px;
border-width: 2px;
border-style: dotted;
border-color: white;
border-radius: 50%;
-webkit-animation: spin-right 22s linear infinite;
-moz-animation: spin-right 22s linear infinite;
-ms-animation: spin-right 22s linear infinite;
-o-animation: spin-right 22s linear infinite;
animation: spin-right 22s linear infinite;
}
#-webkit-keyframes spin-right {
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#keyframes spin-right {
100% {
-webkit-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-ms-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
<div id="sun"></div>
<div id="mercury-orbit">
<div id="mercury"></div>
</div>
From this, a nice starry night.
background-color:black;
background-image:
radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 40px),
radial-gradient(white, rgba(255,255,255,.15) 1px, transparent 30px),
radial-gradient(white, rgba(255,255,255,.1) 2px, transparent 40px),
radial-gradient(rgba(255,255,255,.4), rgba(255,255,255,.1) 2px, transparent 30px);
background-size: 550px 550px, 350px 350px, 250px 250px, 150px 150px;
background-position: 0 0, 40px 60px, 130px 270px, 70px 100px;
I found a pure CSS solution thanks to this code pen. This would make your website look like this - unfortunately I can't copy-paste the entire CSS in, as it's far too long (over 40,000 characters and StackOverflow only permits me to paste 30,000 for a code snippet). The original code was generated with SASS, and compiled, it's ridiculously long.
<div id='stars'></div>
<div id='stars2'></div>
<div id="sun"></div>
<div id="mercury-orbit">
<div id="mercury"></div>
</div>
The SASS code generating these stars:
// n is number of stars required
#function multiple-box-shadow ($n)
$value: '#{random(2000)}px #{random(2000)}px #FFF'
#for $i from 2 through $n
$value: '#{$value} , #{random(2000)}px #{random(2000)}px #FFF'
#return unquote($value)
$shadows-small: multiple-box-shadow(700)
$shadows-medium: multiple-box-shadow(200)
$shadows-big: multiple-box-shadow(100)
#stars
width: 1px
height: 1px
background: transparent
box-shadow: $shadows-small