CSS tile flip on hover - javascript

I have some Div Boxes how can i get them flipped on hover? I tried already some examples i found but i cant get it working? Can someone please help me?
.kachel_a_image_1 {
height:150px;
width:150px;
margin:auto auto;
margin-top:15px;
background:red;
}
.kachel_wrapper {
margin: auto auto;
width: 90%;
min-height: 450px;
margin-top: 55px;
text-align: center;
padding:10px;
padding-top:30px;
padding-bottom:20px;
}
.kachel_text {
font-size:10px;
color:white;
line-height:15px;
text-align:center;
}
.kachel {
height: 180px;
width: 180px;
margin-top: 20px;
margin-left: 58px;
background: #6e7176;
display: inline-block;
margin-bottom:30px;
}
<div class="kachel"><div class="kachel_a_image_1"></div><div class="kachel_text">Social</div></div>
I only want to use Css and no JS if its possible. Can someone explain me how this works or giving me a really simple example :S ?

Use transform:
.kachel:hover{
transform: rotateX(150deg);
}
more Information: http://www.w3schools.com/css/css3_3dtransforms.asp
Also if you want to add a duration to the animation use transition-duration
.kachel{
transition-duration: 5s;
}
for changing the content after the hover use the pseudo element :after and the attribute content.
For example:
.kachel:hover:after{
content: 'hovering';
}
You may have to change it a bit, i haven't tested it.

Using transition and backface-visibility.
Probably the best soultion is to use simple transform and backface-visibility. jsfiddle
.front, .back{
width: 100px;
height: 100px;
}
.front{
background-color: blue;
}
.back{
background-color: red;
background-image: url("https://yt3.ggpht.com/-Bvvd30cZJe4/AAAAAAAAAAI/AAAAAAAAAAA/CxN5F1_QEU8/s100-c-k-no/photo.jpg");
background-size: cover;
}
/* entire container, keeps perspective */
.flip-container {
perspective: 1000;
}
/* flip the pane when hovered */
.flip-container:hover .flipper, .flip-container.hover .flipper {
transform: rotateY(180deg);
}
.flip-container, .front, .back {
width: 100px;
height: 100px;
}
/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(0deg);
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
}
<div class="flip-container" ontouchstart="this.classList.toggle('hover');">
<div class="flipper">
<div class="front">
</div>
<div class="back">
</div>
</div>
</div>
Using #-webkit-keyframe
Another approach is to use animation and #-webkit-keyframes. However this will run the animation one time initially. (jsfiddle)
.box, .wrapper {
width: 100px;
height: 100px;
position: absolute;
}
.back {
transform: rotateY(90deg);
background-color: red;
-webkit-animation: in 0.2s forwards;
animation in 1s forwards;
-webkit-animation-delay: 0.2s; /* Chrome, Safari, Opera */
animation-delay: 0.2s;
}
.front {
transform: rotateY(90deg);
background-color: blue;
-webkit-animation: out 0.2s forwards;
animation out 0.2s forwards;
background-image: url("https://yt3.ggpht.com/-Bvvd30cZJe4/AAAAAAAAAAI/AAAAAAAAAAA/CxN5F1_QEU8/s100-c-k-no/photo.jpg");
background-size: cover;
}
.wrapper:hover .box.back {
-webkit-animation: out 0.2s forwards;
animation: out 0.2s forwards;
}
.wrapper:hover .box.front {
-webkit-animation: in 0.2s forwards;
animation: in 0.2s forwards;
-webkit-animation-delay: 0.2s; /* Chrome, Safari, Opera */
animation-delay: 0.2s;
}
#-webkit-keyframes in {
from {
-webkit-transform: rotateY(90deg);
}
to {
-webkit-transform: rotateY(0deg);
}
}
#-webkit-keyframes out {
0% {
-webkit-transform: rotateY(0deg);
}
100% {
-webkit-transform: rotateY(90deg);
}
}
<div class="wrapper">
<div class="box back"></div>
<div class="box front"></div>
</div>

