CSS Transition works when adding class, but not removing it - javascript

First off, just wanted to mention that I have read this thread:
CSS3 transition only when class is added, not when removed
and the solution there does not work for me. I have a nav that is hidden when the browser is within the small breakpoint, and is revealed when an element is clicked. Clicking the element adds a class via jQuery. Once open, there is a close button that when clicked removes the class. The class is adding and subtracting as expected, but for some reason the transition only works when the .open class is added, not when it's removed. Here's my code:
HTML:
<div class="menu-main-nav-container">
<ul id="menu-main-nav" class="menu">
<li id="menu-item-40" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-40">What We Do</li>
<li id="menu-item-41" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-41">Team</li>
<li id="menu-item-42" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-42">Case Studies</li>
<li id="menu-item-102" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-102">What Next?</li>
<li id="menu-item-104" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-104">Contact</li>
<li id="menu-item-122" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-122">Close</li>
</ul>
</div>
CSS (Compass + Sass):
#menu-main-nav {
#include single-transition(opacity, 0.3s, ease-in-out);
opacity: 0;
position: absolute;
top: -27px;
left: 0px;
height: 0;
overflow: hidden;
z-index: 5000;
&.open {
opacity: 1;
height: auto;
}
}
CSS (Compiled):
#header #menu-main-nav {
transition: opacity 0.3s ease-in-out;
opacity: 0;
position: absolute;
top: -27px;
left: 0px;
height: 0;
overflow: hidden;
z-index: 5000;
}
#header #menu-main-nav.open {
opacity: 1;
height: auto;
}
jQuery:
$('body').on('click', '.menu-main-nav-container', function(e) {
if(!$mobileNav.hasClass('open')) {
$mobileNav.addClass('open');
}
}).on('click', '.nav-close', function(e) {
if($mobileNav.hasClass('open')) {
$mobileNav.removeClass('open');
}
})
});
I'm pretty stumped here. Keep in mind that I am using Compass and that the initial transition is working as expected.

As mentioned in the comments, the issue is that height: 0 immediately hides the element when the class is removed. The opacity still transitions, but you don't see it.
Unfortunately, since height: auto is not a transitionable value, adding a height to the transition is not going to help. You could do it with a fixed height, if you set a delay when the open class is not present, but remove the delay when it is added.
var $menu = $('#menu-main-nav');
setInterval(function() {
$menu.toggleClass('open');
}, 2000);
#menu-main-nav {
background: grey;
overflow: hidden;
height: 0;
opacity: 0;
transition: opacity 1s, height 0s 1s;
}
#menu-main-nav.open {
height: 300px;
opacity: 1;
transition: opacity 1s, height 0s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="menu-main-nav-container">
<ul id="menu-main-nav" class="menu">
<li>What We Do</li>
<li>Team</li>
<li>Case Studies</li>
<li>What Next?</li>
<li>Contact</li>
<li>Close</li>
</ul>
</div>
As an alternative to fixed height, if you do not rely on the layout of the element when expanded, you could use visibility which is transitionable (well, you can delay it by a transition anyway), using the same technique above.
var $menu = $('#menu-main-nav');
setInterval(function() {
$menu.toggleClass('open');
}, 2000);
#menu-main-nav {
background: grey;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
#menu-main-nav.open {
opacity: 1;
visibility: visible;
transition: opacity 1s, visibility 0s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="menu-main-nav-container">
<ul id="menu-main-nav" class="menu">
<li>What We Do</li>
<li>Team</li>
<li>Case Studies</li>
<li>What Next?</li>
<li>Contact</li>
<li>Close</li>
</ul>
</div>
However, this means that the element will always the same height. If you do need the element to have a variable height, you could use JavaScript to calculate the target height, and set it to a fixed height for the duration of the animation.

try this, you just forgot the "" in your body element, and put the elements inside ()
Like this:
$(document).ready(function(){
$("body").on('click', '.menu-main-nav-container', function(e) {
if(!$("mobileNav").hasClass('open')) {
$("mobileNav").addClass('open');
}
}).on('click', '.nav-close', function(e) {
if($("mobileNav").hasClass('open')) {
$("mobileNav").removeClass('open');
}
})
});

Related

Smooth toggle Javascript function

