I am trying to make this button work so it does not just "instantly" display the menu. When I added the .style.WebkitTransition content to my code, it broke the functionality. The button works without it, but it displays the content instantly. I want it to transition smoothly like it does on nice websites. I don't need a demonstration demo or anything, I just need a JavaScript guru to tell me how to go about achieving my desired results from this code. Thank you!
JavaScript
function mobileFunction() {
var x = document.getElementById("JavaMenu").style.WebkitTransition = "ease 1s";
if (x.className === "navbar") {
x.className += " responsive";
} else {
x.className = "navbar";
}
}
Use max-height instead of height in css
function mobileFunction() {
var x = document.getElementById("JavaMenu");
x.style.transition = "ease 1s";
document.getElementById('JavaMenu').classList.toggle('responsive');
}
.navbar{ max-height:0; overflow:hidden; transition: ease 1s}
.navbar.responsive{ max-height: 200px;}
<span onclick="mobileFunction()">Toggle Menu</span>
<ul id="JavaMenu" class="navbar">
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
</ul>
You can't possibly animate display property.
Use should add top, left | margins | transform | opacity to achieve effective animation effect, display: block only shows the element. The most effective way of animating a menu is to hide it by display: none and throw it away from your view X = -MENU_WIDTH LEFT or X = SCREEN_WIDTH + MENU_WIDTH RIGHT then do a sliding effect
// CSS
#JavaMenu {
// hide it by default
display: none;
// width: 320px;
// throw it off screen, give it -width or more than -width to effectively hide it
transform: translateX(-320px);
// you can just simply put the transition here:
// transition: 1s ease;
}
// the show
#JavaMenu.responsive {
// show it
display: block;
// move it on screen;
transform: translateX(0);
}
// JS
// then toggle the classes as you did in your JS
// this will give it animation effect
Also instead of using .className() you can actually use .classList.contains('navbar') to check if navbar class exists, classList.add(class) to add and classList.remove(class) to remove.
hope that helps.
Related
Currently I'm working in Vue.js and have a navigation menu that I'd like to animate. What I'm looking to do is show two li elements when a user hovers over one of the navigational buttons.
Currently what I'm doing is setting a data type of showActivities to false by default and setting that to true on mouseenter and false on mouseleave. So this has the items appearing and disappearing on hover but they're not animated. How could animation for this be done?
<ul class="navs">
<li>Schedule</li>
<li #mouseenter="showActivities = true" #mouseleave="showActivities = false">Team Activity</li>
<li v-show="showActivities">tik tak tow</li>
<li v-show="showActivities">Bejewel</li>
<li>Resources</li>
<li class="logout">Logout</li>
</ul>
<script>
export default {
name: 'SideMenu',
data() {
return {
showActivities: false,
};
},
};
</script>
okay if i got you correct you want a type of animation like a slow fade In and Out.
In vuejs transitions, state are attached to CSS classes that can be called and modified ass you want it to be. The doc is clearer about it
Vuejs Transitions
for example if you add this in your css section the transition will be a slow fade In and Out:
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
I am trying to make it so, that when a button is clicked like a toggle, the texts and everything below it move smoothly below it instead of suddenly moving it. An example of this is bootstrap navbar hamburger menu. When the menu is clicked in mobile view, the rest of the items under it move in a smooth manner to make room for the navbar items.
Here are my codes in the snippet.
let box = document.querySelector("#box");
let seconddiv = document.querySelector("#seconddiv");
box.addEventListener("click", myfunc);
function myfunc() {
if(seconddiv.style.display == "none") {
seconddiv.style.display = "block";
}
else {
seconddiv.style.display = "none"
}
}
#box {
height: 50px;
width: 50px;
background-color: red
}
#seconddiv {
display: none;
}
<div id="box">
</div>
<div id="seconddiv">
<p>whats up</p>
<p>whats up</p>
<p>whats up</p>
<p>whats up</p>
<p>whats up</p>
</div>
<p>hello</p>
When I click the red box, the "hello" text moves instantly when the "seconddiv" is set to display. Is it possible to move "hello" smoothly like in bootstrap?
You can use jQuery for this purpose. jQuery can handle better and in easy way.
Please include jQuery file for following jQuery code:
$('#box').click(function(){
$('#seconddiv').slideToggle();
});
If you want more slow speed for displaying and hiding div on click, then pass "slow" parameter in slideToggle function.
$('#seconddiv').slideToggle("slow");
display:none is not handled with transitions. But you can add a class to the button with javascript on click. And then give the button height:30px when it has class '.clicked'
#seconddiv {
height: 0;
transition: height 0.5s
}
#seconddiv.clicked{
height: 30px;
}
You can work with width or opacity too instead of height, but the difference with opacity is that the element will still use the space even when set to opacity:0
This is frustrating me to no end. Before I post the code, here's a summary:
The goal, in simple terms: when I double click X, I want it to fade out; when I click Y, I want X to fade in.
The method: I'm using CSS to create the actual fade-in and fade-out "animations." I'm using JavaScript to apply the classes when necessary using a little trickery.
The problem: the fade-in transition doesn't work -- the element just appears instantly. What is driving me insane is the fact that the fade-in, when instantly added back onto a faded-out object, works perfectly. I'll explain this better as a comment in the JS code.
(Yes, I've added opacity: 1 and transition: opacity onto the base elements. It had no effect at all.)
The code:
CSS
*.fade-out {
opacity: 0;
transition: opacity 400ms;
}
*.fade-in {
opacity: 1;
transition: opacity 400ms;
}
*.hide {
display: none;
visibility: hidden;
}
JavaScript
$( '#ArtistEmblem' ).on( 'dblclick', function() {
fadeOut($( '#ArtistEmblem' ));
fadeIn($( '#btnShowLogo' ));
});
$( '#btnShowLogo' ).on( 'click', function() {
fadeOut($( '#btnShowLogo' ));
fadeIn($( '#ArtistEmblem' ));
});
function fadeOut(element) {
element.addClass( 'fade-out' );
setTimeout( function () {
element.addClass( 'hide' );
/*
* I tried immediately adding the 'fade-in' class here
* and it worked -- as soon as the element faded out, it faded
* back in (using the CSS transition). However, outside of this,
* it REFUSES to work; everything appears instantly
*/
console.log('timer triggered');
}, 400);
}
function fadeIn(element) {
element.removeClass( 'hide' );
element.removeClass( 'fade-out' );
element.addClass( 'fade-in' );
}
Relevant HTML
<div id="ArtistEmblem">
<img src="img/logo_artist_2.png" />
</div>
<div id="PopMenu" class="collapse">
<article>
<header>
<b>Debug Menu</b>
</header>
<section>
<button id="btnOpenOverlay">Open Overlay</button>
<button id="btnShowLogo" class="hide">Show Logo</button>
<button id="btnClose">Close Menu</button>
</section>
</article>
</div>
I apologize if this is something obvious but I've wasted far too much time trying to solve it. I am also open to better, faster, or more efficient solutions if that would be the best answer. Thanks in advance!
The problem is that the initial opacity of "hidden" element is 1 by default. You just need to set it to 0. And also remove display: none –
*.hide {
opacity: 0;
}
Also I would do a little refactoring and remove setTimeout:
$('#ArtistEmblem').on('click', function() {
fade($('#btnShowLogo'), $(this));
});
$('#btnShowLogo').on('click', function() {
fade($('#ArtistEmblem'), $(this));
});
function fade(inElement, outElement) {
inElement.removeClass('hide');
inElement.addClass('fade-in');
outElement.removeClass('fade-in');
outElement.addClass('fade-out');
}
If you don't want the hidden element to occupy space and you want it to be displayed-none, then you need to set display: block before starting the fadeOut.
I know you're asking for a JS heavy answer, but I highly recommend toggling a class of "active", "open" or something similar and using CSS with the transition. Less is more here.
Here's an example fiddle of something I've transitions not only the opacity, but also the z-index. That's the key with these transitions if you intend on having any elements below such as buttons that require hovering, clicking, etc.
JS Fiddle
Key parts:
.container {
z-index: -1;
opacity: 0;
transition: z-index .01s 1s, opacity 1s;
}
.container.active {
transition: z-index 0s, opacity 1s;
z-index: 500;
opacity: 1;
}
EDIT
I was just messing around with this type of thing for my own project, and observing how beautiful Stripe handles their navigation bar. Something so simple changes everything, and that's pointer-events. If you're okay with its support, (notable no ie. 10) this is infinitely easier to integrate. Here's another fiddle of the simulation in a nav bar.
The key part is pointer-events: none, as it ignores click events if set to none, almost as if it wasn't there, yet visibly it is. I highly recommend this.
https://jsfiddle.net/joshmoxey/dd2sts7d/1/
Here is an example using Javascript Animate API. Animate API is not supported in IE/Edge though.
var element = document.getElementById("fade-in-out")
var button = document.getElementById("x")
button.addEventListener("click", function(event) {
element.animate([{opacity: 1, visibility: "visible"},{opacity: 0, visibility: "hidden"}], {duration: 2000})
setTimeout(function() { element.remove() }, 2000)
})
button.addEventListener("dblclick", function(event) {
element && element.animate([{opacity: 0}, {opacity: 1}], {duration: 2000})
})
<input id="x" type="button" value="Click here" />
<div id="fade-in-out"> FADE ME </div>
I've been trying to create a nav that would be transparent at the top and would gain white color as the user scrolls down the page. My header height is 800px and I want my nav to lose 100% of transparency after those 800px. Here`s my code:
<header id="header">
<nav class="navbar">
<ul class="navigation">
<li>Home</li>
<li>About us</li>
<li>Our qualities</li>
<li>Contact us</li>
<li>contact us</li>
</ul>
</nav>
nav {
width: 1600px;
position: fixed;
top: 0;
ul {
margin: 0 auto;
li {
display: inline-block;
padding: 5px 20px;
a {
font-family: $f1;
font-size: 16pt;
color: $c3;
}
}
}
}
}
First I tried with opacity, but it didn't work, and on top of that child elements (ul and li) had opacity of 0 as well.
Here`s the JS for that:
jQuery(document).ready( function() {
var navOffset = jQuery("nav").offset().top;
jQuery(window).scroll(function() {
var scrollPos = jQuery(window).scrollTop();
var navOpacity = scrollPos /800;
jQuery('.navbar').css(opacity, 'navOpacity');
if (jQuery('nav').css('opacity') < 1) {
jQuery('.navigation').css('opacity', '1')
};
Then I tried to change RGBA value on scroll, that didn't work either
Instead of
jQuery('.navbar').css( opacity, 'navOpacity' );
I used
jQuery('.navbar').css(backgroundcolor, 'rgba (255, 255, 255, + "navOpacity")');
That failed as well, so, I have to ask you too help me
You have made opacity not a string, but the variable navOpacity has become a string. That was wrong. Everything else is working fine in general. :)
// change
$('.navbar').css(opacity, "navOpacity");
// to
$('.navbar').css("opacity", navOpacity);
Working example.
The issue in your code is that you're providing navOpacity as a string to css(), instead of the variable itself. Try this:
$('.navbar').css('opacity', navOpacity);
Also note that your current logic is backwards to what you describe as your goal (the header starts transparent and becomes opaque at 800px) and the logic can also be simplified a lot. Try this:
$(window).scroll(function() {
var pc = $(this).scrollTop() / 800;
$('.navbar').css('opacity', 1 - pc);
});
Working example
Alternatively you could use jquery method .fadeTo() instead of css('opacity'). This method animates the opacity of the elements smoothly. It is easier to use and the animation is pretty good looking compared to instant opacity change.
jQuery('.navbar').fadeTo( "slow" , navOpacity);
if (jQuery('nav').css('opacity') < 1) {
jQuery('.navigation').fadeTo( "slow" , 1);
};
I'm using a script to make content boxes slide from the top upon entry and then slides down upon exit.
It's almost working perfectly however, when you click on the button for content box one, then content box two, then back to one again, one comes in from the bottom instead of the top.
I think I understand why this is happening (because the code runs all in one hit, and thus instead of going from below the viewport, to above the viewport and then into view, it just goes from below into view) but can't figure out how to make it always come in from the top.
HTML:
<div class="slidey slidey1 enter">
Content Box 1
</div>
<div class="slidey slidey2">
Content Box 1
</div>
<div class="slidey slidey3">
Content Box 1
</div>
CSS:
.slidey { top:-100% }
.enter { top:0; transition: all 0.7s ease-in-out; }
.exit { top:100%; transition: all 0.7s ease-in-out; }
jQuery:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(".changer").click(function(){
if ($(".slidey" + $(this).data("slidey")).hasClass("enter")) {
return false
} else {
$(".slidey").removeClass("exit");
$(".slidey.enter").addClass("exit").removeClass("enter");
$(".slidey" + $(this).data("slidey")).addClass("enter");
$(".changer").removeClass("link_change");
$(".changer" + $(this).data("slidey")).addClass("link_change");
return false;
}
});
});
</script>
The page is no longer available to be viewed.
After adding a class your should assign a "transitionend" listener like i.e:
$(".myElement").addClass("transitionClass").on("transitionend", function() {
// Transition ended.
// Do more stuff.
});
I recreated and simplified your HTML, CSS to create this example, so you might want to ignore that part, but focus on the jQ code. Should work even on your page out of the box.
$(document).ready(function(){
var $slides = $(".slidey");
$(".changer").click(function( e ){
e.preventDefault(); // Instead of return false;
var num = $(this).data("slidey");
var $target = $(".slidey"+ num);
$(".enter").not($target) // (not the already active one)
.removeClass("enter") // remove unwanted classes
.addClass("exit") // make it go to bottom
.on("transitionend", function(){ // snap it back to -100% top...
$(this).removeClass("exit"); // by removing the exit class.
});
$target.addClass("enter"); // Animate current down into view
// UL links
$(".changer").removeClass("link_change");
$(this).addClass("link_change");
});
});
*{margin:0;}
html, body{height:100%;}
body{overflow:hidden;}
#navbar{
position:absolute;
bottom:130px;
right:130px;
}
#navbar ul {list-style:none;}
.link_change{
color:fuchsia;
}
.slidey {
position:absolute;
width:50%;
height:90vh;
background:#ddd;
top:-100%;
}
.enter {
top:0;
transition: all 0.7s ease-in-out;
}
.exit {
top:100%;
transition: all 0.7s ease-in-out;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="navbar">
<ul id="navlinks">
<li class="changer changer1 link_change" data-slidey="1">home</li>
<li class="changer changer2" data-slidey="2">profile</li>
<li class="changer changer3" data-slidey="3">message</li>
</ul>
</div>
<div class="slidey slidey1 enter">Content Box 1</div>
<div class="slidey slidey2">Content Box 2</div>
<div class="slidey slidey3">Content Box 3</div>