For this I would use backface-visibility in conjunction with transform
<div class="container">
<div class="box front">image</div>
<div class="box back">Social</div>
</div>
CSS:
.container {
width: 180px;
height: 180px;
position: relative;
-webkit-transition: all .4s linear;
transition: all .4s linear;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.box {
position: absolute;
width: 100%;
height: 100%;
text-align: center;
color: white;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.front {
background: red;
z-index: 2;
}
.back {
z-index: 1;
background-color: green;
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
color:white;
}
.container:hover {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
Here's a JS fiddle
EDIT: The above fiddle has been edited to have an outer wrapper which initiates the flip. This ensures that the animation doesn't jitter.
.wrapper {
width: 180px;
}
.wrapper:hover .container {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}

Related

React CSS animation-delay property does not work

just a quick question regarding animated elements in React.js - I have noticed that when trying to make use of the animation-delay property in CSS, that React does not seem to apply this rule at all for some reason.
For example, I am trying to make a basic loading component, which just has a series of basic circles moving about in sequence, the CSS for which is below:
.--loaderContainer {
position: relative;
left: 50%;
top: 50%;
transform: translateX(-50%), translateY(-50%);
width: 4rem;
height: 4rem;
}
.--loaderContainer:nth-child(n) {
width: 1rem;
height: 1rem;
border-radius: 9999px;
margin: 0;
padding: 0;
position: absolute;
animation-name: spin;
animation-duration: 2s;
animation-timing-function: ease;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.--loaderContainer:first-child {
background-color: red;
transform: rotate(270deg);
animation-delay: -1.5s;
}
.--loaderContainer:nth-child(2) {
background-color: blue;
transform: rotate(180deg);
animation-delay: -1s;
}
.--loaderContainer:nth-child(3) {
background-color: green;
transform: rotate(90deg);
animation-delay: -0.5s;
}
.--loaderContainer:nth-child(4) {
background-color: yellow;
}
#keyframes spin {
0%,
100% {
transform: translate(0);
}
25% {
transform: translate(160%);
}
50% {
transform: translate(160%, 160%);
}
75% {
transform: translate(0, 160%);
}
}
As far as I can tell, this should stagger each of the child elements in sequence, performing the same animation but at different times. However, for some reason, React simply plays the animation, with no delay whatsoever and has all four elements animate at the exact same time.
It seems like a really basic issue to be having and while I have looked up a variety of answers, I just can't seem to find any concrete solutions, so would be super appreciative for any help. Thanks!
If all four circles are seen, I think this animation should be working properly.
The negative animation-delay values ensures that four circles start at different points of the animation, rather than putting an actual delay.
More about animation-delay
Without it, they will start at same point and move together while stacking with each other, resulting in only one circle is seen (the last yellow circle since it's on top of stack).
Here is a basic example for testing the effect of animation-delay by toggling it on and off for all the circles, it can run with the "run code snippet" button below.
Hope it will help.
const btn = document.querySelector("button");
const loaders = document.querySelectorAll(".--loaderContainer");
btn.addEventListener("click", () => {
loaders.forEach((loader) => loader.classList.toggle("no-delay"));
btn.textContent = loaders[0].classList.contains("no-delay")
? "turn delay on"
: "turn delay off";
});
.--loaderContainer {
position: relative;
left: 50%;
top: 50%;
transform: translateX(-50%), translateY(-50%);
width: 4rem;
height: 4rem;
}
.--loaderContainer:nth-child(n) {
width: 1rem;
height: 1rem;
border-radius: 9999px;
margin: 0;
padding: 0;
position: absolute;
animation-name: spin;
animation-duration: 2s;
animation-timing-function: ease;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.--loaderContainer:first-child {
background-color: red;
transform: rotate(270deg);
animation-delay: -1.5s;
}
.--loaderContainer:nth-child(2) {
background-color: blue;
transform: rotate(180deg);
animation-delay: -1s;
}
.--loaderContainer:nth-child(3) {
background-color: green;
transform: rotate(90deg);
animation-delay: -0.5s;
}
.--loaderContainer:nth-child(4) {
background-color: yellow;
}
#keyframes spin {
0%,
100% {
transform: translate(0);
}
25% {
transform: translate(160%);
}
50% {
transform: translate(160%, 160%);
}
75% {
transform: translate(0, 160%);
}
}
button {
text-transform: uppercase;
padding: 6px;
}
section {
width: 100px;
height: 100px;
position: relative;
}
div.--loaderContainer.no-delay:nth-child(n) {
animation-delay: 0s;
opacity: 0.8;
}
body {
background-color: #aaa;
}
<button>turn delay off</button>
<section>
<div class="--loaderContainer"></div>
<div class="--loaderContainer"></div>
<div class="--loaderContainer"></div>
<div class="--loaderContainer"></div>
</section>

Is there any way to achieve this functionality without JavaScript in html and css only?

Question Image
I want to achieve such zoom functionality in Html and CSS only because where I want to implement this doesn't supports JavaScript. Is this possible ?
Today all about is JS. But you can do wonderful things in CSS only and ...
Of course YOU CAN DO EXACTLY THAT in vanillaCSS
Here are TWO demonstration examples.
Louping effect on the image itself. That works in fluent layouts and mostover is the chosed solution.
The demonstration for the louping effect you asked for. That is a boxed design with a setup done in css vars. So, if you want to make it repsonsive up to now you need to define the css vars to the different breakpoints. (Head up: the loupe box has to be placed in the container as in the example and is actual shown below the original image. But you are free to position it anywhere else - i.e. by positioning it absolute/fixed/floated ... - as the html structure keeps untouched.)
Notice: more scaling up as it is needed is not a problem to both demonstrations.
html {
font-family: sans-serif;
}
/* zoomBox */
.zoomBox {
position: relative;
width: 400px;
overflow: hidden;
}
.zoomBox * {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.zoomBox img {
position: relative;
width: 100%;
height: auto;
z-index: -1;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover {
position: absolute;
width: 33.333333%;
height: 33.333333%;
}
.zoomBox .hover.TL {
top: 0;
left: 0;
}
.zoomBox .hover.TL:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: top left;
-ms-transform-origin: top left;
transform-origin: top left;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.TC {
top: 0;
left: 33.333333%;
}
.zoomBox .hover.TC:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: top center;
-ms-transform-origin: top center;
transform-origin: top center;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.TR {
top: 0;
right: 0;
}
.zoomBox .hover.TR:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: top right;
-ms-transform-origin: top right;
transform-origin: top right;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.CL {
top: 33.333333%;
left: 0;
}
.zoomBox .hover.CL:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: center left;
-ms-transform-origin: center left;
transform-origin: center left;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.CC {
top: 33.333333%;
left: 33.333333%;
}
.zoomBox .hover.CC:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: center center;
-ms-transform-origin: center center;
transform-origin: center center;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.CR {
top: 33.333333%;
right: 0;
}
.zoomBox .hover.CR:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: center right;
-ms-transform-origin: center right;
transform-origin: center right;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.BL {
bottom: 0;
left: 0;
}
.zoomBox .hover.BL:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: bottom left;
-ms-transform-origin: bottom left;
transform-origin: bottom left;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.BC {
bottom: 0;
left: 33.333333%;
}
.zoomBox .hover.BC:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: bottom center;
-ms-transform-origin: bottom center;
transform-origin: bottom center;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.zoomBox .hover.BR {
bottom: 0;
right: 0;
}
.zoomBox .hover.BR:hover ~ img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: bottom right;
-ms-transform-origin: bottom right;
transform-origin: bottom right;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
/* imageLouping */
.imageLoupingBox {
--imageWidth: 400px;
--aspectRatio: 0.625;
--imageHeight: calc( var(--imageWidth) * var(--aspectRatio) );
--hoverWidth: calc( var(--imageWidth) * 0.33333334);
--hoverHeight: calc( var(--imageHeight) * 0.33333334);
position: relative;
}
.imageLoupingBox * {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.imageLoupingBox img.imageLoupe {
position: relative;
width: var(--imageWidth);
height: var(--imageHeight);
z-index: -1;
}
.imageLoupingBox .loupeBox {
position: relative;
width: var(--imageWidth);
height: var(--imageHeight);
overflow: hidden;
border: 1px solid green;
}
.imageLoupingBox .loupeBox img {
width: 100%;
height: auto;
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
opacity: 0;
-webkit-transition: all 0.1s;
-o-transition: all 0.1s;
transition: all 0.1s;
}
.imageLoupingBox .loupeBox:after {
content: "CSS LOUPE";
display: block;
width: 100%;
height: 12px;
text-align: center;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
z-index: -2;
font-family: sans-serif;
opacity: 1;
-webkit-transition: all 0.05s;
-o-transition: all 0.05s;
transition: all 0.05s;
}
.imageLoupingBox .hover {
position: absolute;
width: var(--hoverWidth);
height: var(--hoverHeight);
}
.imageLoupingBox .hover:hover ~ .loupeBox:after {
opacity: 0;
-webkit-transition: all 0.05s;
-o-transition: all 0.05s;
transition: all 0.05s;
}
.imageLoupingBox .hover:hover ~ .loupeBox img {
opacity: 1;
-webkit-transition: all 0.1s;
-o-transition: all 0.1s;
transition: all 0.1s;
}
.imageLoupingBox .hover.TL {
top: 0;
left: 0;
}
.imageLoupingBox .hover.TL:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: top left;
-ms-transform-origin: top left;
transform-origin: top left;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.TC {
top: 0;
left: var(--hoverWidth);
}
.imageLoupingBox .hover.TC:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: top center;
-ms-transform-origin: top center;
transform-origin: top center;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.TR {
top: 0;
left: calc( var(--hoverWidth) * 2 );
}
.imageLoupingBox .hover.TR:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: top right;
-ms-transform-origin: top right;
transform-origin: top right;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.CL {
top: var(--hoverHeight);
left: 0;
}
.imageLoupingBox .hover.CL:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: center left;
-ms-transform-origin: center left;
transform-origin: center left;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.CC {
top: var(--hoverHeight);
left: var(--hoverWidth);
}
.imageLoupingBox .hover.CC:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: center center;
-ms-transform-origin: center center;
transform-origin: center center;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.CR {
top: var(--hoverHeight);
left: calc( var(--hoverWidth) * 2 );
}
.imageLoupingBox .hover.CR:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: center right;
-ms-transform-origin: center right;
transform-origin: center right;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.BL {
top: calc( var(--hoverHeight) * 2);
left: 0;
}
.imageLoupingBox .hover.BL:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: bottom left;
-ms-transform-origin: bottom left;
transform-origin: bottom left;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.BC {
top: calc( var(--hoverHeight) * 2);
left: var(--hoverWidth);
}
.imageLoupingBox .hover.BC:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: bottom center;
-ms-transform-origin: bottom center;
transform-origin: bottom center;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
.imageLoupingBox .hover.BR {
top: calc( var(--hoverHeight) * 2);
left: calc( var(--hoverWidth) * 2 );
}
.imageLoupingBox .hover.BR:hover ~ .loupeBox img {
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transform-origin: bottom right;
-ms-transform-origin: bottom right;
transform-origin: bottom right;
-webkit-transition: all 1s;
-o-transition: all 1s;
transition: all 1s;
}
<h1>ZOOMING EFFECTS vanillaCSS</h1>
<h2>Zoom box: enlarge image itself</h2>
<div class="zoomBox">
<div class="hover TL"></div>
<div class="hover TC"></div>
<div class="hover TR"></div>
<div class="hover CL"></div>
<div class="hover CC"></div>
<div class="hover CR"></div>
<div class="hover BL"></div>
<div class="hover BC"></div>
<div class="hover BR"></div>
<img src="https://source.unsplash.com/qpemSW6_1Z0">
</div>
<hr>
<h2>Image with a cssLOUPE</h2>
<div class="imageLoupingBox">
<div class="hover TL"></div>
<div class="hover TC"></div>
<div class="hover TR"></div>
<div class="hover CL"></div>
<div class="hover CC"></div>
<div class="hover CR"></div>
<div class="hover BL"></div>
<div class="hover BC"></div>
<div class="hover BR"></div>
<img class="imageLoupe" src="https://source.unsplash.com/qpemSW6_1Z0">
<div class="loupeBox">
<!--<img src="images/demoImage.jpg">-->
<img src="https://source.unsplash.com/qpemSW6_1Z0">
</div>
</div>
Because the zoom responds to a touch or mouse event and uses its position this is not possible without JS, you can however just enlarge the image on hover, also works on mobile.
img.zoomer {
transition: transform 0.3s;
}
img.zoomer:hover {
transform: scale(1.5);
}
/* css below is irrelevant */
body {
margin: 0;
}
.center {
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
}
<div class="center">
<img class="zoomer" src="https://stackoverflow.design/assets/img/logos/so/logo-stackoverflow.png" width="300">
</div>
In order to be able to zoom on hover with an image inserted with <img> without javascript try this.
#imageZoom{
overflow:hidden;
transition: all 1s;
width:200px;
height:200px;
}
#imageZoom img:hover{
transform: scale(1.2);
}
<div id="imageZoom">
<img src="http://duncanlock.net/images/posts/better-figures-images-plugin-for-pelican/dummy-200x200.png">
</div>
Yes, you can get the detail image to show when you hover on the main image. Here's an example:
.main, .detail {
width: 200px;
height: 200px;
}
.main {
background-color: green;
}
img.detail {
display: none;
background-color: brown;
position: absolute;
top: 0;
left: 0;
}
div.container:hover img.detail {
display: block;
}
.container {
width: auto;
height: auto;
}
<div class="container">
<img class="main" src=""/>
<img class="detail" src=""/>
</div>
If you want several bits to have detail then you could have several divs which are positioned at the right places (in terms of % distance left and right of the main image) and when the user hovers over one show its related detail.

How do I get my bouncing hamburger menu to stop bouncing after a certain amount of seconds have passed once the page loads?

I am a noob at web dev and I am teaching myself using different online platforms (YouTube, Udemy, StackSkills, etc.).
Right now I am trying to focus on learning the basics of HTML, CSS, and JavaScript/JQuery.
I created this hamburger menu for a custom site I am working on to help me learn and I wanted to try and get the bouncing hamburger menu to stop after a certain time threshold has passed.
I tried creating a class using JQuery that I could then use the CSS animation-duration property, but it stopped the bounce completely.
This is what I did using JQuery and CSS to try and get the effect I wanted that completely stopped the bounce animation effect rather than having it stopped after 5 seconds:
JQuery
function bounceDuration() {
document.querySelector('.hamburger-menu').classList.toggle('bounce-duration');
};
CSS
.hamburger-menu.bounce-duration {
animation-duration: 5s;
}
Below you will find the current working code I have in its entirety (HTML, CSS, and JQuery). As you can see, the hamburger menu bounces indefinitely and I would like to somehow give it a timeout or duration of some sort. Any assistance with this is greatly appreciated.
function sidebarToggle() {
document.querySelector(".hamburger-menu").addEventListener("click", () => {
document.querySelector('.hamburger-menu').classList.toggle('bounce-stop');
document.querySelector(".container").classList.toggle("sidebar-toggle");
});
}
sidebarToggle()
* {
margin: 0;
padding: 0;
outline: none;
box-sizing: border-box;
list-style: none;
text-decoration: none;
}
.hamburger-menu {
width: 3rem;
height: 3rem;
position: fixed;
top: 5rem;
right: 5rem;
z-index: 200;
display: flex;
flex-direction: column;
justify-content: space-evenly;
cursor: pointer;
transition: 0.7s;
}
.hamburger-menu.bounce-stop {
animation-name: none;
}
.line {
width: 100%;
height: 0.2rem;
background-color: #fff;
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.2);
}
/*
Hamburger Menu Bounce
---------------------
Description: - Up/Down animation
*/
.hamburger-menu {
-moz-animation: bounce 1s infinite alternate;
-o-animation: bounce 1s infinite alternate;
-webkit-animation: bounce 1s infinite alternate;
animation: bounce 1s infinite alternate;
animation-duration: 0.5s;
}
#-moz-keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
#-o-keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
#-webkit-keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
#keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
.sidebar-toggle .hamburger-menu {
right: 33rem;
background-color: #555;
}
.header {
width: 100%;
height: 100vh;
position: relative;
perspective: 100rem;
overflow: hidden;
background-color: rgba(0, 0, 0, .8);
}
.sidebar {
width: 40rem;
height: 100vh;
position: fixed;
top: 0;
right: -40rem;
background-color: #ffffff;
transition: right 0.5s;
}
.sidebar-toggle .sidebar {
right: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<body>
<div class="container">
<div class="hamburger-menu">
<div class="line line-1"></div>
<div class="line line-2"></div>
<div class="line line-3"></div>
</div>
<header class="header"></header>
<section class="sidebar"></section>
</div>
</body>
</html>
Set the iteration count to 2 (or any other number) rather than infinite:
function sidebarToggle() {
document.querySelector(".hamburger-menu").addEventListener("click", () => {
document.querySelector('.hamburger-menu').classList.toggle('bounce-stop');
document.querySelector(".container").classList.toggle("sidebar-toggle");
});
}
sidebarToggle()
* {
margin: 0;
padding: 0;
outline: none;
box-sizing: border-box;
list-style: none;
text-decoration: none;
}
.hamburger-menu {
width: 3rem;
height: 3rem;
position: fixed;
top: 5rem;
right: 5rem;
z-index: 200;
display: flex;
flex-direction: column;
justify-content: space-evenly;
cursor: pointer;
transition: 0.7s;
}
.hamburger-menu.bounce-stop {
animation-name: none;
}
.line {
width: 100%;
height: 0.2rem;
background-color: #fff;
box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.2);
}
/*
Hamburger Menu Bounce
---------------------
Description: - Up/Down animation
*/
.hamburger-menu {
-moz-animation: bounce 1s 2 alternate;
-o-animation: bounce 1s 2 alternate;
-webkit-animation: bounce 1s 2 alternate;
animation: bounce 1s 2 alternate;
animation-duration: 0.5s;
}
#-moz-keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
#-o-keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
#-webkit-keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
#keyframes bounce {
0% {
transform: translateY(0);
}
100% {
transform: translateY(-10px);
}
}
.sidebar-toggle .hamburger-menu {
right: 33rem;
background-color: #555;
}
.header {
width: 100%;
height: 100vh;
position: relative;
perspective: 100rem;
overflow: hidden;
background-color: rgba(0, 0, 0, .8);
}
.sidebar {
width: 40rem;
height: 100vh;
position: fixed;
top: 0;
right: -40rem;
background-color: #ffffff;
transition: right 0.5s;
}
.sidebar-toggle .sidebar {
right: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<body>
<div class="container">
<div class="hamburger-menu">
<div class="line line-1"></div>
<div class="line line-2"></div>
<div class="line line-3"></div>
</div>
<header class="header"></header>
<section class="sidebar"></section>
</div>
</body>
</html>
Just set some digit instead of infinity in animation
.hamburger-menu {
-moz-animation: bounce 1s 5 alternate;
-o-animation: bounce 1s 5 alternate;
-webkit-animation: bounce 1s 5 alternate;
animation: bounce 1s 5 alternate;
animation-duration: 0.5s;
}
it is animation-iteration-count

How to get jQuery to wait until an animation is finished? [duplicate]

This question already has answers here:
How to use jQuery to wait for the end of CSS3 transitions?
(6 answers)
Closed 5 years ago.
I need to wait (prevent) until this animation (flip card) is finished, if you hover again while animation is running it triggers again and restart the animation.
1) I want leave finish the currently animation even you hover again or you hover out. This is what I have tried so far:
if(!$(this).find(".card").is(':animated')){
$(this).find(".card").toggleClass('flipped')
}
And this:
$(":animated").promise().done(function() {
$(this).find(".card").toggleClass('flipped')
});
2) If you re-hover flipped card (blue part) and you leave the cursor inside dont flip it again to the red part while cursor is inside. I tried this canceling setTimeout with clearTimeout but still doesnt work:
$(document).ready(function () {
var funct = 0
$(".container").hover(function () {
clearTimeout(funct);
$(this).find(".card").addClass('flipped')
}, function () {
var val = $(this).find(".card")
var funct = setTimeout(function () {
val.removeClass('flipped')
}, 2000)
})
})
Note: I use setTimeOut function because I need reverse flip card 2 seconds after you hover out and I want keep it.
Here is the working snippet code:
$(document).ready(function () {
$(".container").hover(function(){
$(this).find(".card").toggleClass('flipped')
}, function(){
var val = $(this).find(".card")
setTimeout(function(){
val.toggleClass('flipped')
}, 2000)
})
})
.container {
width: 200px;
height: 260px;
position: relative;
margin: 0 auto 40px;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
display: inline-block;
}
#main {
border: 1px solid black;
}
button {
width: 30%;
height: 10%;
margin-top: 100px;
cursor: default;
}
.card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: right center;
-moz-transform-origin: right center;
-o-transform-origin: right center;
transform-origin: right center;
}
.card.flipped {
-webkit-transform: translateX( -100%) rotateY( -180deg);
-moz-transform: translateX( -100%) rotateY( -180deg);
-o-transform: translateX( -100%) rotateY( -180deg);
transform: translateX( -100%) rotateY( -180deg);
}
.card div {
height: 100%;
width: 100%;
color: white;
text-align: center;
font-weight: bold;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
cursor: pointer;
}
.card .front {
background: red;
display: flex;
justify-content: center;
align-items: center;
}
/*
.card .front p {
margin-top: 100px;
}
*/
.card .back p {
margin: auto;
}
.card .back {
background: blue;
-webkit-transform: rotateY( 180deg);
-moz-transform: rotateY( 180deg);
-o-transform: rotateY( 180deg);
transform: rotateY( 180deg);
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-fluid">
<div id="main"><br>
<section class="container">
<div class="card">
<div class="front"><p>Test</p></div>
<div class="back">
<p>MyBack</p>
</div>
</div>
</section>
</div>
</div>
Run a conditional check first to determine if the trigger class flipped has already been added to the element in question.
This will imply that the animation is still running or currently active (if the class flipped is already present).
if (!$(this).find(".card").hasClass('flipped')) {
$(this).find(".card").toggleClass('flipped')
}
$(document).ready(function() {
$(".container").hover(function() {
if (!$(this).find(".card").hasClass('flipped')) {
$(this).find(".card").toggleClass('flipped')
}
}, function() {
var val = $(this).find(".card")
setTimeout(function() {
val.removeClass('flipped')
}, 1000);
});
});
.container {
width: 200px;
height: 260px;
position: relative;
margin: 0 auto 40px;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
display: inline-block;
}
#main {
border: 1px solid black;
}
button {
width: 30%;
height: 10%;
margin-top: 100px;
cursor: default;
}
.card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: right center;
-moz-transform-origin: right center;
-o-transform-origin: right center;
transform-origin: right center;
}
.card.flipped {
-webkit-transform: translateX( -100%) rotateY( -180deg);
-moz-transform: translateX( -100%) rotateY( -180deg);
-o-transform: translateX( -100%) rotateY( -180deg);
transform: translateX( -100%) rotateY( -180deg);
}
.card div {
height: 100%;
width: 100%;
color: white;
text-align: center;
font-weight: bold;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
cursor: pointer;
}
.card .front {
background: red;
display: flex;
justify-content: center;
align-items: center;
}
/*
.card .front p {
margin-top: 100px;
}
*/
.card .back p {
margin: auto;
}
.card .back {
background: blue;
-webkit-transform: rotateY( 180deg);
-moz-transform: rotateY( 180deg);
-o-transform: rotateY( 180deg);
transform: rotateY( 180deg);
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-fluid">
<div id="main"><br>
<section class="container">
<div class="card">
<div class="front">
<p>Test</p>
</div>
<div class="back">
<p>MyBack</p>
</div>
</div>
</section>
</div>
</div>
Then replace the .toggleClass() method with the .removeClass() method in your setTimeout() function for better "fool-proofing" and more reliable application during intended events - so that this class is never unintentionally added when it should simply be removed.
Edit
To address the issue you've pointed out in the comments, see what the embedded code snippet below demonstrates.
Essentially, a class is added as a flag to check against during specific events at specific times.
$(document).ready(function() {
$('.container').hover(function() {
if (!$(this).find('.card').hasClass('flipped')) {
$(this).find('.card').toggleClass('flipped')
}
$(this).find('.card').addClass('hovered'); /* add class - this will be our flag we'll check against */
}, function() {
var val = $(this).find('.card');
$(this).find('.card').removeClass('hovered'); /* remove class - if we refrain from hovering over again, the condition block below will return true and run the code within */
setTimeout(function() {
if(!val.hasClass('hovered')) {
val.removeClass('flipped')
}
}, 1000);
});
});
.container {
width: 200px;
height: 260px;
position: relative;
margin: 0 auto 40px;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
display: inline-block;
}
#main {
border: 1px solid black;
}
button {
width: 30%;
height: 10%;
margin-top: 100px;
cursor: default;
}
.card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: right center;
-moz-transform-origin: right center;
-o-transform-origin: right center;
transform-origin: right center;
}
.card.flipped {
-webkit-transform: translateX( -100%) rotateY( -180deg);
-moz-transform: translateX( -100%) rotateY( -180deg);
-o-transform: translateX( -100%) rotateY( -180deg);
transform: translateX( -100%) rotateY( -180deg);
}
.card div {
height: 100%;
width: 100%;
color: white;
text-align: center;
font-weight: bold;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
cursor: pointer;
}
.card .front {
background: red;
display: flex;
justify-content: center;
align-items: center;
}
/*
.card .front p {
margin-top: 100px;
}
*/
.card .back p {
margin: auto;
}
.card .back {
background: blue;
-webkit-transform: rotateY( 180deg);
-moz-transform: rotateY( 180deg);
-o-transform: rotateY( 180deg);
transform: rotateY( 180deg);
display: flex;
justify-content: center;
align-items: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-fluid">
<div id="main"><br>
<section class="container">
<div class="card">
<div class="front">
<p>Test</p>
</div>
<div class="back">
<p>MyBack</p>
</div>
</div>
</section>
</div>
</div>

Divs are not flipping on IE

Pre-story: I am using CSS and jQuery to create a flipping effect.
How I am achieving it: For that purpose I am using preserve-3d.
Good news: It works all fine on all major browsers
Problem: It does not work in IE.
Solution approach: Initially I thought it is not applying the preserve but then I think it is just not firing the back element.
Help: Can you please help, link to my JSFiddle
function flip() {
$('.card').toggleClass('flipped');
}
.container {
width: 200px;
height: 260px;
position: relative;
border: 1px solid #ccc;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
}
.card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: 50% 50%;
}
.card div {
display: block;
height: 100%;
width: 100%;
line-height: 260px;
color: white;
text-align: center;
font-weight: bold;
font-size: 140px;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.card .front {
background: red;
}
.card .back {
background: blue;
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
transform: rotateY(180deg);
}
.card.flipped {
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
transform: rotateY(180deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="flip()">flip the card</button>
<section class="container">
<div class="card" onclick="flip()">
<div class="front">1</div>
<div class="back">2</div>
</div>
</section>
As described in the remarks it's a compatibility issue with IE.
I suggest a simple workaround, hoping it could help:
var ua = window.navigator.userAgent;
var msie = (ua.indexOf("MSIE ") > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) ? true : false;
var i = 0;
function flip() {
$('.card').toggleClass('flipped')
if (msie) {
// the timeout happens after 400ms because on my computer this create the right effect
i = (i + 1) % 2;
setTimeout(function (i) {
$('.card > div:eq(' + i + ')').css('backface-visibility', 'visible');
$('.card > div:not(:eq(' + i + '))').css('backface-visibility', 'hidden');
}, 400, i);
}
}
.container {
width: 200px;
height: 260px;
position: relative;
border: 1px solid #ccc;
-webkit-perspective: 800px;
-moz-perspective: 800px;
-o-perspective: 800px;
perspective: 800px;
}
.card {
width: 100%;
height: 100%;
position: absolute;
-webkit-transition: -webkit-transform 1s;
-moz-transition: -moz-transform 1s;
-o-transition: -o-transform 1s;
transition: transform 1s;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform-origin: 50% 50%;
}
.card div {
display: block;
height: 100%;
width: 100%;
line-height: 260px;
color: white;
text-align: center;
font-weight: bold;
font-size: 140px;
position: absolute;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.card .front {
background: red;
}
.card .back {
background: blue;
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
transform: rotateY(180deg);
}
.card.flipped {
-webkit-transform: rotateY(180deg);
-moz-transform: rotateY(180deg);
-o-transform: rotateY(180deg);
transform: rotateY(180deg);
}
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<button onclick="flip()">flip the card</button>
<section class="container">
<div class="card" onclick="flip()">
<div class="front">1</div>
<div class="back">2</div>
</div>
</section>

Categories