I'm trying to make a menu with css3 rotations. Here is an example.
http://jsfiddle.net/5Bg7P/
When a person hovers the square rotates 90 degrees around the x-axis, then when a user clicks it, it rotates an additional 5 degrees to 95 degrees. In chrome, sometimes after it rotates, and i click on it, it goes back to 0 degrees as if the mouse left the item even though it didn't. It happens more often if you let the menu item finish spinning and then only click on it.
Any advice would be appreciated.
#menu .menuItem {
position: relative;
float: left;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translate3d(0, 0, -50px);
transform: translate3d(0, 0, -50px);
-webkit-transition: .5s;
transition: .5s;
width: 120px;
height: 50px;
opacity: .6;
cursor: pointer;
}
#menu .menuItem:hover {
-webkit-transform: rotateX(90deg);
transform: rotateX(90deg);
margin-top: 1px;
}
#menu .menuItem:active {
-webkit-transform: rotateX(95deg);
transform: rotateX(95deg);
margin-top: 1px;
}
#menu .menuItem div {
position: absolute;
width: 120px;
height: 50px;
border: 1px solid #f2f2f2;
background: #848488;
}
#menu .menuItem .front,
#menu .menuItem .bottom {
text-align: center;
height: 50px;
line-height: 50px;
color: #f2f2f2;
letter-spacing: 1px;
font-size: 18px;
}
#menu .menuItem .front {
-webkit-transform: translate3d(0, 0, 25px);
transform: translate3d(0, 0, 25px);
}
#menu .menuItem .back {
-webkit-transform: translate3d(0, 0, -25px);
transform: translate3d(0, 0, -25px);
/* box-shadow: 0px 0px 40px 7px #b9c9d0; */
}
#menu .menuItem .top {
-webkit-transform: rotateX(90deg) translate3d(0, 0, 25px);
transform: rotateX(90deg) translate3d(0, 0, 25px);
}
#menu .menuItem .bottom {
-webkit-transform: rotateX(-90deg) translate3d(0, 0, 25px);
transform: rotateX(-90deg) translate3d(0, 0, 25px);
}
#menu .menuItem .right {
-webkit-transform: rotateY(90deg) translate3d(0, 0, 50px);
transform: rotateY(90deg) translate3d(0, 0, 50px);
height: 50px;
width: 50px;
left: 25px;
}
#menu .menuItem .left {
-webkit-transform: rotateY(-90deg) translate3d(0, 0, 50px);
transform: rotateY(-90deg) translate3d(0, 0, 50px);
height: 50px;
width: 50px;
left: 25px;
}
I think that's a problem about the hover state being activated in the base element or the child element.
I have changed a little bit how the hover and the transforms work, and now it works ok (or at least it works ok in my tests)
CSS
#menu {
position: relative;
z-index: 1;
float: left;
font-family: helvetica;
}
#menu .menuItem {
position: relative;
float: left;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transition: .5s;
transition: .5s;
width: 120px;
height: 50px;
opacity: .6;
cursor: pointer;
}
#menu .menuItem:active {
-webkit-transform: rotateX(5deg);
transform: rotateX(5deg);
margin-top: 1px;
}
#menu .menuItem div {
position: absolute;
width: 120px;
height: 50px;
border: 1px solid #f2f2f2;
background: #848488;
text-align: center;
line-height: 50px;
letter-spacing: 1px;
font-size: 18px;
margin-top: 1px;
transition: .5s;
}
#menu .menuItem .front {
-webkit-transform: translate3d(0, 0, 25px);
transform: translate3d(0, 0, 25px);
}
#menu .menuItem .bottom {
-webkit-transform: rotateX(-90deg) translate3d(0, 0, 25px);
transform: rotateX(-90deg) translate3d(0, 0, 25px);
}
#menu .menuItem:hover .front {
-webkit-transform: rotateX(90deg) translate3d(0, 0, 25px);
transform: rotateX(90deg) translate3d(0, 0, 25px);
}
#menu .menuItem:hover .bottom {
-webkit-transform: translate3d(0, 0, 25px);
transform: translate3d(0, 0, 25px);
}
fiddle
updated fiddle
The transtion between
transform: rotateX(90deg) translate3d(0, 0, 25px);
and
transform: translate3d(0, 0, 25px);
is not a perfect rotation, but the interpolation between the 2 movements.
To get a pure rotation, the other state must have matching properties:
transform: rotateX(0deg) translate3d(0, 0, 25px);
Related
I found this css code on internet it creates underline animation effect, i need to reverse it to be right-to-left instead of left to right.
.nav-item a {
display: inline-block !important;
&:after {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-transition: all .3s cubic-bezier(.19,1,.22,1);
-moz-transition: all .3s cubic-bezier(.19,1,.22,1);
transition: all .3s cubic-bezier(.19,1,.22,1);
-webkit-transform: scaleX(0) translate3d(0,0,0);
-moz-transform: scaleX(0) translate3d(0,0,0);
transform: scaleX(0) translate3d(0,0,0);
-webkit-transform-origin: 0 0;
-moz-transform-origin: 0 0;
-ms-transform-origin: 0 0;
-o-transform-origin: 0 0;
transform-origin: 0 0;
display: block;
height: 4px;
width: 100%;
background-color: #6cb2eb;
-o-transition: all .3s cubic-bezier(.19,1,.22,1);
opacity: 1;
content: "";
}
&:hover {
&:after {
-webkit-transform: scaleX(1) translate3d(0,0,0);
-moz-transform: scaleX(1) translate3d(0,0,0);
transform: scaleX(1) translate3d(0,0,0);
}
}
}
i tried to change &:after from scaleX(1) to scaleX(-1) it works as i needed but far from the text.
Just change transform-origin from 0 0 to 100% 100%:
.nav-item a {
display: inline-block !important;
}
.nav-item a:after {
border-radius: 10px;
transition: all 0.3s cubic-bezier(0.19, 1, 0.22, 1);
transform: scaleX(0) translate3d(0, 0, 0);
transform-origin: 100% 100%;
display: block;
height: 4px;
width: 100%;
background-color: #6cb2eb;
opacity: 1;
content: "";
}
.nav-item a:hover:after {
-webkit-transform: scaleX(1) translate3d(0, 0, 0);
-moz-transform: scaleX(1) translate3d(0, 0, 0);
transform: scaleX(1) translate3d(0, 0, 0);
}
<div class="nav-item">
<a>test</a>
</div>
Note: I converted scss to css and I removed useless vendor-specific properties
You have to float: right .nav-item a::after. It will work
.nav-item > a {
display: inline-block;
border-radius: 10px;
padding: 10px 20px;
transition: all 0.3s cubic-bezier(.19,1,.22,1);
text-decoration: none;
}
.nav-item > a::after {
content: '';
display: block;
height: 4px;
width: 0%;
background-color: #6cb2eb;
float: right;
transition: all 0.3s cubic-bezier(.19,1,.22,1);
}
.nav-item > a:hover::after {
width: 100%;
}
Check this fiddle - https://jsfiddle.net/jfgq2kva/6/
Im trying to use this character
֍
in place of a loading spinner.
Here's what I've got so far:
.spinner::after {
animation: rotating 2s linear infinite;
content: "֍";
font-size: 60px;
display: inline-block;
font-weight: normal;
transform-origin: 50% 50%;
}
#keyframes rotating {
0% {
transform: rotate(0deg) scale(1);
color: rgba(0, 0, 0, .5);
}
50% {
transform: rotate(180deg) scale(.8);
color: rgba(0, 0, 0, .85);
}
100% {
transform: rotate(360deg);
color: rgba(0, 0, 0, .5);
}
}
<i class="spinner"></i>
Even though this works, it is not perfect because the rotation does currently not happen around the perfect center of the character despite
transform-origin: 50% 50%;
making it look less than stellar.
Any ideas how to fix this?
I would use a fixed height equal to the font-size then play with line-height until I get it right. Also no need to set transform-origin since by default it's set to center
.spinner::after {
content: "֍";
font-size: 60px;
font-weight: normal;
line-height: 0.8;
display: inline-block;
height: 60px;
animation: rotating 2s linear infinite;
}
#keyframes rotating {
0% {
transform: rotate(0deg) scale(1);
color: rgba(0, 0, 0, .5);
}
50% {
transform: rotate(180deg) scale(.8);
color: rgba(0, 0, 0, .85);
}
100% {
transform: rotate(360deg);
color: rgba(0, 0, 0, .5);
}
}
<i class="spinner"></i>
it happens because a character height and width are not equal...
I tried to increase the height until It does what you want..
and here is the result:
.spinner::after {
animation: rotating 2s linear infinite;
content: "֍";
height: 80px;
font-size: 60px;
display: inline-block;
font-weight: normal;
}
#keyframes rotating {
0% {
transform: rotate(0deg) scale(1);
color: rgba(0, 0, 0, .5);
}
50% {
transform: rotate(180deg) scale(.8);
color: rgba(0, 0, 0, .85);
}
100% {
transform: rotate(360deg);
color: rgba(0, 0, 0, .5);
}
}
<i class="spinner"></i>
Three Properties
line-height: 3;
transform-origin: 50% 54%;
text-align: center;
Demo
.spinner::after {
animation: spin 2s infinite linear;
content: "֍";
font-size: 5em;
display: inline-block;
font-weight: normal;
/* Required */
line-height: 3;
/* Required */
transform-origin: 50% 54%;
/* Required */
text-align: center;
/* Optional for Position */
position: relative;
width: 3em;
top: 0;
}
#keyframes spin {
0% {
transform: rotate(0deg) scale(1);
color: rgba(0, 0, 0, .5);
}
50% {
transform: rotate(180deg) scale(.8);
color: rgba(0, 0, 0, .85);
}
100% {
transform: rotate(360deg);
color: rgba(0, 0, 0, .5);
}
}
<i class="spinner"></i>
You will not get perfect center while rotating rectangle shape but you will get perfect center if its square shape
see demo below
div {
display: inline-block;
width: 100px;
height: 100px;
background-color: brown;
text-align: center;
position: relative;
margin: 10px;
float: left;
}
.spinner0::after {
animation: rotating 2s linear infinite;
content: "֍";
height: 80px;
font-size: 60px;
display: inline-block;
font-weight: normal;
}
#keyframes rotating {
0% {
transform: rotate(0deg) scale(1);
color: rgba(0, 0, 0, .5);
}
50% {
transform: rotate(180deg) scale(.8);
color: rgba(0, 0, 0, .85);
}
100% {
transform: rotate(360deg);
color: rgba(0, 0, 0, .5);
}
}
div > i:before {
content: '';
width: 5px;
height: 5px;
background-color: #000;
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.spinner1::after{
animation: rotating 5s linear infinite;
content: "֍";
font-size: 60px;
line-height: 60px;
display: inline-block;
font-weight: normal;
position: absolute;
left: 50%;
top: 50%;
margin-top: -30px;
margin-left: -22px;
}
.spinner2::after {
animation: rotating 5s linear infinite;
content: "֍";
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
font-size: 60px;
transform: rotate(90deg);
margin-left: 2px;
}
.spinner3::after {
animation: rotating 5s linear infinite;
content: "";
height: 30px;
width: 30px;
font-size: 60px;
line-height: 1;
display: inline-block;
font-weight: normal;
border: 1px solid #000;
position: absolute;
left: 50%;
top: 50%;
margin-top: -15px;
margin-left: -15px;
}
<div>
<i class="spinner1"></i>
</div>
<div>
<i class="spinner2"></i>
</div>
<div>
<i class="spinner3"></i>
</div>
if you still want to rotate rectangular shape/icon then along with rotation you have to adjust its position a bit
hope you got my point here
I want to perform some div animation with intervals. In the first time the animation will play, and then it will be delayed, and then (from the second time) there will be an interval. After that, the animation will be played every X seconds.
This is what I got so far, but the animation starts after delay:
#-webkit-keyframes shake {
10%,
90% {
-webkit-transform: translate3d(-1px, 0, 0);
transform: translate3d(-1px, 0, 0);
}
20%,
80% {
-webkit-transform: translate3d(2px, 0, 0);
transform: translate3d(2px, 0, 0);
}
30%,
50%,
70% {
-webkit-transform: translate3d(-4px, 0, 0);
transform: translate3d(-4px, 0, 0);
}
40%,
60% {
-webkit-transform: translate3d(4px, 0, 0);
transform: translate3d(4px, 0, 0);
}
}
#keyframes shake {
10%,
90% {
-webkit-transform: translate3d(-1px, 0, 0);
transform: translate3d(-1px, 0, 0);
}
20%,
80% {
-webkit-transform: translate3d(2px, 0, 0);
transform: translate3d(2px, 0, 0);
}
30%,
50%,
70% {
-webkit-transform: translate3d(-4px, 0, 0);
transform: translate3d(-4px, 0, 0);
}
40%,
60% {
-webkit-transform: translate3d(4px, 0, 0);
transform: translate3d(4px, 0, 0);
}
}
.error-container {
position: absolute;
left: auto;
border-collapse: separate;
margin: 0;
padding: 2px 10px;
list-style: none;
color: #ffffff;
font-size: 12px;
font-weight: 600;
background: #d9534f;
border-top-right-radius: 4px;
border-top-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
display: none;
z-index: 100;
&.active {
display: block;
-webkit-animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both 4s infinite;
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both 4s infinite;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-perspective: 1000px;
perspective: 1000px;
}
}
Is it possible without any JavaScript?Thanks.
Update: here is a demo: [demo][1]
Here you go. What I did is I changed the code so that complete animation ends at 20% and after that it will do nothing till 100%. For more details, visit this link
NOTE: You can clone the webkit to keyframes code as well. I removed it
#-webkit-keyframes shake {
2%,
18% {
-webkit-transform: translate3d(-1px, 0, 0);
transform: translate3d(-1px, 0, 0);
}
4%,
16% {
-webkit-transform: translate3d(2px, 0, 0);
transform: translate3d(2px, 0, 0);
}
6%,
10%,
14% {
-webkit-transform: translate3d(-4px, 0, 0);
transform: translate3d(-4px, 0, 0);
}
8%,
12% {
-webkit-transform: translate3d(4px, 0, 0);
transform: translate3d(4px, 0, 0);
}
100%{
-webkit-transform: translate3d(0px, 0, 0);
transform: translate3d(0px, 0, 0);
}
}
.error-container {
position: absolute;
left: auto;
border-collapse: separate;
margin: 0;
padding: 2px 10px;
list-style: none;
color: #ffffff;
font-size: 12px;
font-weight: 600;
background: #d9534f;
border-top-right-radius: 4px;
border-top-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-left-radius: 4px;
display: none;
z-index: 100;
&.active {
display: block;
animation: shake 4s cubic-bezier(0.36, 0.07, 0.19, 0.97) both infinite;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-perspective: 1000px;
perspective: 1000px;
}
}
You can change iteration on animation-duration
here is example
#import url(https://fonts.googleapis.com/css?family=Montserrat:700,400);
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
background: purple;
font-family: 'Montserrat', sans-serif;
}
html, body {
height: 100%;
}
button {
background: #333;
color: #fff;
border-radius: 40px;
padding: 15px 30px;
border: 0;
overflow: hidden;
width: 200px;
transition:
all 1.2s,
border 0.5s 1.2s,
box-shadow 0.3s 1.5s;
white-space: nowrap;
text-indent: 23px;
font-weight: bold;
}
span {
display: inline-block;
transform: translateX(300px);
font-weight: normal;
opacity: 0;
transition:
opacity 0.1s 0.5s,
transform 0.4s 0.5s;
}
button:hover {
text-indent: 0;
background: #55706D;
color: #FFE8A3;
width: 250px;
}
button:hover span {
transform: translateX(0);
opacity: 1;
}
<button>
Animate
<span>After Delay</span>
</button>
I have the following HTML and CSS code to draw the top of a cube. So it moves down and I want it to animate as if it is opening up. I am unable to figure out how to transform the top so that it appears to open up.
I have included the entire code for the cube. With respect to this, I want the top to open up.
.pers500 {
perspective: 500px;
-webkit-perspective: 500px;
-moz-perspective: 500px;
}
/* Define the container div, the cube div, and a generic face */
.container {
width: 25%;
margin: 0 auto;
margin-top: 2em;
border: none;
animation-name: moveDown;
animation-duration: 2s;
animation-timing-function: linear;
transform: translate(0px, 110px);
}
.cube {
width: 70%;
height: 70%;
backface-visibility: visible;
perspective-origin: 150% 150%;
transform-style: preserve-3d;
-webkit-backface-visibility: visible;
-webkit-perspective-origin: 150% 150%;
-webkit-transform-style: preserve-3d;
}
.face {
display: block;
position: absolute;
border: none;
line-height: 100px;
font-family: sans-serif;
font-size: 60px;
color: white;
text-align: center;
}
/* Define each face based on direction */
.front {
width: 3.64em;
height: 3.43em;
background-color: rgba(0, 255, 0, 0.7);
transform: translateZ(50px) translateX(171px) translateY(222px);
-webkit-transform: translateZ(50px) translateX(171px) translateY(222px);
-moz-transform: translateZ(50px) translateX(171px) translateY(222px);
}
.left {
width: 2em;
height: 3.4em;
background-color: rgba(0, 0, 255, 0.7);
margin: 70px;
transform: skewY(40deg) translateZ(50px);
-webkit-transform: skewY(40deg) translateZ(50px) translateY(65px) translateX(-20px);
-moz-transform: skewY(40deg) translateZ(50px) translateY(62px) translateX(-20px);
}
.top {
width: 3.65em;
height: 1.7em;
background-color: rgba(255, 0, 0, 0.7);
margin: 100px;
transform: skewX(50deg) translateZ(50px) translateX(-14px) translateY(20px);
-webkit-transform: skewX(50deg) translateZ(50px) translateX(-14px) translateY(20px);
;
-moz-transform: skewX(50deg) translateZ(50px) translateX(-14px) translateY(20px);
;
animation-name: openTop;
animation-duration: 2s;
animation-timing-function: linear;
}
#-webkit-keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes openTop {
/*0% {transform:rotateX(30deg);}
50% {transform:rotateX(30deg);}
100% {transform:rotateX(30deg);} commented code here doesn't work*/
}
<div class="container">
<div class="cube pers500">
<div class="face front"></div>
<div class="face top"></div>
<br>
<br>
<br>
<div class="face left"></div>
</div>
</div>
To make the cube open up, you first need to set the transform-origin property (as mentioned in the other answer) to top. This setting would make the top side of the .face.top remain fixed when the rotation is being performed. Then you need to add the rotation using rotateX(). This would rotate the top face to produce the opening effect. Note that the transform property should contain the entire list of transforms for it to open correctly. You cannot just add the rotateX() alone within the animation.
.pers500 {
perspective: 500px;
}
/* Define the container div, the cube div, and a generic face */
.container {
width: 25%;
margin: 0 auto;
margin-top: 2em;
border: none;
animation-name: moveDown;
animation-duration: 2s;
animation-timing-function: linear;
transform: translate(0px, 110px);
}
.cube {
width: 70%;
height: 70%;
backface-visibility: visible;
perspective-origin: 150% 150%;
transform-style: preserve-3d;
}
.face {
display: block;
position: absolute;
border: none;
line-height: 100px;
font-family: sans-serif;
font-size: 60px;
color: white;
text-align: center;
border: 1px solid brown; /* just for testing */
}
/* Define each face based on direction */
.front {
width: 3.64em;
height: 3.43em;
background-color: rgba(0, 255, 0, 0.7);
transform: translateZ(50px) translateX(171px) translateY(222px);
}
.left {
width: 2em;
height: 3.43em;
background-color: rgba(0, 0, 255, 0.7);
margin: 70px;
transform: skewY(40deg) translateZ(50px) translateY(64px) translateX(-20px);
}
.top {
width: 3.65em;
height: 1.69em;
background-color: rgba(255, 0, 0, 0.7);
margin: 100px;
transform: skewX(50deg) translateZ(50px) translateX(-74px) translateY(20px) rotateX(0deg);
transform-origin: top;
animation-name: openTop;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
}
#-webkit-keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes moveDown {
0% {
transform: translate(0px, 10px);
}
50% {
transform: translate(0px, 55px);
}
100% {
transform: translate(0px, 110px);
}
}
#keyframes openTop {
0% {
transform: skewX(50deg) translateZ(50px) translateX(-74px) translateY(20px) rotateX(0deg);
}
100% {
transform: skewX(50deg) translateZ(50px) translateX(-74px) translateY(20px) rotateX(200deg);
}
}
<div class="container">
<div class="cube pers500">
<div class="face front"></div>
<div class="face top"></div>
<br>
<br>
<br>
<div class="face left"></div>
</div>
</div>
Note:
Setting a transform-origin will affect the position of the top face in the demo and so the values that you've used for translateX() and translateY() on the top face need to be modified a bit like in the above demo.
The vendor prefixed versions of properties should always be added before the standard property in order to be future proof.
I have removed the vendor prefixed versions in the above snippet just to keep it simple.
Set the transform origin to tbe edge of the cube with
transform-origin: 0 50% 0;
Then rotate it around the z axis:
transform: rotateZ(90deg);
I hope this works for you, I didn't have the chance to test it.
Specifically the perspective and transform properties are not working in css code provided below. Also, the radio buttons work but they do not link to the correct side of the cube. I can't spot the problem.
$size: 500px; // cube length
body {
text-align: center;
padding: 50px;
}
.scene {
display: inline-block;
margin-top: 50px;
width: 500px;
height: 500px;
-webkit-perspective: 600px;
}
.cube3d {
display: inline-block;
position: 500px;
width: 500px;
height: 500px;
-webkit-transform-style: preserve-3d;
-webkit-transition: transform 0.6s;
}
.cube-face {
width: 500px;
height: 500px;
position: absolute;
background: red;
opacity: 0.8;
}
// faces
.cube-face-front {
background: yellow;
transform: translate3d(0, 0, $size/2);
}
.cube-face-back {
background: black;
transform: rotateY(180deg) translate3d(0, 0, $size/2);
}
.cube-face-left {
background: green;
transform: rotateY(-90deg) translate3d(0, 0, $size/2);
}
.cube-face-right {
background: magenta;
transform: rotateY(90deg) translate3d(0, 0, $size/2);
}
.cube-face-top {
background: blue;
transform: rotateX(90deg) translate3d(0, 0, $size/2);
}
.cube-face-bottom {
background: red;
transform: rotateX(-90deg) translate3d(0, 0, $size/2);
}
// controls
#radio-back:checked ~ .scene .cube {
transform: rotateY(180deg);
}
#radio-left:checked ~ .scene .cube {
transform: rotateY(90deg);
}
#radio-right:checked ~ .scene .cube {
transform: rotateY(-90deg);
}
#radio-top:checked ~ .scene .cube {
transform: rotateX(-90deg);
}
#radio-bottom:checked ~ .scene .cube {
transform: rotateX(90deg);
}