Element wobbles CSS - html

I've made a heart with CSS and made it resize, go small - big every second, like normally. But I noticed this strange wobble, that I didn't really put there and is really painful to look at. I aware of few possible duplicate questions, but they didn't really help. Here's a fiddle.
html,
body,
.container {
height: 100%;
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
.heart {
display: flex;
justify-content: center;
align-items: center;
background-color: red;
transform: rotate(-45deg);
transform-style: preserve-3d;
animation: growMain 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
.heart:after,
.heart:before {
background-color: red;
content: "";
border-radius: 50%;
position: absolute;
transform: translateZ(-1px);
}
.heart:after {
animation: growAfter 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
.heart:before {
animation: growBefore 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#keyframes growMain {
from {
width: 50px;
height: 50px;
}
to {
width: 80px;
height: 80px;
}
}
#keyframes growAfter {
from {
left: 25px;
width: 50px;
height: 50px;
}
to {
left: 40px;
width: 80px;
height: 80px;
}
}
#keyframes growBefore {
from {
top: -25px;
width: 50px;
height: 50px;
}
to {
top: -40px;
width: 80px;
height: 80px;
}
}
.inner {
display: initial;
transform: rotate(45deg);
}
.text {
text-align: center;
color: white;
font-family: "Comic Sans MS";
font-size: 100%;
margin: 0;
}
<div class="container">
<div class="heart">
<div class="inner">
<p class="text">Some text</p>
</div>
</div>
</div>

Animating actual width/height/position tends to not perform super well, especially when doing multiple animations at once like you are here. Moving/resizing elements with transform tends to perform better.
In this case, I would recommend setting the initial size of your heart and then using a scale transformation to make the pulse effect. With this approach, you also get the added benefit of going from three animations to one, which is easier for the browser to handle, and you don't have to worry about syncing them all up.
In order to make the text not shrink along with the heart, you can put a wrapper around it, and absolutely position the text in the center of the wrapper, on top of the heart. Then just transform the heart itself, not the wrapper. (Or if you want the text to shrink along with the heart, keep the same HTML structure you have now.)
html,
body,
.container {
height: 100%;
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
.heart-wrapper {
position: relative;
width: 80px;
height: 80px;
}
.heart {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: red;
transform: rotate(-45deg) scale(1);
transform-style: preserve-3d;
animation: pulse 1s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
.heart::before {
left: 40px;
}
.heart::after {
top: -40px;
}
.heart::after,
.heart::before {
background-color: red;
content: "";
width: 80px;
height: 80px;
border-radius: 50%;
position: absolute;
transform: translateZ(-1px);
}
#keyframes pulse {
from {
transform: rotate(-45deg) scale(1);
}
to {
transform: rotate(-45deg) scale(0.6);
}
}
.text {
position: absolute;
top: 40%; /* slightly off-center to the top, so it appears centered when the heart shrinks */
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
color: white;
font-family: "Comic Sans MS";
font-size: 100%;
margin: 0;
}
<div class="container">
<div class="heart-wrapper">
<div class="heart"></div>
<div class="text">some text</div>
</div>
</div>

Related

How to make css animations work one by one

I am studying CSS animation. I want my animation moving one by one, as I don't know JS I want to do it by CSS only. How can I do this? I faced the problem of rules from and to in animations, when I change them the animations don't work as expected.
I have the following HTML
body {
margin: 0;
background: grey;
}
main {
font-family: Open Sans;
text-transform: uppercase;
line-height: 1;
position: absolute;
width: 100%;
height: 100%;
overflow: hidden;
background: transparent;
}
.animation {
width: 20em;
height: 4em;
margin: 1em auto;
position: relative;
}
.squares {
margin: auto;
background: red;
/* display: flex;
flex-wrap: wrap;
justify-content: center;*/
}
.small_square {
width: 10px;
height: 10px;
background-color: white;
text-align: center;
display: block;
text-align: center;
position: relative;
margin: 0;
padding: 0;
left: 48%;
animation: appearance_small 1s ease-in-out;
animation: move_around 3s ease-in-out;
*/
}
.big_square {
margin: auto;
width: 40px;
height: 40px;
background-color: black;
display: block;
position: relative;
top: 30px;
animation: appearance_big 1.3s ease-in-out;
animation-delay: 2s;
animation: spin 3s ease-in-out;
forwards;
}
#keyframes appearance_big {
0% {
transform: scale(0%);
}
100% {
opacity: 1;
}
}
#keyframes appearance_small {
0% {
opacity: 0;
transform: scale(0%);
top: 50px;
}
100% {
opacity: 1;
top: 0px;
}
}
#keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(180deg);
}
}
#keyframes move_around {
from {
transform: translate(50%, 50px) rotate(0turn) translate(-50%, -50px);
}
to {
transform: translate(50%, 50px) rotate(0.50turn) translate(-0%, -50px);
}
<main>
<div id="animation" class="animation">
<div class="squares">
<div class="small_square"></div>
<div class="big_square"></div>
</div>
</main>

