I'm creating a Website with HTML, CSS, and JavaScript (no jQuery).
I have created the following script to change my Navigation Class when my pageoffset is more than 50 and change it back if its less then 50:
window.onscroll = function (event) {
var nav = document.getElementsByClassName('main-navigation');
var navscr = document.getElementsByClassName('main-navigation-scrolled');
if (window.pageYOffset > 50) {
for(var i = 0; i < nav.length; i++) {
nav[i].className = 'main-navigation-scrolled';
}
}
else {
if (window.pageYOffset < 50) {
for(var i = 0; i < navscr.length; i++) {
navscr[i].className = 'main-navigation';
}
}
}
}
For some reason, when I scroll very slowly or reload the page when my offset is more than 50 only half the li-elements change class.
Maybe there is a smarter solution which also has better performance?
This is my first question, go easy on me please :)
€dit: HTML
<div id="nav-menu-container-fix">
<ul>
<li><a class="main-navigation" href="index.html">Home</a></li>
<li><a class="main-navigation" href="about.html">About</a></li>
<li><a class="main-navigation" href="#">Team</a></li>
<li><a class="main-navigation" href="#">24 Weeks</a></li>
<li><a class="main-navigation" href="#">Donate</a></li>
<li><a class="main-navigation" href="#">Downloads</a></li>
<li><a class="main-navigation" href="#">Forum</a></li>
</ul>
</div>
Aaaaand CSS
a.main-navigation {
padding:18px 15px 15px 15px;
background-color:#222222;
color:#bbbbbb;
display:inline-block;
text-decoration:none;
-webkit-transition: all 600ms ease;
-moz-transition: all 600ms ease;
-ms-transition: all 600ms ease;
-o-transition: all 600ms ease;
transition: all 600ms ease;
}
a.main-navigation:hover {
padding:18px 15px 15px 15px;
background-color:#555555;
color:#ffffff;
display:inline-block;
text-decoration:none;
-webkit-transition: all 600ms ease;
-moz-transition: all 600ms ease;
-ms-transition: all 600ms ease;
-o-transition: all 600ms ease;
transition: all 600ms ease;
}
a.main-navigation-scrolled {
padding:7.5px 15px 7.5px 15px;
background-color:#604D9D;
color:#eeeeee;
display:inline-block;
text-decoration:none;
-webkit-transition: all 600ms ease;
-moz-transition: all 600ms ease;
-ms-transition: all 600ms ease;
-o-transition: all 600ms ease;
transition: all 600ms ease;
}
a.main-navigation-scrolled:hover {
padding:7.5px 15px 7.5px 15px;
background-color:#402c6c;
color:#ffffff;
display:inline-block;
text-decoration:none;
-webkit-transition: all 400ms ease;
-moz-transition: all 600ms ease;
-ms-transition: all 600ms ease;
-o-transition: all 600ms ease;
transition: all 600ms ease;
}
Scroll event will be called hundreds of times while you are scrolling. so you need to perform the actions one and only once when the conditions are matched.
the following will reduce dom accessing
var scrolled = false; // initially page is not scrolled
window.onscroll = function (event) {
if (window.pageYOffset > 50 && !scrolled) { //perform following only if it's not done already
var nav = document.querySelectorAll('main-navigation');
for (var i = 0; i < nav.length; i++) {
nav[i].className = 'main-navigation-scrolled';
scrolled = true; // applied scroll class no need to do this again
}
} else if (window.pageYOffset < 50 && scrolled) { //perform the following only it's not done already
var navscr = document.querySelectorAll('main-navigation-scrolled');
for (var i = 0; i < navscr.length; i++) {
navscr[i].className = 'main-navigation';
scrolled = false; // applied no scroll class, no need to do it again
}
}
}
Update: working fiddle
I don't really know why it didn't work, but I know it works now. I started using jquery and with the following code it works just fine.
$(document).scroll(function () {
if (window.scrollY > 50) {
$(".main-navigation").attr('class', 'main-navigation-scrolled');
} else {
$(".main-navigation-scrolled").attr('class', 'main-navigation');
}
});
Related
I tried this way of code to save menu state when refresh and user can expand and close the menu but go some problems
javascript functions used to togglesidebar open/close menu
function toggleSidebar(){
if(!document.readyState === 'complete') {
return;
}
toggleElements();
if ($('.collapseSidebar').length > 0) {
upSizeSidebar();
} else {
collapseSidebar();
}
};
function toggleElements(){
$('.site-menubar-footer').toggle();
$('.site-menu-title').toggle();
$('.navbar-header').find('.fa-bars').toggle();
$('.navbar-header').find('.fa-chevron-left').toggle();
};
function collapseSidebar(){
localStorage.setItem('collapsed', 'true');
$(".site-menubar").removeClass("upSizeSidebar");
$(".site-menubar").addClass("collapseSidebar");
$("#layout_new").css("margin-left", "75px");
};
function upSizeSidebar(){
localStorage.setItem('collapsed', 'false');
$(".site-menubar").removeClass("collapseSidebar");
$(".site-menubar").addClass("upSizeSidebar");
$("#layout_new").css("margin-left", "290px");
};
function setMenuState(){
var menuState = localStorage.getItem('collapsed')
if (menuState !== null && menuState === 'true') {
toggleElements();
collapseSidebar();
}
};
function activateMenuToggleButtons(){
$('.navbar-header').find('.fa-chevron-left').css('pointer-events', 'auto');
$('.navbar-header').find('.fa-bars').css('pointer-events', 'auto');
};
document.addEventListener("DOMContentLoaded", function(){
activateMenuToggleButtons();
setMenuState();
});
CSS used for transition when open/close menu
.collapseTransition {
-moz-transition: width 0.2s ease-in-out, left 0.2s ease-in-out;
-webkit-transition: width 0.2s ease-in-out, left 0.2s ease-in-out;
-moz-transition: width 0.2s ease-in-out, left 0.2s ease-in-out;
-o-transition: width 0.2s ease-in-out, left 0.2s ease-in-out;
transition: width 0.2s ease-in-out, left 0.2s ease-in-out;
}
.collapseSidebar {
width: 45px !important;
}
.upSizeSidebar {
width: 260px !important;
}
Sometimes when clicking to open close and refreshing this occur
I am trying to make a message appear if the user doesn't scroll for specific amount of time and then make the text fade out as soon as the user scroll. What I have tried so far is not working.
I am looking for vanilla javascript solutions only.
thank you for your help.
// make scroll button appear ---------------
var scrollText = document.getElementById("scrollMsg");
function showMsg() {
scrollText.className = "show";
}
setTimeout(showMsg, 2000);
// make scroll button fadout ---------------
function scrollHide() {
var scrollText2 = document.querySelector("#scrollMsg.show");
var scrllTPosition = scrollText2.getBoundingClientRect().top;
var screenPosition = window.innerHeight / 0.5;
if (scrllTPosition < screenPosition) {
scrollText2.classList.add("scrollHide");
}
}
window.addEventListener("scroll", scrollHide);
#scrollMsg {
height: auto;
position: sticky;
bottom: 175px;
z-index: 1;
opacity: 0;
-webkit-transition: opacity 0.7s;
-moz-transition: opacity 0.7s;
transition: opacity 0.7s;
}
#scrollMsg.show {
opacity: 1;
-webkit-transition: opacity 0.7s ease-in-out;
-moz-transition: opacity 0.7s ease-in-out;
transition: opacity 0.7s ease-in-out;
}
#scrollhide {
opacity: 0;
-webkit-transition: opacity 0.7s ease-in-out;
-moz-transition: opacity 0.7s ease-in-out;
transition: opacity 0.7s ease-in-out;
}
<p id="scrollMsg">scroll</p>
I've added some large divs to allow us to scroll through the document.
// make scroll button appear ---------------
var scrollText = document.getElementById("scrollMsg");
window.addEventListener('scroll', (e) => {
console.log('user scrolled!')
scrollText.style.opacity = 0
});
#scrollMsg {
opacity: 1;
transition: opacity 1s;
}
<div style="height:100px"></div>
<p id="scrollMsg">scroll</p>
<div style="height:4000px"></div>
I've implemented ngAnimate into a project to help with animations, but I'm getting really odd behaviour with a certain element.
To add some background, we have a shop with categories and products inside the categories. I'm doing an ng-repeat with: data-ng-repeat="product in currentProductCategory.Products" and I have data-ng-class="{ 'open': product.ShowDetails == true }" on my root element.
My root element also has an id of product-{{product.Id}}-{{currentProductCategory.Id}} and I have a child element with id product-options-{{product.Id}}-{{currentProductCategory.Id}} which products expected results.
When clicking a button, I call a function that sets the max-height on the parent element to a desired height, and the animation is handled in the CSS. Here's the function code:
var reg = /\d+/g;
var productParentElement = $('#product-' + product.Id + '-' + $scope.currentProductCategory.Id);
var optionsElement = $('#product-options-' + product.Id + '-' + $scope.currentProductCategory.Id);
var productParentPaddingTop = parseInt(productParentElement.css("padding-top").match(reg));
var productParentPaddingBottom = parseInt(productParentElement.css("padding-bottom").match(reg));
var productParentTotalHeight = productParentPaddingTop + productParentPaddingBottom + productParentElement.height() + optionsElement.height();
var optionsElementPaddingTop = parseInt(optionsElement.css("padding-top").match(reg));
var optionsElementPaddingBottom = parseInt(optionsElement.css("padding-bottom").match(reg));
var optionsElementTotalHeight = optionsElementPaddingTop + optionsElementPaddingBottom + optionsElement.height();
var totalHeight = productParentTotalHeight + optionsElementTotalHeight;
if (product.ShowDetails) {
product.ShowDetails = true;
productParentElement.css("max-height", totalHeight);
} else {
product.ShowDetails = false;
productParentElement.removeAttr('style');
}
And my CSS for the closed and open classes:
Closed:
.products-list .product {
margin-bottom: 20px;
max-height: 200px;
overflow: hidden;
-moz-transition: max-height 2s ease;
-o-transition: max-height 2s ease;
-webkit-transition: max-height 2s ease;
transition: max-height 2s ease;
}
Open:
.products-list .product.open {
-moz-transition: max-height 2s ease;
-o-transition: max-height 2s ease;
-webkit-transition: max-height 2s ease;
transition: max-height 2s ease;
max-height: 200px;
}
The issue is that out of the many products over 4 categories, the same one which is the same product in each category is not animating open. It animates the close/shrink, but when opening, it just instantly appears open.
This has been gating on us for a long time now and it's becoming a real issue, any help is greatly appreciated.
UPDATE: Now none of the "products" will animate open, but they do animate closed. Could this be because I'm setting the max-height on the style rather than a class?
Sorry but this might sound like I am pointing out the obvious and I can't see the rest of your code but in your CSS, you have;
.products-list .product {
margin-bottom: 20px;
max-height: 200px;
overflow: hidden;
-moz-transition: max-height 2s ease;
-o-transition: max-height 2s ease;
-webkit-transition: max-height 2s ease;
transition: max-height 2s ease;
}
for your closed list which has a 'max-height: 200px' but is also the same in your open list;
.products-list .product.open {
-moz-transition: max-height 2s ease;
-o-transition: max-height 2s ease;
-webkit-transition: max-height 2s ease;
transition: max-height 2s ease;
max-height: 200px;
}
Which also has a max-height of 200px. So in this case you're asking it to transition from 200px to 200px. try changing the height of open classes to be bigger or smaller. Then it will transition.
I am looking for a native JS solution to toggle div display using display:'none' and display:'block' properties. I have the first part done. I only need the part to do a simple fadeIn and fadeOut animation.
I need to use native JS and display:block,none.
var e = document.getElementById('calendarPickerContainer');
if (e.className == 'visible') {
e.className = 'hidden';
} else {
e.className = 'visible';
}
need to adapt to this css
.visible{
display:block;
}
.hidden {
display:none;
}
If you wanna use a pure JavaScript fadeIn and fadeOut, try this:
transition: opacity 1s linear;
This is a pure CSS method.
#cont {-webkit-transition: opacity 1s linear; -o-transition: opacity 1s linear; transition: opacity 1s linear;}
#cont.hidden {opacity: 0;}
<button onclick="cont.classList.add('hidden'); setTimeout('cont.style.display=\'none\'', 1000);">Click</button>
<div id="cont">
Hello
</div>
Working Snippet (includes toggle):
#cont {-webkit-transition: opacity 1s linear; -o-transition: opacity 1s linear; transition: opacity 1s linear; opacity: 1;}
#cont.hidden {opacity: 0; -webkit-transition: opacity 1s linear; -o-transition: opacity 1s linear; transition: opacity 1s linear;}
<button onclick="if (cont.style.display != 'none') { cont.classList.add('hidden'); setTimeout('cont.style.display=\'none\'', 1000); } else {cont.style.display='block'; setTimeout('cont.classList.remove(\'hidden\')', 10);}">Click</button>
<div id="cont">
Hello
</div>
You can achieve this easily with CSS3
.visible {
visibility: visible;
opacity: 1;
transition: opacity 2s linear;
}
.hidden {
visibility: hidden;
opacity: 0;
transition: visibility 0s 2s, opacity 2s linear;
}
Native JS fade function:
var s = document.getElementById('calendarPickerContainer').style;
s.opacity = 1;
(function fade(){(s.opacity-=.1)<0?s.display="none":setTimeout(fade,40)})();
You can simplfy this with classList
document.querySelector('.toggle').addEventListener('click',function(e) {
e.target.classList.toggle('hide');
})
Css:
div {
transition:all 0.3s ease-in;
}
.hide {
opacity: 0;
}
We're using opacity since display cannot be animated.
Example
I have a problem with animating a font when is scrolls past the viewport height. It can animate once but not back again...
This works, it just changes the font size back and forth:
if ($(this).scrollTop() > $( window ).height()) {
$('.nav li a').css({"font-size":"2vw"});
} else {
$('.nav li a').css({"font-size":"1.2vw"});
}
But this does not, it animates once but then starts to lag and jump when it should animate back:
if ($(this).scrollTop() > $( window ).height()) {
$('.nav li a').animate({"font-size":"2vw"});
} else {
$('.nav li a').animate({"font-size":"1.2vw"});
}
Does anyone know why?
Thanks!
Does this need to be animated in jQuery? You can get your effect with CSS3 transitions (unless you're trying to support older browsers):
transition: all 0.3s ease;
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
-ms-transition: all 0.3s ease;
Or font only:
transition: font 0.3s ease;
-webkit-transition: font 0.3s ease;
-moz-transition: font 0.3s ease;
-o-transition: font 0.3s ease;
-ms-transition: font 0.3s ease;
You can then use the .css() method to change font-size and the CSS transition will handle the animation.
Just in case the problem is you calling animate too many times, you may try something like this (untested code, sorry I can't try it now):
var newState=$(this).scrollTop() > $( window ).height();
function updateOnScroll(e) {
var oldState=newState;
newState=$(this).scrollTop() > $( window ).height();
if(oldState!=newState) {
if(newState) {
$('.nav li a').animate({"font-size":"100vw"});
} else {
$('.nav li a').animate({"font-size":"1.2vw"});
}
}
}
Just an idea...