Facebook playable ads in Google Web Designer - html
(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!
Related
Animating two circles to meet exactly in the middle
So I'm aiming to have two circles meet from either side of the screen and meet in the middle to perform the second half of the animation (scaling and opacity change). But by setting the initial keyframe and last using vw they don't meet in the middle - since the vw value is relative to the left side of the div and not the centre (I have used vw as I need this to be responsive). So, what happens is that the left sides of the circle meet in the centre. Does anyone know a simple fix to this using just css? I am newish to coding, so if the answer is obvious I apologise. Here is my code: #keyframes left { 0% { transform: translate3d(0vw, 50%, 0) scale3d(1, 1, 1); opacity: 50%; animation-timing-function: ease-in; } 60% { transform: translate3d(50vw, 50%, 0) scale3d(1, 1, 1); opacity: 50%; animation-timing-function: ease-out; } 100% { transform: translate3d(50vw, 50%, 0) scale3d(2, 2, 1); opacity: 0%; animation-timing-function: ease-out; } } #keyframes right { 0% { transform: translate3d(100vw, 50%, 0) scale3d(1, 1, 1); opacity: 50%; animation-timing-function: ease-in; } 60% { transform: translate3d(50vw, 50%, 0) scale3d(1, 1, 1); opacity: 50%; animation-timing-function: ease-out; } 100% { transform: translate3d(50vw, 50%, 0) scale3d(2, 2, 1); opacity: 0%; animation-timing-function: ease-out; } } .circleleft { overflow: hidden; position: absolute; background: white; border-radius: 50%; width: 500px; height: 500px; animation: left 2s; animation-fill-mode: forwards; } .circleright { overflow: hidden; position: absolute; background: white; border-radius: 50%; width: 500px; height: 500px; animation: right 2s; animation-fill-mode: forwards; } <div style="width:100vw; height:100vh; background-color:#87827E"> <div class="circleleft"></div> <div class="circleright"></div> </div> You can see it in use here too: https://ruairimadine.co.uk/sudoroux
One trick is to initially position both circles in the center and the animation/translation will offset them from the left or right. I optimized the code to only use pseudo-elements and make it easier to understand: body { margin: 0; height: 100vh; background-color: #87827E; overflow: hidden; position:relative; } body::before, body::after{ content:""; position: absolute; top: calc(50% - 25vmin); left:calc(50% - 25vmin); background: white; opacity: 50%; border-radius: 50%; width: 50vmin; height: 50vmin; animation: move 2s forwards; } /* 50vw : half the screen width | 25vmin half the circle width*/ body::before { transform:translateX(calc( 50vw + 25vmin)); } body::after { transform:translateX(calc(-50vw - 25vmin)); } #keyframes move { 60% { transform: translateX(0) scale(1); opacity: 50%; } 100% { transform: translateX(0) scale(2); opacity: 0%; } }
In this example the circles size is stored in the root variable --circle-size: 100px;. So the circles can be centered with top and left easily. The animation uses the properties left (position), opacity and transform: scale (scaling). setTimeout(()=>{ document.querySelector('.circle-left').classList.add('circle__animated'); document.querySelector('.circle-right').classList.add('circle__animated'); }, 1000); :root{ --circle-size: 100px; } .circle{ position: absolute; width: var(--circle-size); height: var(--circle-size); border-radius: 50%; top: calc(50% - var(--circle-size)/2); } .circle.circle-left{ background: red; left: 0; animation: left 2s; animation-fill-mode: forwards; } .circle.circle-right{ background: green; left: calc(100% - var(--circle-size)); animation: right 2s; animation-fill-mode: forwards; } #keyframes left { 0% { left: 0; opacity: 1; transform: scale(1); animation-timing-function: ease-in; } 60% { left: calc(50% - var(--circle-size)/2); opacity: 0.5; transform: scale(1); animation-timing-function: ease-out; } 100% { left: calc(50% - var(--circle-size)/2); opacity: 0; transform: scale(5); animation-timing-function: ease-out; } } #keyframes right { 0% { left: calc(100% - var(--circle-size)); opacity: 1; transform: scale(1); animation-timing-function: ease-in; } 60% { left: calc(50% - var(--circle-size)/2); opacity: 0.5; transform: scale(1); animation-timing-function: ease-out; } 100% { left: calc(50% - var(--circle-size)/2); opacity: 0; transform: scale(5); animation-timing-function: ease-out; } } <div style="position: absolute; top:0; left: 0; width:100vw; height:100vh; background-color:#87827E; padding: 0; margin: 0; overflow: hidden;"> <div class="circle circle-left"></div> <div class="circle circle-right"></div> </div>
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>
How to move an element linearly while rotating with css
When i use transform on one element for translate3d and rotate3d then the element starts to orbit. i want linear motion while rotating. i have used webkit animations in css img{height:50px; width:50px; animation:tt; animation-duration:10s; position:relative; top:40vh; left:40vw;} #keyframes tt { 0%{ transform:rotate3d(0,0,0,0) translate3d(0,0,0); } 50%{ transform:rotate3d(0,0,1,2000deg) translate3d(300px,0,0); } } i wanted it move forward while rotating like a cars tire instead its like a comet or excited electron
You could use the left and right CSS properties, similar example on https://www.w3schools.com/css/css3_animations.asp I have included the snippet below: https://codepen.io/mohamedhmansour/pen/bOONQr img { height: 50px; width: 50px; animation: tt; animation-duration: 5s; position: relative; top: 0; left: 0; } #keyframes tt { 0% { transform: rotate(0deg); left: 0px; } 50% { transform: rotate(-360deg); left: 100%; } 100% { transform: rotate(0deg); left: 0px; } } <div class="wrapper"> <img src="http://blog.codepen.io/wp-content/uploads/2012/06/Button-Fill-Black-Small.png" /> </div> https://codepen.io/mohamedhmansour/pen/bOONQr
You didn't define the 100% state so by default it will be the a transform:none (the default value since no transform is defined on the element) which is creating the issue. You should define it and use a bigger value for the angle by keeping the same axis to keep your element on the orbit: .img { height: 50px; width: 50px; animation: tt linear 10s; position: relative; top: 40vh; left: 40vw; background:red; } #keyframes tt { 0% { transform: rotate3d(0, 0, 0, 0) translate3d(0, 0, 0); } 50% { transform: rotate3d(0, 0, 1, 2000deg) translate3d(100px, 0, 0); } 100% { transform: rotate3d(0, 0, 1, 4000deg) translate3d(100px, 0, 0); } <div class="img"></div> And if you want a linear animation simply do like this (translation before rotation): .img { height: 50px; width: 50px; animation: tt linear 5s forwards; position: relative; top: 40vh; left: 40vw; background:red; } #keyframes tt { 0% { transform: translateX(0) rotate(0); } 100% { transform: translateX(100px) rotate(360deg); } <div class="img"></div>
You can try this: img{ height: 50px; width: 50px; position: absolute; top:40vh; left:40vw; -webkit-animation: spinner 10s linear infinite; left: 0; } #-webkit-keyframes spinner{ 50%{ -webkit-transform: rotate(1440deg); left: calc(100% - 200px); } } <img src="https://www.gstatic.com/webp/gallery/4.sm.jpg">
Transform-origin problem while resizing div in an animation
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>
CSS transform with parent transform does not work on iOS Safari
I created a mockup of the situation because I wasn't able to create a testable version so easily. But to get the gist: #keyframes mainFadeIn { 0% { opacity: 0; transform: translateY(-3rem); } 100% { opacity: 1; transform: translateY(0); } } // If I use this, without the transform, then everything works. // // #keyframes mainFadeIn { // 0% { // opacity: 0; // } // // 100% { // opacity: 1; // } // } .main { animation-name: mainFadeIn; animation-duration: 1s; animation-fill-mode: both; animation-timing-function: linear; background-color: gray; width: 100%; height: 16rem; padding: 3rem; } .card { transition: transform 500ms; transform-style: preserve-3d; -webkit-transform-origin: 50% 50%; perspective: 200px; // Ignore margin: auto; width: 30rem; height: 10rem; background-color: lightblue; &.flipped { transform: rotateY(-180deg); } } .front, .back { backface-visibility: hidden; } .back { transform: rotateY(-180deg); } <div class="main"> <div class="card"> <div class="front"></div> <div class="back"></div> </div> </div> Hopefully this is enough to know where the issue is. CodePen: https://codepen.io/anon/pen/owvqQP/ EDIT Well. It's probably this thing: css z-index lost after webkit transform translate3d But I still can't get it to work. The only solution would be to use position: relative; and top: 0; and top: -3rem; for the animations..
Looks like you forgot -webkit- prefix. Also recommend using translate3d for hardware acceleration. Try this way: #-webkit-keyframes mainFadeIn { 0% { opacity: 0; -webkit-transform: translate3d(0, -3rem, 0); transform: translate3d(0, -3rem, 0); } 100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } #keyframes mainFadeIn { 0% { opacity: 0; -webkit-transform: translate3d(0, -3rem, 0); transform: translate3d(0, -3rem, 0); } 100% { opacity: 1; -webkit-transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0); } } .main { -webkit-animation-name: mainFadeIn; -webkit-animation-duration: 1s; -webkit-animation-fill-mode: both; -webkit-animation-timing-function: linear; animation-name: mainFadeIn; animation-duration: 1s; animation-fill-mode: both; animation-timing-function: linear; background-color: gray; width: 100%; height: 16rem; padding: 3rem; } .card { transition: -webkit-transform 500ms; -webkit-transform-style: preserve-3d; transition: transform 500ms; transform-style: preserve-3d; -webkit-transform-origin: 50% 50%; -webkit-perspective: 200px; // Ignore perspective: 200px; // Ignore margin: auto; width: 30rem; height: 10rem; background-color: lightblue; &.flipped { -webkit-transform: rotateY(-180deg); transform: rotateY(-180deg); } } .front, .back { -webkit-backface-visibility: hidden; backface-visibility: hidden; } .back { -webkit-transform: rotateY(-180deg); transform: rotateY(-180deg); }