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?
Related
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>
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:
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>
I have the following HTML/CSS code and I have an issue to center the content inside a flex container. The result is :
In my mind, I would like to center the ring inside the flex container AND center the text (temperature) and the CSS animation (arrow) just after the temperature inside the ring animation.
How to do this?
body {
background-color: #0d74ff;
}
.container {
padding: 20px;
}
.flexwrap {
display: flex;
flex-wrap: wrap;
}
.cell {
position: relative;
height: 200px;
width: 200px;
border: 1px solid rgba(0, 0, 0, 0.25);
}
.loader-ring {
width: 150px;
height: 150px;
}
.loader-ring-light {
width: 150px;
height: 150px;
border-radius: 150px;
box-shadow: 0 4px 0 #ffffff inset;
animation: rotate-360 6s linear infinite;
}
.loader-text {
font-weight: bold;
font-size: 2em;
}
.scroll-down {
border: 2px solid #fff;
border-radius: 100px;
width: 30px;
height: 30px;
}
.scroll-down i {
display: block;
border-radius: 100px;
transition: all 0.4s ease;
width: 100%;
height: 100%;
background-size: 0 auto;
animation: pulse 1.5s 0s infinite normal ease forwards;
background-image: url("https://jamesmuspratt.com/codepen/img/arrow-down.svg");
background-repeat: no-repeat;
}
#keyframes rotate-360 {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes pulse {
0% {
opacity: 0;
background-position: center top;
background-size: 0 auto;
}
10% {
opacity: 0;
}
50% {
opacity: 1;
background-size: 75% auto;
}
90% {
opacity: 0;
}
100% {
opacity: 0;
background-position: center bottom;
background-size: 0 auto;
}
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<div class="container">
<div class="flexwrap">
<div class="cell">
<div class='loader-ring'>
<div class='loader-ring-light'></div>
<div class='loader-ring-track'>
<div class='loader-text'>26.6°</div>
<div class="scroll-down"><i></i></div>
</div>
</div>
</div>
</div>
</div>
You don't need so many blocks here. You need absolute positioning because elements will need to stack on each other. Also for centering absolutely positioned elements you need this styles
.loader-ring,
.loader-ring-track {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
Demo:
body {
background-color: #0d74ff;
}
.container {
padding: 20px;
}
.cell {
position: relative;
height: 200px;
width: 200px;
border: 1px solid rgba(0, 0, 0, 0.25);
}
/* center absolutely positioned items */
/* both vertically and horizontally */
.loader-ring,
.loader-ring-track {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.loader-ring-track {
display: flex; /* new */
}
.loader-ring {
width: 150px;
height: 150px;
}
.loader-ring-light {
width: 150px;
height: 150px;
border-radius: 150px;
box-shadow: 0 4px 0 #ffffff inset;
animation: rotate-360 6s linear infinite;
}
.loader-text {
font-weight: bold;
font-size: 2em;
}
.scroll-down {
border: 2px solid #fff;
border-radius: 100px;
width: 30px;
height: 30px;
}
.scroll-down i {
display: block;
border-radius: 100px;
transition: all 0.4s ease;
width: 100%;
height: 100%;
background-size: 0 auto;
animation: pulse 1.5s 0s infinite normal ease forwards;
background-image: url("https://jamesmuspratt.com/codepen/img/arrow-down.svg");
background-repeat: no-repeat;
}
#keyframes rotate-360 {
from {
transform: rotate(0);
}
to {
transform: rotate(360deg);
}
}
#keyframes pulse {
0% {
opacity: 0;
background-position: center top;
background-size: 0 auto;
}
10% {
opacity: 0;
}
50% {
opacity: 1;
background-size: 75% auto;
}
90% {
opacity: 0;
}
100% {
opacity: 0;
background-position: center bottom;
background-size: 0 auto;
}
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
<div class="cell">
<div class='loader-ring'>
<div class='loader-ring-light'></div>
<div class='loader-ring-track'>
<div class='loader-text'>26.6°</div>
<div class="scroll-down"><i></i></div>
</div>
</div>
</div>
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>