Well what I want to do is to toggle a menu when is clicked but it's not smooth and it feels tough, I'm a newbie in JS but I do know CSS and HTML well enough, so is there a way to smooth this toggle function?
menu unclicked:
menu clicked:
const toggleButton = document.getElementsByClassName("nav__toggle-button")[0];
const navbarLinks = document.getElementsByClassName("nav__links")[0];
toggleButton.addEventListener("click", () => {
console.log("clicked");
navbarLinks.classList.toggle("active");
toggleButton.classList.toggle("open");
});
If you want to solve this with CSS you can 'animate' the two divs with the transitions property: https://www.w3schools.com/css/css3_transitions.asp
close state:
div {
opacity: 0;
transition: opacity 1s;
}
open state:
div.active {
opacity: 1;
transition: opacity 1s;
}
Two minors:
don't use BEM classes to trigger an event listener, use instead a proper class (js-click or something..)
a small refactor for your first two lines:
const [toggleButton] = document.querySelectorAll(".nav__toggle-button")
const [navbarLinks] = document.querySelectorAll(".nav__links")
You can apply transition and transform properties to the element through CSS.
For example, if you are using a drop down menu and controlling the slide and the opacity:
transform: translateY(-10px);
transition: opacity 150ms ease-in-out, transform 150ms ease-in-out;
You could check out:
https://developer.mozilla.org/en-US/docs/Web/CSS/transition
All you need is a transition and transform property that you can toggle. Transform CSS property is used for handling dimensions, orientation etc of a DOM element. Adding transition adds an effect where the transform properties if changed, change gradually.
const closeButton = document.getElementById("close")
closeButton.addEventListener("click", () => {
const menu = document.getElementById("nav-links")
menu.classList.toggle("closed-list");
})
ol {
width: 100%;
list-style-type: none;
background: gray;
transition: all 0.4s ease-in-out;
}
.closed-list {
transform: scaleY(0);
transform-origin: top;
}
li {
text-align: center;
padding: 12px 0px;
color: white;
font-weight: 700;
font-size: 18px;
}
#close-container {
text-align: right;
}
<div>
<div id="close-container">
<button id="close">
open/close
</button>
</div>
<ol id="nav-links">
<li>Test 1</li>
<li>Test 2</li>
<li>Test 3</li>
<li>Test 4</li>
</ol>
</div>

jquery animation while switchig menu on hover

I have code that switches between menu and submenu on hover, but I want short slide-left animation on mouse-in and slide-right on mouse-out.
My template contain this animations (.mk-vm-animate-out-1 and .mk-vm-animate-in-1) so i'd like to use them (but it's not necessary).
My idea was to add class with animation and some dealy and then add classes that shows submenu... but everything that i tried wasnt working... :/
Here is my code:
$(function() {
$('#menu-item-155').hover(
function(){
$(this).parent().addClass("mk-vm-animate-out-1");
$(this).addClass("mk-vm-subviewopen");
$(this).parent().addClass("mk-vm-subview");
},
function(){
$(this).removeClass("mk-vm-subviewopen");
$(this).parent().removeClass("mk-vm-animate-out-1");
$(this).parent().removeClass("mk-vm-subview");
}
);
});
<ul id="menu-main-menu">
<li id="menu-item-4673"> <a><span>ITEM 1</span></a></li>
<li id="menu-item-155" class="menu-item"><a><span>ITEM with submenu</span></a>
<ul class="sub-menu ">
<li id="menu-item-4792"><a><span>submenu item1</span></a></li>
<li id="menu-item-4718"><a><span>submenu item2</span></a></li>
<li id="menu-item-4718"><a><span>submenu item3</span></a></li></ul>
</li>
<li id="menu-item-159"><a><span>ITEM 3</span></a></li>
<li id="menu-item-159"><a><span>ITEM 4</span></a></li>
</ul>
You can use transform and transition for this
.before-hover {
left:15px;
opacity: 0;
z-index:-1;
visibility: hidden;
transition: all 0.4s;
}
.before-hover:hover {
opacity:1;
z-index:1;
visibility:visible;
transform: translateY(-15px);
}

Animate easy in and easy out when hover a link