IE11 Pseudo-element animation is not working properly

While building a loader icon, I noticed odd behavior in IE11 compared to Chrome, using this animation:
#keyframes loader-2 {
0% {
transform: translateX(0);
}
50% {
transform: translateX(-1.6rem);
}
100% {
transform: translateX(0);
}
}
The element correctly translates to the side at first, but then shifts super far before translating back. This only behaves this way in IE11 (works fine in Chrome/Firefox), and only on a pseudo-element (::after).
See this fiddle (or below code snippet) for an example. The top dot is a span, which works fine, the bottom dot is an ::after element, which behaves weirdly.
html {
font-size: 62.5%;
}
.splash {
align-items: center;
display: flex;
height: 100vh;
justify-content: center;
width: 100vw;
}
#keyframes loader-2 {
0% {
transform: translateX(0);
}
50% {
transform: translateX(-1.6rem);
}
100% {
transform: translateX(0);
}
}
.loader {
display: inline-block;
height: 3.2rem;
padding: 4rem 0;
position: relative;
width: 3.2rem;
border: 1px solid red;
}
.loader span {
animation: loader-2 1.5s ease infinite;
background: #024;
border-radius: 50%;
bottom: 0;
display: block;
height: 1.6rem;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 1.6rem;
}
.loader div::after {
animation: loader-2 1.5s ease infinite;
background: #024;
border-radius: 50%;
bottom: 0;
content: '';
display: block;
height: 1.6rem;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 3.2rem;
width: 1.6rem;
}
<div class="splash">
<div class="loader">
<span></span>
<div></div>
</div>
</div>
I'm able to work around this by not using pseudo-elements of course, but I would still like to know what causes this issue.
Animation and transition for pseudo-elements is not supported by IE11, check here:
https://caniuse.com/#feat=mdn-css_selectors_after_animation_and_transition_support
To work around this issue, you can try to use ID for the div and write CSS for it and avoid using pseudo.
Modified code:
html {
font-size: 62.5%;
}
.splash {
align-items: center;
display: flex;
height: 100vh;
justify-content: center;
width: 100vw;
}
#keyframes loader-2 {
0% {
transform: translateX(0);
}
50% {
transform: translateX(-1.6rem);
}
100% {
transform: translateX(0);
}
}
.loader {
display: inline-block;
height: 3.2rem;
padding: 4rem 0;
position: relative;
width: 3.2rem;
border: 1px solid red;
}
.loader span {
animation: loader-2 1.5s ease infinite;
background: #024;
border-radius: 50%;
bottom: 0;
display: block;
height: 1.6rem;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 0;
width: 1.6rem;
}
.loader #abc {
animation: loader-2 1.5s ease infinite;
background: #024;
border-radius: 50%;
bottom: 0;
content: '';
display: block;
height: 1.6rem;
left: 0;
margin: auto;
position: absolute;
right: 0;
top: 3.2rem;
width: 1.6rem;
}
<div class="splash">
<div class="loader">
<span></span>
<div id="abc"></div>
</div>
</div>
Output in IE 11 browser:

