Trigger css class onclick with javascript - javascript

this question is newbie but i'm stuck in this thing. I hope someone can help me.
I have this code:
HTML:
<div class='zone11'>
<div class='book11'>
<div class='cover11'></div>
<div class='page11'></div>
<div class='page11'></div>
<div class='page11'></div>
<div class='page11'></div>
<div class='page11'></div>
<div class='last-page11'></div>
<div class='back-cover11'></div>
</div>
</div>
CSS:
.zone11{
height: 700px;
display: flex;
align-items: center;
justify-content: center;
perspective: 1000px;
}
.book11{
display: flex;
align-items: center;
cursor: pointer;
}
.book11:hover .cover11{
transform: rotateX(10deg) rotateY(-180deg);
}
.book11:hover .page11{
transform: rotateX(10deg) rotateY(-180deg);
z-index: 2;
}
.cover11{
z-index: 1;
transition: all 3.5s;
}
.back-cover11{
z-index: -3;
}
.cover11, .back-cover11{
height: 450px;
width: 360px;
background: #3f0035;
border-radius: 2px 20px 20px 2px;
position: absolute;
box-shadow: 1px 1px 10px gray;
transform: rotateX(10deg);
transform-origin: center left;
}
.page11{
height: 430px;
width: 350px;
background: white;
position: absolute;
border-radius: 2px 10px 10px 2px;
transform: rotateX(10deg);
transform-origin: center left;
z-index: -1;
}
.last-page11{
height: 430px;
width: 350px;
background: white;
position: absolute;
border-radius: 2px 10px 10px 2px;
transform: rotateX(10deg);
transform-origin: center left;
z-index: -2;
}
.page11:nth-child(2){
transition-duration: 3s;
}
.page11:nth-child(3){
transition-duration: 2.6s;
}
.page11:nth-child(4){
transition-duration: 2.2s;
}
.page11:nth-child(5){
transition-duration: 1.8s;
}
.page11:nth-child(6){
transition-duration: 1.4s;
}
.book11:hover .page11:nth-child(2){
transition-duration: 6s;
}
.book11:hover .page11:nth-child(3){
transition-duration: 5.6s;
}
.book11:hover .page11:nth-child(4){
transition-duration: 5.2s;
}
.book11:hover .page11:nth-child(5){
transition-duration: 4.8s;
}
.book11:hover .page11:nth-child(6){
transition-duration: 4.4s;
}
Now, this way I have an animation of a book that when you hover, it opens to one page (with 5 pages scrolling before you get there). I want to remove the hover and make sure that it opens and closes on click.
I removed the hover from the classes. For example the cover:
.cover11__open{
transform: rotateX(10deg) rotateY(-180deg);
}
And then in the javascript:
var cover11 = document.querySelector('.cover11');
var book11= document.querySelector('.book11');
book11.addEventListener( 'click', function() {
cover11.classList.toggle('cover11__open');
});
The latter thing has worked on other occasions but it doesn't work here. I also tried something else found on the internet but nothing. Thanks.

You can try adding this to your css:
.book11 .cover11__open {
transform: rotateX(10deg) rotateY(-180deg);
}
.book11__open .page11 {
transform: rotateX(10deg) rotateY(-180deg);
z-index: 2;
}
.book11__open .page11:nth-child(2) {
transition-duration: 6s;
}
.book11__open .page11:nth-child(3) {
transition-duration: 5.6s;
}
.book11__open .page11:nth-child(4) {
transition-duration: 5.2s;
}
.book11__open .page11:nth-child(5) {
transition-duration: 4.8s;
}
.book11__open .page11:nth-child(6) {
transition-duration: 4.4s;
}
and keep every hover removes/commented there is no need for it
and add this too in the javascript instead of the current onclick
book11.addEventListener( 'click', function() {
cover11.classList.toggle('cover11__open');
book11.classList.toggle('book11__open')//this is the added line.
});
basically I just added the classes .cover11__open and .book11__open to the css with the properties given to the hover. now when clicking on the cover these two classes get added/removed. and great animation btw.