Hi guys i want to make a menu similar to this site: http://tommasoraspo.com/creativepartners/DesignLovers/index.html
But I don't know how i would animate the Bookmark to show up when i hover a link. I thought in using animate.css (slideInDown animation) but then it would only show up when hover over but wouldn't get back when hover out.
Initiate Animation on Hover:
function animationHover(element, animation){
element = $(element);
element.hover(
function() {
element.addClass('animated ' + animation);
},
function(){
//wait for animation to finish before removing classes
window.setTimeout( function(){
element.removeClass('animated ' + animation);
}, 2000);
});
}
The site you point to isn't using an javascript. Rather, they are using css3 transitions to animate the background position of an image that is "off-canvas" when the site is loaded.
Here's a fiddle with the relevant css/html.
You may have to tweak the values to suit your specific design and image.
HTML:
<ul class="nav">
<li>Menu Item 1
</li>
<li>Menu Item 2
</li>
<li>Menu Item 3
</li>
<li>Menu Item 4
</li>
</ul>
CSS:
ul.nav {
list-style: none;
margin: 0;
}
ul.nav li {
float: left;
margin: 0 0 0 30px;
}
ul.nav li.current a, ul.nav li a:hover {
background-position: 50% 0;
}
ul.nav li a {
height: 50px;
line-height: 50px;
display: block;
padding: 50px 20px 0;
position: relative;
background: url(http://lorempixel.com/50/70/abstract/) no-repeat 50% -90px;
-webkit-transition: background-position 0.2s linear;
-moz-transition: background-position 0.2s linear;
transition: background-position 0.2s linear;
}

How do you transition a height without the element going outside the parents border?

I am trying to make a transition that starts with everything at the top and after the page loads, the content slowly expands down the page.
I've gotten most of it working, except when the content expands down the page, it keeps expanding way outside it's parents borders. I have all the elements set to expand to 100%, so I thought the expanding elements would only expand to 100% of its parents size, but it just keeps going down the page.
Perhaps I am just misunderstanding how the parent/child height percentages work. Can anyone point out what I am doing wrong? Thanks.
Here is a link to the code on jsfiddle
Here is the HTML code:
<body>
<div id="outer">
<div class="middle">
<div class="inner">
<h3>A-B</h3>
<ul>
<li>A</li>
<li>B</li>
</ul>
</div>
<div class="inner">
<h3>C-G</h3>
<ul>
<li>C</li>
<li>D</li>
<li>E</li>
<li>F</li>
<li>G</li>
</ul>
</div>
<div class="inner">
<h3>H</h3>
<ul>
<li>H</li>
</ul>
</div>
</div>
</div>
</body>
Here is the javascript code:
window.onload = function () {
document.getElementById("outer").setAttribute("class", "loaded");
}
Here is the CSS:
html {
height: 100%;
}
body {
height: 100%;
}
#outer {
height: 100%;
}
.middle {
border: solid 2px black;
height: 100%;
}
.inner {
height: 0%;
transition: height 5s 2s;
-moz-transition: height 5s 2s;
-webkit-transition: height 5s 2s;
-o-transition: height 5s 2s;
}
#outer.loaded .inner {
height: 100%;
}
percentages are based on the parent. You are setting three divs with class .inner to height 100%. which means the total height is 300%. Set the .inner to 33% would be more reasonable.
EDIT
Just out of interest, found another article on here on SO that might help you with what you are trying to do, which is transition height 0 to transition height auto, which actually involves setting the max-height to a number really big (well at least bigger than its auto height), so only transitions to the auto anyway. Link here

Jquery Hover Class Fade with Background Image

I have the following Jquery script below that adds a the .hover class on rollover and then removes it on rollout. Currently, the background (whether image or color) fades in and out nicely. However, I don't want the menu text to fade in and out.
I'm aware of the CSS3 fade transitions and the Jquery color plugins but would like to have the option of fading in image backgrounds as well (which is why I'd like to fade in a class rather than just background-color.) Any help would be most appreciated:)Thanks in advance.
Jquery
$(document).ready(function () {
//Set the anchor link opacity to 0 and begin hover function
$("#menu-sample-menu li a").hover(function () {
//Fade to an opacity of 1 at a speed of 200ms
$(this).fadeOut(0).addClass('hover').fadeIn(300);
//On mouse-off
}, function () {
//Fade to an opacity of 0 at a speed of 100ms
$(this).fadeOut(300)
.queue(function () {
$(this).removeClass('hover').fadeIn(0).dequeue()
});
});
});
HTML
<nav id="access">
<ul id="menu-sample-menu" class="menu">
<li id="menu-item-198" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-198">Health Care Professional
</li>
<li id="menu-item-197" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-197">Web Designer
<ul class="sub-menu">
<li id="menu-item-199" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-199">Construction Worker
</li>
</ul>
</li>
</ul>
</nav>
Style
#access li {
position:relative;
float:left;
padding:0;
margin:0;
}
#access ul li:first-child {
padding-left:0;
}
#access a {
display:block;
padding:15px 24px;
color:#f0f0f0;
text-decoration:none;
}
#menu-sample-menu li {
color: black;
text-shadow: 0px 1px 4px #777;
background-color: green;
padding: 0 12px 0 12px;
}
#menu-sample-menu li a.hover {
background-color: orange;
background-image: url(images/over.jpg);
}
You can do this without javascript: http://jsfiddle.net/WjrnB/1/
Simply use:
#menu-sample-menu li a:hover {
background-color: orange;
background-image: url(images/over.jpg);
}
instead of
#menu-sample-menu li a.hover {
background-color: orange;
background-image: url(images/over.jpg);
}
and add:
#menu-sample-menu li a {
-khtml-transition: all 0.5s;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
-o-transition: all 0.5s;
-ms-transition: all 0.5s;
transition: all 0.5s;
}
Xarcell's answer is probably the best simplicity-wise. If you are looking to accomplish this with JavaScript, one option would be using JQuery-UI which has addClass and removeClass functions which incorporate transitions.
Basically, the HTML and CSS is the same as above, but the JS would look as follows:
$(document).ready(function () {
//Set the anchor link opacity to 0 and begin hover function
$("#menu-sample-menu li a").hover(function () {
//Fade 'hover' class in at 300ms
$(this).addClass('hover', 300);
//On mouse-off
}, function () {
//Fade 'hover' class out at 300ms
$(this).removeClass('hover', 300);
});
});
And, of course, you would have to include JQuery-UI (I usually use Cloud Flair's CDNJS):
http://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js
Personally, I would use this method if I was already using JQuery-UI. Otherwise, I would go with Xarcell's solution.

Categories