Animation positioning on window resize

I was wondering if it was possible to use jquery window.resize() to ensure the two donuts positioning never collides with the home text in the middle. I'm not sure how to link the x and y of the window size to change the top/left and bottom/right positioning values.
Or is there a way I could decrease the width and height of the donuts on window resize?
Any help would be appreciated!
html, body {
margin: 0;
}
#container {
width: 100vw;
height: 100vh;
background-color: pink;
display: flex;
align-items: center;
overflow: hidden;
position: relative;
}
#donut img,
#donut2 img {
width: 500px;
height: 500px;
}
#donut {
width: auto;
height: auto;
position: absolute;
animation: donut 2s;
animation-fill-mode: forwards;
}
#keyframes donut {
0% {
left: -20%;
top: -20%;
transform: translateZ(-100px);
}
100% {
left: -5%;
top: -5%;
transform: translateZ(100px);
}
}
#donut2 {
width: auto;
height: auto;
position: absolute;
animation: donut2 2s;
animation-fill-mode: forwards;
}
#keyframes donut2 {
0% {
right: -20%;
bottom: -20%;
transform: translateZ(-100px);
}
100% {
right: -5%;
bottom: -5%;
transform: translateZ(-100px);
}
}
#homeText {
width: 100%;
height: auto;
text-align: center;
font-size: 30px;
}
<div id="container">
<div id="donut">
<img src="https://upload.wikimedia.org/wikipedia/commons/a/a5/Glazed-Donut.jpg">
</div>
<div id="homeText">
<p>
Reward Points
</p>
<p>Get Your Daily Sweet Rewards</p>
</div>
<div id="donut2">
<img src="https://upload.wikimedia.org/wikipedia/commons/a/a5/Glazed-Donut.jpg">
</div>
</div>
Please Try This. I think this should be work:-
#container {
width: 100vw;
height: 100vh;
background-color: pink;
display: flex;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
}
#donut { width:30vw; }
#donut2 { width:30vw; }
#donut2 img, #donut img {
width: 100%;
max-width:100%;
height:auto;
}
#donut {
position: absolute;
animation: donut 2s;
animation-fill-mode: forwards;
}
#keyframes donut {
0% {
left: -5%;
top: -5%;
transform: translateZ(-100px);
}
100% {
left: 5%;
top: 5%;
transform: translateZ(100px);
}
}
#donut2 {
position: absolute;
animation: donut2 2s;
animation-fill-mode: forwards;
}
#keyframes donut2 {
0% {
right: -5%;
bottom: -5%;
transform: translateZ(-100px);
}
100% {
right: 5%;
bottom: 5%;
transform: translateZ(-100px);
}
}
#homeText {
width: 25vw;
height: auto;
text-align: center;
font-size: 30px;
}

Animate a skewed element in the skew angle in CSS