Related

How to hide the scroll indicator on scroll?

Dear people of the Internet,
I have this css & html code to add an scroll indicator to my landing page.
My goal is; As soon as you scroll down, the indicator disappears and only appears again after reloading the page.
My jquery seems not to work, any help much appreciated!
$(window).scroll(function() {
if ($(this).scrollTop()>0)
{
$('.scrolli').fadeOut();
}
});
body{
margin: 0;
padding: 0;
background: #000;
}
.scrolli{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.scrolli span{
display: block;
width: 20px;
height: 20px;
border-bottom: 1px solid #FFF;
border-right: 1px solid #FFF;
transform: rotate(45deg);
margin: -10px;
animation: animate 2s infinite;
}
.scrolli span:nth-child(2){
animation-delay: -0.2s;
}
.scrolli span:nth-child(3){
animation-delay: -0.4s;
}
#keyframes animate{
0%{
opacity: 0;
transform: rotate(45deg) translate(-20px,-20px);
}
50%{
opacity: 1;
}
100%{
opacity: 0;
transform: rotate(45deg) translate(20px,20px);
}
}
<div class="scrolli">
<span></span>
<span></span>
<span></span>
</div>
Your code is fine, it doesn't work because there isn't any available scroll, so $(this).scrollTop() can't ever be greater than zero.
You can see it working by making the body taller:
$(window).scroll(function() {
if ($(this).scrollTop()>0)
{
$('.scrolli').fadeOut();
}
});
body{
margin: 0;
padding: 0;
background: #000;
height: 200vh;
}
.scrolli{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
.scrolli span{
display: block;
width: 20px;
height: 20px;
border-bottom: 1px solid #FFF;
border-right: 1px solid #FFF;
transform: rotate(45deg);
margin: -10px;
animation: animate 2s infinite;
}
.scrolli span:nth-child(2){
animation-delay: -0.2s;
}
.scrolli span:nth-child(3){
animation-delay: -0.4s;
}
#keyframes animate{
0%{
opacity: 0;
transform: rotate(45deg) translate(-20px,-20px);
}
50%{
opacity: 1;
}
100%{
opacity: 0;
transform: rotate(45deg) translate(20px,20px);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="scrolli">
<span></span>
<span></span>
<span></span>
</div>

div onclick does not fire (css-animated arrow, possible div size/overlaying issue)

I am using an animated arrow with the following code:
function startDownload() {
alert("Hi");
}
.arrow {
cursor: pointer;
height: 120px;
position: relative;
transition: transform 0.1s;
width: 80px;
/*display: inline-block;*/
}
.arrow-top, .arrow-bottom {
background-color: #666;
height: 4px;
left: -5px;
position: absolute;
top: 50%;
width: 100%;
}
.arrow-top:after, .arrow-bottom:after {
background-color: #fff;
content: '';
height: 100%;
position: absolute;
top: 0;
transition: all 0.15s;
}
.arrow-top {
transform: rotate(45deg);
transform-origin: bottom right;
}
.arrow-top:after {
left: 100%;
right: 0;
transition-delay: 0s;
}
.arrow-bottom {
transform: rotate(-45deg);
transform-origin: top right;
}
.arrow-bottom:after {
left: 0;
right: 100%;
transition-delay: 0.15s;
}
.arrow:hover .arrow-top:after {
left: 0;
transition-delay: 0.15s;
}
.arrow:hover .arrow-bottom:after {
right: 0;
transition-delay: 0s;
}
.arrow:active {
transform: translateX(-50%) translateY(-50%) scale(0.9);
}
<style type="text/css">
body {
background-color: black;
/*background-color: #2B2A3F;*/
}
</style>
<div class="arrow" id="start-arrow" onclick="startDownload()" style="z-index: 10;">
<div class="arrow-top" style="border:1px solid black; z-index: 9;"></div>
<div class="arrow-bottom" style="border:1px solid black; z-index: 9;"></div>
</div>
The issue is that when I click on the two arrow lines, the onclick() does not work. It works only if I click in the surrounding area of the two lines, that is enclosed by the border of the parent div with id start-arrow.
The desired behavior is for the onclick to work in the entire area enclosed by the start-arrow div.
I tried using z-index to make the start-arrow div be on top, but it's not working. I tried messing with display and also with position of the elements in CSS but no luck as well. However I should mention that I'm looking for a solution that does not include changing the position attributes of the elements.
How can I make the onclick fire regardless of where I click in the start-arrow div area?
EDIT: it seems to be working a lot better inside Stack Overflow, why? However if a click on top of the border of each line, it doesn't always work. I am opening mine (exact same code) in Firefox (it doesn't work inside my asp.net either).
Why don't we simply wrap the elements into another parent element and bind the event on that? I am able to solve it using a parent element ('parent-id').
function startDownload() {
alert("Hi");
}
.arrow {
cursor: pointer;
height: 120px;
position: relative;
transition: transform 0.1s;
width: 80px;
/*display: inline-block;*/
}
.arrow-top, .arrow-bottom {
background-color: #666;
height: 4px;
left: -5px;
position: absolute;
top: 50%;
width: 100%;
}
.arrow-top:after, .arrow-bottom:after {
background-color: #fff;
content: '';
height: 100%;
position: absolute;
top: 0;
transition: all 0.15s;
}
.arrow-top {
transform: rotate(45deg);
transform-origin: bottom right;
}
.arrow-top:after {
left: 100%;
right: 0;
transition-delay: 0s;
}
.arrow-bottom {
transform: rotate(-45deg);
transform-origin: top right;
}
.arrow-bottom:after {
left: 0;
right: 100%;
transition-delay: 0.15s;
}
.arrow:hover .arrow-top:after {
left: 0;
transition-delay: 0.15s;
}
.arrow:hover .arrow-bottom:after {
right: 0;
transition-delay: 0s;
}
.arrow:active {
transform: translateX(-50%) translateY(-50%) scale(0.9);
}
<style type="text/css">
body {
background-color: black;
/*background-color: #2B2A3F;*/
}
</style>
<div id="parent-id" onclick="startDownload()">
<div class="arrow" id="start-arrow" style="z-
index: 10;">
<div class="arrow-top" style="border:1px solid black; z-index: 9;"></div>
<div class="arrow-bottom" style="border:1px solid black; z-index: 9;"></div>
</div>
</div>
let parent = document.getElementById("start-arrow");
for(let element of parent.children){
element.addEventListener("click", startDownload)
}
function startDownload() {
alert("Hi");
}
.arrow {
cursor: pointer;
height: 120px;
position: relative;
transition: transform 0.1s;
width: 80px;
/*display: inline-block;*/
}
.arrow-top, .arrow-bottom {
background-color: #666;
height: 4px;
left: -5px;
position: absolute;
top: 50%;
width: 100%;
}
.arrow-top:after, .arrow-bottom:after {
background-color: #fff;
content: '';
height: 100%;
position: absolute;
top: 0;
transition: all 0.15s;
}
.arrow-top {
transform: rotate(45deg);
transform-origin: bottom right;
}
.arrow-top:after {
left: 100%;
right: 0;
transition-delay: 0s;
}
.arrow-bottom {
transform: rotate(-45deg);
transform-origin: top right;
}
.arrow-bottom:after {
left: 0;
right: 100%;
transition-delay: 0.15s;
}
.arrow:hover .arrow-top:after {
left: 0;
transition-delay: 0.15s;
}
.arrow:hover .arrow-bottom:after {
right: 0;
transition-delay: 0s;
}
.arrow:active {
transform: translateX(-50%) translateY(-50%) scale(0.9);
}
<style type="text/css">
body {
background-color: black;
/*background-color: #2B2A3F;*/
}
</style>
<div class="arrow" id="start-arrow" onclick="startDownload()" style="z-index: 10;">
<div class="arrow-top" style="border:1px solid black; z-index: 9;"></div>
<div class="arrow-bottom" style="border:1px solid black; z-index: 9;"></div>
</div>
This is not the most optimize solution, but it should do the trick, other solution is to increase click box by adding it padding.
let parent = document.getElementById("filterInput");
for(let element of parent.children){
element.addEventListener("click", startDownload)
}
The problem is you're attaching a click event listener. That means if you want it to fire, the element needs to be clicked & released.
If you click on your element, it moves to the upper-left. Now if you're slow enough the element isn't below your mouse pointer anymore, thus the click event won't fire because you released the mouse somewhere below.
So simply replace
onclick="startDownload()"
by
onmousedown="startDownload()"
and make sure you don't have an alert dialog in the callback function since it would stop the movement of your arrow. Simply trace something using console.log("fired");
Do it with jquery. Use the id start-arrow
<div class="arrow" id="start-arrow" onclick="startDownload()" style="z-index: 10;">
<div class="arrow-top" style="border:1px solid black; z-index: 9;"></div>
<div class="arrow-bottom" style="border:1px solid black; z-index: 9;"></div>
</div>
Try this:
$(document).on('click','#start-arrow',function(){
alert('Hi');
});

Nextjs React SSR with styled-jsx - Cannot read property 'state' of undefined

I have stumbled upon a problem which I cannot seem to resolve. I tried to search here for the solution but was unable to help myself. I am a newbie in javascript and react so be considerate.
Problem:
I am using React (16.5.0) with nextjs (6.1.2) with styled-jsx like so:
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import Link from 'next/link';
class ProductCard extends Component {
constructor(props) {
super(props);
this.state = {imgLoaded: false};
this.imgHasLoaded = this.imgHasLoaded.bind(this);
}
imgHasLoaded() {
this.setState({imgLoaded:true})
}
render() {
return (
<div className="thumbnail-container">
<div className="loader-box">
<img src={require("../static/loading.png")} className="loading-img" />
</div>
<img src={this.props.imgSrc} className="main-img" onLoad={this.imgHasLoaded} />
<div className="thumbnail-text">
{this.props.text}
</div>
<ul className="item-list">
{this.props.links.map(link =>
<li className="item">
<span className="item-span"> {link.text} </span>
{link.subLinks &&
<ul className="sub-item-list">
{link.subLinks.map(subLink => <li>{subLink.text}</li>)}
</ul>
}
</li>
)}
</ul>
<style jsx> {`
.thumbnail-container {
user-select: none;
position: relative;
text-align: center;
width: 98%;
height: 98%;
margin: 1%;
display: block;
border: 0.3px solid black;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 0 20px 0px rgba(0, 0, 0, 0.5);
overflow: hidden;
align-items: center;
}
.thumbnail-text {
position: absolute;
width: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #ffffff;
font-size: 1.8em;
background-color: #333;
padding: 5px;
border-radius: 5px;
text-shadow: 1px 1px #000000;
text-transform: uppercase;
box-shadow: 0 5px 10px 0px rgba(0, 0, 0, 1);
transition: all 0.2s ease;
}
.thumbnail-container:hover .thumbnail-text, .thumbnail-container:focus .thumbnail-text, .thumbnail-container:active .thumbnail-text {
top: 0;
transform: translate(-50%, 0);
background-color: rgba(255, 124, 4, 0.9);
color: #000000;
text-shadow: none;
}
.main-img {
width: 100%;
height: 100%;
border-radius: 8px;
margin: auto;
-webkit-filter: grayscale(40%) contrast(120%) brightness(110%) saturate(120%);
-moz-filter: grayscale(40%) contrast(120%) brightness(110%) saturate(120%);
filter: grayscale(40%) contrast(120%) brightness(110%) saturate(120%);
opacity: ${this.state.imgLoaded ? 1 : 0};
}
.thumbnail-container:hover .main-img, .thumbnail-container:focus .main-img, .thumbnail-container:active .main-img{
-webkit-filter: grayscale(40%) contrast(120%) saturate(120%) brightness(30%);
-moz-filter: grayscale(40%) contrast(120%) saturate(120%) brightness(30%);
filter: grayscale(40%) contrast(120%) saturate(120%) brightness(30%);
}
.item-list {
display: none;
position: absolute;
bottom: 0;
left: 0;
height: calc(100% - 2em);
flex-flow: column wrap;
justify-content: space-around;
list-style-type: none;
}
.thumbnail-container:hover .item-list, .thumbnail-container:focus .item-list, .thumbnail-container:active .item-list{
display: flex;
}
.item {
font-size: 1.3em;
display: flex;
flex-flow: column wrap;
}
.item-span {
padding-left: 8px;
border-bottom: solid #ff7c04;
border-left: solid #ff7c04;
transition: border-bottom 0.2s ease;
}
.item:hover .item-span, .item:focus .item-span, .item:active .item-span{
border-bottom: none;
}
.sub-item-list {
margin-left: 8px;
margin-top: 8px;
border-bottom: solid #ff7c04;
border-left: solid #ff7c04;
height: auto;
flex: 0;
overflow: hidden;
transition: flex 0.2s ease;
}
.item:hover .sub-item-list, .item:focus .sub-item-list, .item:active .sub-item-list{
flex: 1;
}
.loader-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 48px;
height: 48px;
}
.loading-img {
-webkit-animation: rotate-scale-up 1s linear infinite both;
animation: rotate-scale-up 1s linear infinite both;
}
#-webkit-keyframes rotate-scale-up {
0% {
-webkit-transform: scale(1) rotateZ(0);
transform: scale(1) rotateZ(0);
}
50% {
-webkit-transform: scale(1.5) rotateZ(180deg);
transform: scale(1.5) rotateZ(180deg);
}
100% {
-webkit-transform: scale(1) rotateZ(360deg);
transform: scale(1) rotateZ(360deg);
}
}
#keyframes rotate-scale-up {
0% {
-webkit-transform: scale(1) rotateZ(0);
transform: scale(1) rotateZ(0);
}
50% {
-webkit-transform: scale(1.5) rotateZ(180deg);
transform: scale(1.5) rotateZ(180deg);
}
100% {
-webkit-transform: scale(1) rotateZ(360deg);
transform: scale(1) rotateZ(360deg);
}
}
a {
text-decoration: none;
}
#media only screen and (max-width: 700px) {
.thumbnail-container {
width: 96%;
height: 96%;
margin: 2%;
}
.thumbnail-text {
height: 1.5em;
font-size: 1em !important;
}
.item-list {
height: calc(100% - 3em) !important;
}
}
`}
</style>
</div>
);
}
}
However when using code above I get
Cannot read property 'state' of undefined
error in render function at line 26 (where item-list begins). The problem has something to do with using
opacity: ${this.state.imgLoaded ? 1 : 0};
in styled-jsx, because without this line, code works well.
Interestingly if I remove the item-list and its contents everything is working even with
opacity: ${this.state.imgLoaded ? 1 : 0};
I am sorry if this is something trivial or/and i forgot something fundamental. Just push me in the correct direction please
ok i found out that my problem was related to styled jsx issue described here:
https://github.com/zeit/styled-jsx/issues/486
temporary workaround is to pull the imgLoaded into var and then use it in styled jsx.
Similar example here : https://github.com/zeit/next.js/issues/5735

how can i animate the elements in the nav bar like this : https://riot.design/en/? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
hey there im trying to do something like the effect on the nav bar here:
https://riot.design/en/
this is the closest I got, pls help
.button_sliding_bg {
color: #31302B;
background: #FFF;
padding: 12px 17px;
margin: 25px;
font-family: 'OpenSansBold', sans-serif;
border: 3px solid #31302B;
font-size: 14px;
font-weight: bold;
letter-spacing: 1px;
text-transform: uppercase;
border-radius: 2px;
display: inline-block;
text-align: center;
cursor: pointer;
box-shadow: inset 0 0 0 0 #31302B;
-webkit-transition: all ease 0.8s;
-moz-transition: all ease 0.8s;
transition: all ease 0.8s;
}
.button_sliding_bg:hover {
box-shadow: inset 0 100px 0 0 #31302B;
color: #FFF;
}
<div class="button_sliding_bg">HELLOW</div>
$(".div1").on("mouseover",function(){
var $this=$(this).parent();
$this.find(".div2").slideDown("fast");
$this.find(".div1").slideUp("fast");
});
$(".div2").on("mouseleave",function(){
var $this=$(this).parent();
$this.find(".div1").slideDown("fast");
$this.find(".div2").slideUp("fast");
});
body{
background-color:#0C2663;
}
.element{
float:left;
width:65px;
margin:0 10px;
}
.element div{
width:60px;
margin-top:5px;
cursor:pointer;
padding:5px;
text-align:center;
}
.element div:last-child{
background-color:#fff;
color:#0C2663;
display:none;
}
.element div:first-child{
color:#fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="element">
<div class="div1">Home</div>
<div class="div2">Home</div>
</div>
<div class="element">
<div class="div1">About</div>
<div class="div2">About</div>
</div>
<div class="element">
<div class="div1">Portfolio</div>
<div class="div2">Portfolio</div>
</div>
<br>
This should work for you. The concept relies on the CSS transform: translate and transform: rotate properties to create the flipping cube effect.
Hope this helps!
body {
padding-top: 20px;
background: #0B1F5C;
color: white;
text-transform: uppercase;
font-family: sans-serif;
font-size: 20px;
-webkit-perspective: 1000px;
}
.flip-box {
-webkit-transition: -webkit-transform .5s;
transition: transform .5s;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
width: 30%;
text-align: center;
margin: 0 auto;
height: 100px;
}
.flip-box:hover {
-webkit-transform: rotateX(90deg);
transform: rotateX(90deg);
}
.face1,
.face2 {
background: #0B1F5C;
border: 1px solid #0B1F5C;
height: 100px;
}
.face1 {
-webkit-transform: translateZ(100px);
transform: translateZ(100px);
}
.face2 {
-webkit-transform: rotateX(-90deg) translateZ(-100px);
transform: rotateX(-90deg) translateZ(-100px);
font-size: 25px;
background: white;
color: #0B1F5C;
}
<div class="flip-box">
<div class="face1">
<h1>Home</h1>
</div>
<div class="face2">
<h2>Home</h2>
</div>
</div>
i used chrome inspector on the link that you mentioned and created this for you. please ask questions that its answer could help other people too.
notice that beside the css3 transforms the trick is in
.roll span:after
that the content of data-title attribute of the hovered element will be fetched and applied to the content property:
.roll span:after {
content: attr(data-title);
}
<span data-title="Home">Home</span>
body{
background-color:grey;
}
.navbar .navbar-inner {
margin-top: 80px;
}
.navbar .nav {
float: right;
margin-right: 0;
}
.navbar .nav li {
display: inline-block;
float: none;
overflow: hidden;
transform: translate3d(0,0,0);
}
.navbar-nav>li>a {
padding-top: 13px;
padding-bottom: 7px;
}
.navbar .nav li:last-child a {
padding-right: 0;
}
.lt-ie8 .navbar .nav li {
display: block;
float: left;
}
.roll {
display: inline-block;
overflow: hidden;
z-index: 200;
position: relative;
vertical-align: top;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-webkit-perspective: 400px;
-moz-perspective: 400px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
}
.roll span {
display: block;
position: relative;
padding: 0 2px;
-webkit-transition: all 400ms ease;
-moz-transition: all 400ms ease;
pointer-events: none;
-webkit-pointer-events: none;
-webkit-transform-origin: 50% 0%;
-moz-transform-origin: 50% 0%;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
overflow: hidden;
height: 18px;
}
a.roll:hover span {
overflow: visible;
-webkit-transform: translate3d( 0px, 0px, -30px ) rotateX( 90deg );
-moz-transform: translate3d( 0px, 0px, -30px ) rotateX( 90deg );
}
.roll span:after {
content: attr(data-title);
display: block;
position: absolute;
left: 0;
top: 1px;
padding: 0 2px;
color: #323C46;
background: #fff;
-webkit-transform-origin: 50% 0%;
-moz-transform-origin: 50% 0%;
-webkit-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
-moz-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
}
<body>
<div class="navbar">
<ul id="menu-primary-navigation-en" class="nav navbar-nav">
<li class="active menu-home">
<span data-title="Home">Home</span>
</li>
<li class="menu-about">
<span data-title="About">About</span>
</li>
<li class="menu-portfolio">
<span data-title="Portfolio">Portfolio</span>
</li>
<li class="menu-contacts">
<span data-title="Contacts">Contacts</span>
</li>
</ul>
</div>
</body>

Multiple CSS animations: How to avoid re-triggering one of them?

I am trying to build an animated menu for mobile apps similar to Pinterest's radial menu. I have managed to get the behaviour to where I want it except for one minor detail: when the menu opens, the items shoot out as I want them to, and when you hover on them, they transform as I want them to. problem is, after the cursor leaves the items, they re-trigger their original animation, instead of just returning to their previous state. I realise this is a problem to do with the class being used for the animation and I have tried a number of solutions, including deleting the class and adding a new one .onmouseover() and changing animation running state on hover/mousover. I am probably missing something simple and idiotic, but I just cannot see it. can anybody help?
The following code is just the way I had it before trying to implement solutions.
HTML:
<!--Footer-->
<div class="footer">
<!--RADIAL NAV MENU-->
<div id="navContainer">
<!--Buttons-->
<div id="workouts" class="sml smlOne">Go there</div>
<div id="home" class="sml smlTwo">Go here</div>
<div id="profile" class="sml smlThree">Go somewhere</div>
<!--Burger-->
<div class="burger-menu">
<div id="top" class="bar barTop"></div>
<div id="middle" class="bar barMid"></div>
<div id="bottom" class="bar barBot"></div>
</div>
</div>
</div>
CSS:
.footer
{
position: fixed;
bottom: 0%;
width: 100%;
height: 50px;
background-color: #d36363;
box-shadow: 0px -6px 6px #888888;
z-index: +2;
}
/* Burger menu section */
#navContainer
{
text-align: center;
font-size: 10px;
}
.burger-menu
{
position: relative;
margin: auto;
height: 100%;
width: 50px;
}
.bar
{
height: 6px;
width: 100%;
background-color: white;
}
#top
{
position: relative;
top: 5px;
}
#middle
{
position: relative;
top: 15px;
}
#bottom
{
position: relative;
top: 25px;
}
.barTop, .barMid, .barBot
{
-webkit-transition: all 0.1s ease;
-moz-transition: all 0.1s ease;
-o-transition: all 0.1s ease;
-ms-transition: all 0.1s ease;
transition: all 0.1s ease;
}
.barTopOn
{
transform: rotate(45deg) translateY(12px) translateX(11px);
}
.barMidOn
{
opacity: 0;
}
.barBotOn
{
transform: rotate(-45deg) translateY(-12px) translateX(11px);
}
/* Navigation buttons section */
#navContainer
{
position: relative;
margin: auto;
width: 50px;
}
.sml
{
border: 2px solid #58a7dd;
height: 50px;
width: 50px;
border-radius: 50%;
background-color: white;
box-shadow: 6px 6px 6px #888888;
transform: scale(0);
}
#workouts
{
position: absolute;
bottom: 10px;
left: -60px;
}
#home
{
position: absolute;
bottom: 50px;
}
#profile
{
position: absolute;
bottom: 10px;
left: 60px;
}
.smlOnOne
{
animation: pop, slideOne 0.1s ease-in;
animation-fill-mode: forwards;
}
.smlOnTwo
{
animation: pop, slideTwo 0.1s ease-in;
animation-fill-mode: forwards;
}
.smlOnThree
{
animation: pop, slideThree 0.1s ease-in;
animation-fill-mode: forwards;
}
.smlOnOne:hover
{
background-color: red;
border: none;
box-shadow: 6px 10px 18px #686868;
animation: whopL 0.2s;
animation-fill-mode: forwards;
}
.smlOnTwo:hover
{
background-color: red;
border: none;
box-shadow: 6px 10px 18px #686868;
animation: whopC 0.2s;
animation-fill-mode: forwards;
}
.smlOnThree:hover
{
background-color: red;
border: none;
box-shadow: 6px 10px 18px #686868;
animation: whopR 0.2s;
animation-fill-mode: forwards;
}
#keyframes pop
{
100%
{
transform: scale(1,1);
}
}
#keyframes slideOne
{
0%
{
bottom: -20px;
left: 0px;
}
100%
{
bottom: 10px;
left: -60px;
}
}
#keyframes slideTwo
{
0%
{
bottom: -20px;
}
100%
{
bottom: 50px;
}
}
#keyframes slideThree
{
0%
{
bottom: -20px;
left: 0px;
}
100%
{
bottom: 10px;
left: 60px;
}
}
#keyframes whopL
{
0%
{
transform: scale(1,1) translateY(0px) translateX(0px);
}
100%
{
transform: scale(1.5) translateY(-10px) translateX(-10px);
}
}
#keyframes whopC
{
0%
{
transform: scale(1,1) translateY(0px) translateX(0px);
}
100%
{
transform: scale(1.5) translateY(-10px);
}
}
#keyframes whopR
{
0%
{
transform: scale(1,1) translateY(0px) translateX(0px);
}
100%
{
transform: scale(1.5) translateY(-10px) translateX(10px);
}
}
JS/jQuery:
$(".burger-menu").click(function()
{
$(".barTop").toggleClass("barTopOn");
$(".barMid").toggleClass("barMidOn");
$(".barBot").toggleClass("barBotOn");
$(".smlOne").toggleClass("smlOnOne");
$(".smlTwo").toggleClass("smlOnTwo");
$(".smlThree").toggleClass("smlOnThree");
});
Here is a working demo:
https://codepen.io/BGGrieco/pen/NgjxXq
You have an element that is a set of #-webkit-keyframes to animate in. On hamburger-menu click, these keyframes run, and that works well.
Next, you have a second set of #-webkit-keyframes on hover, so on hover works well too.
However, the instant the mouse is away from the element, the first (intro) set of keyframes gets run again. You don't want it to run after it first runs.
Here is what I was able to accomplish:
https://codepen.io/CapySloth/pen/RgxKEb
<div id="workouts" class="sml smlOne">
<div class="test1">
Go there
</div>
</div>
Instead of stacking classes which contain keyframe animations onto the one ".sml" class, I have split the task between two elements. ".sml" now acts as a wrapper which takes care of the "hamburger-menu open" animation and "test1 a" takes care of the "whop" animation.
If you can find a way to hide/show parents of the "test1 a/test2 a/test3 a" then you will have what you want.
You can use .stop() before your .toggleClass.
$("#example").stop().toggleClass("class");

Categories

Resources