After translating an element in CSS it's transformation origin stays in it's original location. In this particular case I want the transformation origin to stay centered relative to the element during all transforms. I want the origin to sort of follow the element being transformed. I know about the transform-origin property but that seems to require me to manually move the origin with the element each time...And even if I could do that in JavaScript, it seems very math heavy and not intuitive.
The animation below behaves exactly as intended except for the last wide rotation. I want that last rotation to revolve around the center of the actual element. Not it's original location. How can I move the transform origin back to the center of this element. Ideas?
html, body {
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
justify-content: center;
align-items: center;
background-color: #fdfdfd;
color: #aaa;
font-family: Arial, 'sans-serif';
font-size: 0.8rem;
letter-spacing: 0.1rem;
}
.tri {
width: 0;
height: 0;
border-left: 1rem solid transparent;
border-right: 1rem solid transparent;
border-bottom: 1rem solid #555;
transform: scaleY( 2 );
border-radius: 50%;
}
.status, .instr {
position: absolute;
}
.status {
top: 0;
}
.instr {
bottom: 0;
}
<head>
<style>
.tri-bx {
animation-name: start;
animation-duration: 5s;
animation-iteration-count: infinite;
}
#keyframes start {
0% {
transform: rotate( 0deg );
}
33% {
transform: rotate( 315deg );
}
66% {
transform: rotate( 315deg ) translate( 0, -5rem );
}
100% {
transform: rotate( 720deg ) translate( 0, -5rem );
}
}
</style>
</head>
<body>
<div class="tri-bx">
<div class="tri"></div>
</div>
</body>
Resetting the transform origin, as you say is hard
However, you can keep adding transforms on the right side, with the previous ones unchanged, and you'll get what you want.
(As a side note, in a snippet you don't need the body element in the HTML, and the styles are better placed in the CSS editor.)
.tri-bx {
animation-name: start;
animation-duration: 5s;
animation-iteration-count: infinite;
}
#keyframes start {
0% {
transform: rotate( 0deg);
}
33% {
transform: rotate( 315deg);
}
66% {
transform: rotate( 315deg) translate( 0, -5rem) rotate(0deg);
}
100% {
transform: rotate( 315deg) translate( 0, -5rem) rotate( 405deg);
}
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
justify-content: center;
align-items: center;
background-color: #fdfdfd;
color: #aaa;
font-family: Arial, 'sans-serif';
font-size: 0.8rem;
letter-spacing: 0.1rem;
}
.tri {
width: 0;
height: 0;
border-left: 1rem solid transparent;
border-right: 1rem solid transparent;
border-bottom: 1rem solid #555;
transform: scaleY( 2);
border-radius: 50%;
}
.status,
.instr {
position: absolute;
}
.status {
top: 0;
}
.instr {
bottom: 0;
}
<div class="tri-bx">
<div class="tri"></div>
</div>
Related
I want to:
Align the circle (containing exclamation mark) with the dashed vertical line.
Make the circle bounce along the vertical line while changing the height of the dashed vertical line accordingly.
Can you please tell me how can I achieve that in CSS? thank in advance.
.pin{
display:inline-block;
align-contents: center;
}
.circle {
color: #ffffff;
background: #ff5500;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
font-size: 25px;
font-weight: bold;
display: inline-block;
animation: blinkingBackground 1s infinite;
}
#keyframes blinkingBackground {
0% {
opacity: 0;
transform: translateY(-10px);
}
25% {
opacity: 0.025;
transform: translateY(10px);
}
50% {
opacity: 0.05;
transform: translateY(-10px);
}
75% {
opacity: 0.075;
transform: translateY(10px);
}
100% {
opacity: 1;
}
}
.vline{
border-left: 1px dashed orangered;
height: 50px;
position: relative;
}
<div class="pin">
<div class="circle">
!
</div>
<div class="vline"></div>
</div>
#1 Align circle with line
For your .vline class add those two properties. Width in order to have the one pixel width from your border. And margin: 0 auto will center your div inside the parent div.
width: 1px;
margin: 0 auto;
#2 Reduce height while bouncing
Just add another animation to your .vline class.
In the example below I also changed the height from 50px to 0, that's keeping the .vline at zero pixels after animation is done. And instead I'm setting at keyframe 0% the height to 50px.
Depending on how many pixels you want to reduce it, you will need more keyframes. In the example I've reduced the height by 10px per second, so I have 5 keyframes with 10px steps.
#keyframes reduceHeight {
0% {
height: 50px;
}
20% {
height: 40px;
}
40% {
height: 30px;
}
60% {
height: 20px;
}
80% {
height: 10px;
}
100% {
height: 0px;
}
}
And here the working example
.pin{
display:inline-block;
align-contents: center;
}
.circle {
color: #ffffff;
background: #ff5500;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
font-size: 25px;
font-weight: bold;
display: inline-block;
animation: blinkingBackground 1s infinite;
}
.vline{
width: 1px;
margin: 0 auto;
border-left: 1px dashed orangered;
height: 0;
position: relative;
animation: reduceHeight 5s;
}
#keyframes blinkingBackground {
0% {
opacity: 0;
transform: translateY(-10px);
}
25% {
opacity: 0.025;
transform: translateY(10px);
}
50% {
opacity: 0.05;
transform: translateY(-10px);
}
75% {
opacity: 0.075;
transform: translateY(10px);
}
100% {
opacity: 1;
}
}
#keyframes reduceHeight {
0% {
height: 50px;
}
20% {
height: 40px;
}
40% {
height: 30px;
}
60% {
height: 20px;
}
80% {
height: 10px;
}
100% {
height: 0px;
}
}
<div class="pin">
<div class="circle">
!
</div>
<div class="vline"></div>
</div>
It's not perfect yet and you'll have to play around with positionings (maybe even have to add them to the animations), depending on what exactly you wanna acchieve. But it should give you a general idea and ONE possibility on how to do it. There might be different methods to do the same.
I have tried applying animation of rotating word vertically with the help of CSS and HTML but it does't work. Can anyone tell me that what is the problem with the code.
.line {
width: 100%;
height: 4rem;
overflow: hidden;
border: 1px solid black;
padding: 0;
margin-bottom: 16px;
}
/* flipping class and key frames*/
keyframes anim-flipX {
0% {
opacity: 0;
transform: rotateX(90def);
}
50% {
opacity: 1;
transform: rotateX(720deg);
}
100% {
/* animate nothing to pause animation at the end */
opacity: 1;
transform: rotateX(720deg);
}
}
<div class='line'>
<h2 class='flipX'>flip vertical</h2>
</div>
You have a couple of things wrong with your syntax. Here is the fixed up version that works. You were missing in # at beginning of keyframe, missing the animation duration and animation name in the class. There was also a type (def instead of deg).
.line {
width: 100%;
height: 4rem;
overflow: hidden;
border: 1px solid black;
padding: 0;
margin-bottom: 16px;
animation-duration: 3s;
animation-name: anim-flipX;
}
/* flipping class and key frames*/
#keyframes anim-flipX {
0% {
opacity: 0;
transform: rotateX(90deg);
}
50% {
opacity: 1;
transform: rotateX(720deg);
}
100% {
/* animate nothing to pause animation at the end */
opacity: 1;
transform: rotateX(720deg);
}
}
<div class='line'>
<h2 class='flipX'>flip vertical</h2>
</div>
You have to add animation-name and animation-duration properties:
.line {
width: 100%;
height: 4rem;
overflow: hidden;
border: 1px solid black;
padding: 0;
margin-bottom: 16px;
animation-name: anim-flipX; /* new */
animation-duration: 2s; /* new */
}
Also you need to add # before keyframes:
#keyframes anim-flipX {
0% {
opacity: 0;
transform: rotateX(90deg);
}
50% {
opacity: 1;
transform: rotateX(720deg);
}
100% {
opacity: 1;
transform: rotateX(720deg);
}
}
And your animation should work.
html {
font-size: 0.7rem;
}
div div {
top: 5rem;
background-color: #444;
transform-origin: top center;
}
.rotate_x {
animation-name: rotate_x;
}
#keyframes rotate_x {
0% {
transform: rotateX( 0deg );
}
100% {
transform: rotateX( 360deg );
}
}
.rotate_y {
animation-name: rotate_y;
}
#keyframes rotate_y {
0% {
transform: rotateY( 0deg );
}
100% {
transform: rotateY( 180deg );
}
}
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
html, body {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
}
body {
perspective: 5rem;
}
div {
position: relative;
top: -1.5rem;
width: 5rem;
height: 5rem;
background-color: #222;
border-radius: 0.5rem;
}
</style>
<div class='rotate_y'>
<div class='rotate_x'>
</div>
</div>
The gray bottom div doesn't appear to be rotating out perpendicular to the black top div as intended. Instead the bottom gray div appears to shrink until it has a negative value and gets inverted. The desired result is for the bottom gray div to rotate up as if on a hinge; making a 'L' shape in 3D space
before it comes all the way up and flips around to do the same on the other side. As the parent div rotates 360 degrees.
How can I make the bottom div create an 'L' shape as it connects with it's parent div?
You need to set transform-style and make the perspective a bit bigger:
html {
font-size: 0.7rem;
}
div div {
top: 5rem;
background-color: #444;
transform-origin: top center;
}
.rotate_x {
animation-name: rotate_x;
}
#keyframes rotate_x {
0% {
transform: rotateX( 0deg );
}
100% {
transform: rotateX( 360deg );
}
}
.rotate_y {
animation-name: rotate_y;
transform-style:preserve-3d; /* HERE */
}
#keyframes rotate_y {
0% {
transform: rotateY( 0deg );
}
100% {
transform: rotateY( 180deg );
}
}
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
animation-duration: 5s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
html, body {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
}
body {
perspective: 15rem;
}
div {
position: relative;
top: -1.5rem;
width: 5rem;
height: 5rem;
background-color: #222;
border-radius: 0.5rem;
}
</style>
<div class='rotate_y'>
<div class='rotate_x'>
</div>
</div>
Question:
Is it possible to animate the inner-circle .watch-face from 12 o'clock, counter clockwise, a full rotation or 2πr in only css keyframes?
Here would be the look of the completed animation:
COMPLETED ANIMATION:
Check out Live code starting point: Code sample
HTML:
<div class="watch-container">
<div class="watch-face"></div>
</div>
SCSS
$watch-face-size: 165;
$watch-border-size: 185;
.watch-face {
height: $watch-face-size + px;
width: $watch-face-size + px;
background: green;
box-sizing: border-box;
border-radius: $watch-face-size + px;
position: relative;
display: inline-block;
&.animate-counter-clockwise {
//How to write a keyframe animation to animate from
}
&::after {
content: "10";
position: absolute;
font-size: 68px;
color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
text-align: center;
font-weight: 400;
letter-spacing: -3px;
}
&::before {
position: absolute;
content: " ";
border: 5px solid green;
background: transparent;
border-radius: $watch-border-size + px;
width: $watch-border-size + px;
height: $watch-border-size + px;
top: -10px;
left: -10px;
}
}
//boilerplate styles
html {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
-o-box-sizing: border-box;
box-sizing: border-box;
}
*, *:before, *:after {
-webkit-box-sizing: inherit;
-moz-box-sizing: inherit;
-ms-box-sizing: inherit;
-o-box-sizing: inherit;
box-sizing: inherit;
}
.watch-container {
width: 30%;
margin: 50px auto;
line-height: 22px;
font-family: 'Roboto', arial, sans-serif;
font-size: 14px;
font-weight: 400;
text-align: center;
}
I don't know how you'd animate with your current markup. As far as I know, animating a div radially like that isn't possible. However, you can fake it by rotating squares and adding some covering. Here's a demo:
http://codepen.io/apexskier/pen/wGovRy
<div class="watch-face animating">
<div class="cover"></div>
<div class="a"></div>
<div class="b"></div>
<div class="c"></div>
<div class="d"></div>
</div>
a, b, c, and d represent the four quadrants of your clock, each will be rotated about the middle and shown and hidden as appropriate. cover is used to hide the first one as it's gradually shown.
I used z-index to properly layer things.
Here's some of the important css (see the codepen for everything)
EDIT: Fixed borders around quadrant by making the whole thing an even width
.watch-face {
.a, .b, .c, .d, .cover {
position: absolute;
height: ($watch-face-size / 2);
width: ($watch-face-size / 2);
background-color: green;
z-index: 5;
transform-origin: bottom right;
border-top-left-radius: ($watch-face-size / 2) - 1;
border-top: 1px solid #fff; // hides a nasty green aliasing line
border-left: 1px solid #fff; // hides a nasty green aliasing line
}
.cover {
opacity: 0;
}
&.animating, &.animate {
.a, .b, .c, .d, .cover {
animation-duration: 4s;
animation-timing-function: linear;
}
}
&.animating {
.a, .b, .c, .d, .cover {
animation-iteration-count: infinite;
}
}
&.animate {
.a, .b, .c, .d, .cover {
animation-iteration-count: 1;
}
}
.a {
animation-name: clock-a;
opacity: 1;
transform: rotate(90deg);
}
.b {
animation-name: clock-b;
transform: rotate(180deg);
}
.c {
animation-name: clock-c;
transform: rotate(270deg);
}
.d {
animation-name: clock-d;
transform: rotate(360deg);
}
.cover {
animation-name: clock-cover;
z-index: 10;
background-color: #fff;
}
}
#keyframes clock-cover {
0% {
opacity: 1;
}
74.9999999% {
opacity: 1;
}
75% {
opacity: 0;
}
100% {
opacity: 0;
}
}
#keyframes clock-a {
0% {
transform: rotate(0);
}
25% {
transform: rotate(90deg);
}
100% {
transform: rotate(90deg);
}
}
#keyframes clock-b {
0% {
transform: rotate(90deg);
opacity: 0;
}
24.999999% {
opacity: 0;
}
25% {
transform: rotate(90deg);
opacity: 1;
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(180deg);
opacity: 1;
}
}
#keyframes clock-c {
0% {
transform: rotate(180deg);
opacity: 0;
}
49.999999% {
opacity: 0;
}
50% {
transform: rotate(180deg);
opacity: 1;
}
75% {
transform: rotate(270deg);
}
100% {
transform: rotate(270deg);
opacity: 1;
}
}
#keyframes clock-d {
0% {
transform: rotate(270deg);
opacity: 0;
}
74.999999% {
opacity: 0;
}
75% {
transform: rotate(270deg);
opacity: 1;
}
100% {
transform: rotate(360deg);
opacity: 1;
}
}
I would use SVG for this animation, see the solution codepen:
<div class="watch-container">
<div class="watch-face">
<svg class="animator">
<circle cx="50%" cy="50%" r="100" />
</svg>
</div>
</div>
So you can animate the circle with simple:
#-webkit-keyframes clock-animation {
0% { stroke-dashoffset: 0; }
33% { stroke-dashoffset: 628; }
100% { stroke-dashoffset: 628; }
}
.animator {
height: 100%;
width: 100%;
circle {
animation: clock-animation 3s linear infinite;
fill: transparent;
stroke: white;
stroke-dasharray: 628;
stroke-dashoffset: 0;
stroke-width: 200px;
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
}
Short description: you need to create an SVG with a circle element inside. The circle element has a border (stroke) which in fact fills the whole circle size. Then you need to define the stroke appearance with stroke-dasharray which sets up the width of one stroke dash (100% in our case) and manipulate this single big dash with stroke-dashoffset. The offset moves the dash and it slightly goes away out of the circle.
I picked the numbers manually with simple guessing / chrome console, but they are quite calculatable with normal school geometry rules, and SASS helps here a lot.
What's really comfortable with this method is you need only one SVG element and a really small piece of CSS. It looks very pretty and makes you remember the school days, that's why this is my favorite way of doing these things.
Inspired by this awesome progress bar implementation
Helo Guys!
I was trying to create a spinning hover effect with CSS3.
Just made a circle spinning effect. Check the jsFiddle here: http://jsfiddle.net/63yyeezn/26/
However what I want to do now is to create something tthat spins but this time its box type
just like this image:
So basically I want similar effect just like the jsFiddle I shown above however this time it must be box.
Really having a hard time figuring this out. Here's my CSS:
body {
background: #292929;
padding-left: 30px;
font-size: 12px;
}
.twist {
display: inline-block;
font-size: 45px;
line-height: 90px;
cursor: pointer;
margin: 20px;
width: 90px;
height: 90px;
border-radius: 50%;
text-align: center;
position: relative;
text-decoration: none;
z-index: 1;
color: #fff;
}
.twist:after {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
content:'';
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.twist:before {
speak: none;
font-size: 48px;
line-height: 90px;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
display: block;
-webkit-font-smoothing: antialiased;
}
.twist.demo-4 {
width: 92px;
height: 92px;
box-shadow: 0 0 0 4px rgba(255, 255, 255, 1);
}
.twist.demo-4:before {
line-height: 92px;
}
.twist.demo-4:after {
top: -4px;
left: -4px;
padding: 0;
z-index: 10;
border: 4px dashed #fff;
}
.twist.demo-4:hover {
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
color: #fff;
}
.twist.demo-4:hover i {
color: #fff;
}
.twist.demo-4.spin:hover {
-webkit-transition: box-shadow 0.2s;
-moz-transition: box-shadow 0.2s;
transition: box-shadow 0.2s;
}
.twist.demo-4.spin:hover:after {
-webkit-animation: spinAround 9s linear infinite;
-moz-animation: spinAround 9s linear infinite;
animation: spinAround 9s linear infinite;
}
#-webkit-keyframes spinAround {
from {
-webkit-transform: rotate(0deg)
}
to {
-webkit-transform: rotate(360deg);
}
}
#-moz-keyframes spinAround {
from {
-moz-transform: rotate(0deg)
}
to {
-moz-transform: rotate(360deg);
}
}
#keyframes spinAround {
from {
transform: rotate(0deg)
}
to {
transform: rotate(360deg);
}
}
Hope you can help me with a jsFiddle file.
Thanks!
My answer won't fit exactly your example, but may interest you as it's a full-CSS3 solution, without HTML markup change. The animation won't be a rotation, but a translation.
Webkit version
.bordered {
overflow: hidden;
}
.bordered:before {
content: '';
position: absolute;
top: 5px; /* 5px: border width */
left: 5px;
right: 5px;
bottom: 5px;
background: white;
z-index: -1;
}
.bordered:after {
content: '';
position: absolute;
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
background: black;
z-index: -2;
}
.bordered:hover:after {
background: -webkit-linear-gradient(left, white 50%, black 50%); /* black: border color*/
background-size: 20px 100%; /* 20px: dash width */
-webkit-animation: borderAnimated 1s linear infinite;
}
#-webkit-keyframes borderAnimated {
from {
transform: rotate(45deg) translate(0, 0);
}
to {
transform: rotate(45deg) translate(20px, 0);
}
}
/* --- Style only--- */
.bordered {
width: 150px;
height: 150px;
line-height: 150px;
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div class="bordered">Lorem ipsum</div>
The trick is to have a stripped background in the :after pseudo-element, and a fake empty background in the :before element, which will work as a mask. When hovering your element, you just have to animate the :after pseudo-element to get something nice.
Credits: #vsynz
I don't think it can be possible only with static borders. Here is an alternative solution:
.rotating-dashed {
position: relative;
margin: 40px auto;
width: 90px;
height: 90px;
overflow: hidden;
color: #268;
}
.rotating-dashed .dashing {
display: block;
width: 100%;
height: 100%;
position: absolute;
}
.rotating-dashed .dashing:nth-of-type(2) {
-webkit-transform: rotate(90deg);
}
.rotating-dashed .dashing:nth-of-type(3) {
-webkit-transform: rotate(180deg);
}
.rotating-dashed .dashing:nth-of-type(4) {
-webkit-transform: rotate(270deg);
}
.rotating-dashed .dashing i {
display: block;
position: absolute;
left: 0;
top: 0;
width: 200%;
border-bottom: 5px solid
}
.rotating-dashed strong {
display: block;
width: 105%;
line-height: 90px;
text-align: center;
position: absolute;
}
.rotating-dashed:hover {
cursor: pointer;
}
.rotating-dashed:hover .dashing i {
-webkit-animation: slideDash 2.5s infinite linear;
border-bottom: 5px dashed
}
#-webkit-keyframes slideDash {
from {
-webkit-transform: translateX(-50%);
}
to {
-webkit-transform: translateX(0%);
}
}
<div class="rotating-dashed"> <span class="dashing"><i></i></span>
<span class="dashing"><i></i></span>
<span class="dashing"><i></i></span>
<span class="dashing"><i></i></span>
<strong>Demo</strong>
</div>