So I'm doing this for some lines on my webpage.
#keyframes dropHeader {
0% {
height: 0px;
}
100% {
height: 100%;
}
}
.slant-decor {
left: 50%;
height: 100%;
position: fixed;
display: inline-flex;
animation-name: dropHeader;
animation-iteration-count: 1;
animation-timing-function: ease-out;
animation-duration: 0.6s;
}
.slant-decor:after {
width: 5px;
height: 100%;
background-color: rgba(0, 0, 0, 0.55);
content: "";
position: relative;
margin-left: -5px;
transform: skewX(-30deg);
display: inline-block;
}
.slant-decor div {
width: 19px;
height: 100%;
display: inline-block;
margin-left: -4px;
-ms-transform: skewX(-30deg); /* IE 9 */
-webkit-transform: skewX(-30deg); /* Safari */
transform: skewX(-30deg); /* Standard syntax */
}
.decor-orange {
background-color: orange;
}
.decor-red {
background-color: red;
}
.decor-green {
background-color: green;
}
<div class="slant-decor">
<div class="decor-red"></div>
<div class="decor-orange"></div>
<div class="decor-green"></div>
</div>
As of right now, the animation on .slant-decor works fine, however - as you can see, it causes a kind of a weird effect on the lines. What I'd like to achieve is that the animation follow the skew angle aswell, creating an effect where the lines would slide in from the top of the page, at the right angle. How could I achieve this?
If my understanding is correct, setting a transform-origin: right top would produce the effect that you are looking for. The default value for transform-origin is 50% 50% (the center-mid point of the element). When you animate the height, this point is constantly changing and hence creates that weird effect. If the transform-origin is set to a point that is fixed then that problem would be avoided.
#keyframes dropHeader {
0% {
height: 0px;
}
100% {
height: 100%;
}
}
.slant-decor {
left: 50%;
height: 300px;
position: fixed;
display: inline-flex;
animation-name: dropHeader;
animation-iteration-count: 1;
animation-timing-function: ease-out;
animation-duration: 0.6s;
}
.slant-decor:after {
width: 5px;
height: 100%;
background-color: rgba(0, 0, 0, 0.55);
content: "";
position: relative;
margin-left: -5px;
transform-origin: right top;
transform: skewX(-30deg);
display: inline-block;
}
.slant-decor div {
width: 19px;
height: 100%;
display: inline-block;
margin-left: -4px;
transform-origin: right top;
transform: skewX(-30deg);
}
.decor-orange {
background-color: orange;
}
.decor-red {
background-color: red;
}
.decor-green {
background-color: green;
}
<div class="slant-decor">
<div class="decor-red"></div>
<div class="decor-orange"></div>
<div class="decor-green"></div>
</div>

Pulsating ring animation with CSS

I want to have an expanding radius that starts from the center of the div instead of it starting on the top left of the div.
Imagine the button has a pulsing outline that goes outwards. That pulsing outline should start from the middle of the div and go out.
See example here: https://jsbin.com/dinehoqaro/edit?html,css,output
You can see that the expansion is starting from the top left.
.circle {
background-color: white;
border: 1px solid red;
border-radius: 50%;
width: 50px;
height: 50px;
animation: pulse 1s infinte;
-webkit-animation: pulse 1.2s infinite;
}
button {
background-color: green;
border: none;
border-radius: 50%;
width: 50px;
height: 50px;
}
#-webkit-keyframes pulse {
from {
width: 50px;
height: 50px;
}
to {
width: 100px height: 100px;
}
}
#keyframes pulse {
from {
width: 50px;
height: 50px;
}
to {
width: 100px;
height: 100px;
}
}
<div class="circle"><button>click here</button></div>
Here's a general solution using CSS flexbox, transform and pseudo-elements.
body {
display: flex;
align-items: center;
justify-content: center;
background-color: lightyellow;
height: 100vh;
margin: 0;
}
#container {
display: flex;
align-items: center;
justify-content: center;
}
.sphere {
display: flex;
background: lightblue;
border-radius: 300px;
height: 100px;
width: 100px;
}
#container::after {
display: flex;
background: lightpink;
border-radius: 300px;
height: 250px;
width: 250px;
animation: pulsate 2.5s ease-out;
animation-iteration-count: infinite;
opacity: 0.0;
content: "";
z-index: -1;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#keyframes pulsate {
0% {
transform: scale(0.1, 0.1);
opacity: 0.0;
}
50% {
opacity: 1.0;
}
100% {
transform: scale(1.2, 1.2);
opacity: 0.0;
}
}
<div id="container">
<div class="sphere"></div>
</div>
jsFiddle
Also see this awesome solution by #harry: How to create a pulsing glow ring animation in CSS?