I am using the semplice theme on wordpress to build my portfolio website. In the theme I am able to add CSS and JS coding. I would like to make my navbar dissapear when I scroll down and reappear when I scroll up.
I have found coding that should do this, however, it does not work and it does not look like coding which were suggested by semplice for other features. Unfortunately, semplice wont help in providing custom coding anymore.
I have been searching the whole afternoon on an answer. Does anyone have any experience with this? All suggestions are very welcome!!
Thanks in advance!
Tomas
You can set a variable as the window's current scrollY and when the user is scrolling, check is the scrollY is increasing or decreasing (scrolling down or scrolling up) to hide or show the navbar.
<!DOCTYPE html>
<html>
<head>
<style>
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
width: 100%;
position: fixed;
top: 0;
left: 0;
right: 0;
}
li {
float: left;
}
li a {
display: block;
color: white;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
li a:hover {
background-color: #111;
}
body, html{
height: 1000px;
}
</style>
</head>
<body>
<ul id="header">
<li><a class="active" href="#home">Home</a></li>
<li>News</li>
<li>Contact</li>
<li>About</li>
</ul>
<script>
var position = window.scrollY;
window.onscroll = function(){
var scroll = this.scrollY;
if(scroll>position){
//scrolling down
document.getElementById('header').style.display = "none";
} else {
//scrolling up
document.getElementById('header').style.display = "";
}
position = scroll;
}
</script>
</body>
</html>
Related
I'm about to give up, so I'm rewriting this question one more time. I just can't make it work, I have too much left to learn for this to work out. I really tried my best but I need help.
As you can see on my Codepen I managed to make it work "somehow". But I know the calculation is wrong and can't even think about how it could work when scrolling back up.
https://codepen.io/Nimyr/pen/ZEaWpzb
All I want is a navigation like here:
https://www.lieferando.de/speisekarte/bella-italia-bunde
As you can see the navigation sticks to the top and moves the navigation-element thats fitting the currently active section automatically to the left as you scroll down.
I've set up a WordPress Site where I am trying to make the navigation work just like that. Any ideas? :( I'm really lost.
The usecase for this is pretty simple: I want to make a (especially mobile-)user-friendly page that shows a restaurant's menu.
Please don't hesitate to ask any questions if my explanation is weak, I don't know how to formulate it more precisely.
Thanks in advance!
I will also post the code from the Codepen:
HTML
<body>
<nav>
<div class="nav-test">
<ul class="nav-test2">
<li>About</li>
<li>Team</li>
<li>Gallery</li>
<li>Testimonials</li>
<li>Contact</li>
</ul>
</div>
</nav>
<section class="about">
<h1>About</h1>
</section>
<section class="team">
<h1>Team</h1>
</section>
<section class="gallery">
<h1>Gallery</h1>
</section>
<section class="testimonials">
<h1>Testimonials</h1>
</section>
<section class="contact">
<h1>Contact</h1>
</section>
</body>
CSS
* {
margin: 0;
padding: 0;
}
body {
font-family: Verdana, serif;
color: #fff;
}
nav {
position: fixed;
top: 0;
left: 0;
width: 100%;
text-align: center;
background: #515151;
}
.nav-test {
display: flex;
justify-content: center;
}
nav ul {
width: 500px;
overflow: scroll hidden;
display: flex;
flex-wrap: nowrap;
}
nav ul li {
list-style: none;
display: inline-block;
}
nav ul li a {
display: block;
padding: 20px 40px;
text-decoration: none;
color: #fff;
transition: background-color .4s ease;
}
nav ul li a.active {
background-color: #FF0000;
}
section {
padding: 30% 0;
text-align: center;
}
section.about {
background: #888;
}
section.team {
background: skyblue;
}
section.gallery {
background: #aaa;
}
section.testimonials {
background: orange;
}
section.contact {
background: #ccc;
}
JavaScript (please note that this project also contains highlighting the active navigation element through a change in background color. This is purely optional, I need the automatic scroll. But I started with a Codepen created by Kon Kim as a basic structure to figure the rest out. I failed. gg
(function(){
var navLinks = $('nav ul li a'),
navH = $('nav').height(),
section = $('section'),
documentEl = $(document);
documentEl.on('scroll', function() {
var currentScrollPos = documentEl.scrollTop();
section.each(function(){
var self = $(this);
if ( self.offset().top < (currentScrollPos + navH) && (currentScrollPos + navH) < (self.offset().top + self.outerHeight() ) ) {
var
targetClass = '.' + self.attr('class') + '-marker',
width = $(targetClass).outerWidth();
navLinks.removeClass('active'),
$(targetClass).addClass('active');
if ( $(targetClass).offset().left > $('.nav-test2').offset().left)
{
var
newWidth = $(targetClass).offset().left - $('.nav-test2').offset().left;
$('.nav-test2').animate(
{scrollLeft: newWidth},
{duration: 150}
);
return false;
}
}
});
});
})();
Hey out there reading,
i'm making a webpage and im relativly new to JavaScript. I want the Navbar to change Color when its in section Two, while in Section One and Three the Navbar should have the same Color. I watched some tutorials and was able with that code to change the color of the navbar so that in section one and section two the navbar has the right color. When trying out the variables sectionTwo and sectionThree (in order to get the navbars Color to switch back to the color in sectionOne when entering sectionThree) on the other hand it didnt change the colors at the right position (like 100px befor the section). I dont know why this problem accures. If someone knows how to fix it, it would mean the world to me :).
const header = document.querySelector("header")
const sectionOne = document.querySelector(".one")
const sectionTwo = document.querySelector(".two")
const sectionThree = document.querySelector(".three")
const sectionOneOptions = {
}
const sectionOneObserver = new IntersectionObserver(function(entries, sectionOneObserver) {
entries.forEach(entry => {
if (entry.isIntersecting) {
header.classList.add("nav-scrolled")
} else {
header.classList.remove("nav-scrolled")
}
});
},
sectionOneOptions);
sectionOneObserver.observe(sectionTwo)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Arial";
}
body {
width: 100vw;
height: 100vh;
margin: 0;
background: #000;
}
header {
--text: #fff;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 8rem;
z-index: 10000;
padding: 0 1rem 5rem;
display: flex;
justify-content: space-between;
align-items: center;
}
header nav {
margin: auto;
display: flex;
justify-content: center;
align-items: center;
}
header nav li {
flex: 0 0 auto;
list-style: none;
margin-left: 1rem;
}
header nav li a {
text-decoration: none;
padding: 6px, 15px;
color: var(--text);
border-radius: 20px;
}
.nav-scrolled {
--text: #000;
}
.one {
position: relative;
width: 100%;
height: 100vh;
padding: 200px 20vw;
display: flex;
}
.two {
height: 100vh;
position: relative;
padding: 100px 20vw;
background: #fff;
}
.three {
position: relative;
padding: 100px 20vw;
color: #fff;
height: 100vh;
}
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<header>
<nav>
<li>one</li>
<li>two</li>
<li>three</li>
</nav>
</header>
<section>
<div class="one" id="one"></div>
</section>
<section>
<div class="two" id="two"></div>
</section>
<section>
<div class="three" id="three"></div>
</section>
<script src="app.js"></script>
</body>
</html>
Let me know if you need some more Code and not only the snippet to fix this.
Hopefully some hero can help me :).
Greetings
Noel
I did research to try and answer this question, so please take the preface that I am not an expert in IntersectionObserver.
With that preface out of the way,
There were many things I changed from your example to create the desired effect, however the core feature that you would have needed to implement in your example is the option for intersection observers, rootMargin. By adding this option you can give the item on the screen a negative top and bottom margin. This is important, because you do not want the observer to fire until the header is about to cross into the observed section, and you dont want the header to change until just before it crosses back into the next section.
The way I chose to emulate this behavior, is by using the rootMargin option to give a negative margin. This makes the actual element observed begin however many pixels after we specify. For example, an element that is 100px in height, with "0px 0px -20px 0px" as the value for rootMargin in the options object, would not trigger the IntersectionObserver until 20px of the element was scrolled into the viewport height.
With this understanding, we can define our goal. We want to preform an action when the observed element is about to touch the header. We can describe this as the viewport height minus the header height in a negative margin to the bottom would adjust the element just enough to trigger the intersection observer as desired. Because the methods of obtaining margins are not exact, I subtract one from the numbers calculated to adjust for small error. If we set both margins to overlap eachother, we will never have the observer fire.
I also decided to use css variables and set the value of the variable depending on whether or not the element observed scrolled into or out of the viewport.
This code is not able to execute properly in a stack snippet because the viewport option that the intersection observer defaults to in the options is not set correctly for the snippet environment. I have not tested this code in environments that resize.
Hopefully that explanation helps you understand this code. Let me know if you have any questions.
relevant html:
<header>
<nav>
<li>one</li>
<li>two</li>
<li>three</li>
</nav>
</header>
<section id="one">
</section>
<section id="two">
</section>
<section id="three">
</section>
<script src="app.js"></script>
relevant css:
:root {
--header-text-color: white;
}
body {
margin: 0;
}
header {
position: fixed;
top: 0;
width: 100%;
}
header nav {
display: flex;
justify-content: center;
align-items: center;
}
header li {
list-style: none;
padding: 1rem;
font-size: 2rem;
}
header a {
color: var(--header-text-color);
text-decoration: none;
}
section {
height: 120vh;
background: black;
}
#two {
background: white;
}
relevant js:
const header = document.querySelector("header");
const sectionTwo = document.querySelector("#two");
const topMargin = header.offsetHeight - 1;
const bottomMargin = window.innerHeight - header.offsetHeight - 1;
const options = {
rootMargin: `-${topMargin}px 0px -${bottomMargin}px 0px`,
}
const observer = new IntersectionObserver(([entry]) => {
const color = entry.isIntersecting ? "black" : "white";
document.documentElement.style.setProperty('--header-text-color', color);
}, options);
observer.observe(sectionTwo);
I'm just trying to teach myself some (vanilla) Javascript at the moment, so I'm assuming this is probably a pretty basic question.
At the moment, I've already displayed and hidden the hamburger menu with CSS media queries, so when the page is loaded up for the first time, it works exactly as it should.
The problem:
After the JS script is run (on click) to open the hamburger menu and I widen my window again, the hamburger menu stays on the screen along with the nav that's supposed to show up past the breakpoint.
What I have tried is to use an if statement to basically do some sort of Javascript media query magic.
if (window.matchMedia('screen and (max-width: 48.62rem)').matches) {document.getElementById("mobile-nav").style.display = "block";
} else{
document.getElementById("mobile-nav").style.display = "none";
};
What ends up happening is the same thing as before where the hamburger menu stays on screen if I go from a smaller window to a wider one BUT clicking it again makes it vanish. Good stuff, but now when I make my window smaller again, the menu has completely vanished.
I'm fairly new to JS, so what I understand is that the script is run, it overrides the css media queries and keeps the page like that. I'm thinking a loop might be my solution (maybe a while loop?), but I'm not really sure how to go about doing this.
Here's all the HTML, CSS and Javascript:
function openNav(){
document.getElementById("mobile-nav").style.display = "none";
document.getElementById("menu-items").style.width = "100%";
};
function closeNav(){
document.getElementById("menu-items").style.width = "0";
if (window.matchMedia('screen and (max-width: 48.62rem)').matches) {document.getElementById("mobile-nav").style.display = "block";
} else{
document.getElementById("mobile-nav").style.display = "none";
};
};
#nav {
display: none;
}
#mobile-nav{
float:right;
}
.open-nav {
display:block;
cursor: pointer;
margin: 0.5rem 4rem 0 0;
font-size: 35px;
line-height: 70px;
}
.menu-items{
text-align: center;
width: 0%;
overflow-x: hidden;
height: 100vh;
z-index: 50;
position:fixed;
background: rgba(24,24,24,0.9);
transition:0.5s;
display:block;
}
.menu-items a{
clear:right;
display:block;
font-size: 1.25;
padding:1em 0;
transition:0.3s
}
.close-nav{
float:right;
margin:0.5rem 1em 0 0;
font-size: 50px;
color:rgb(206, 206, 206);
}
/* Media Queries*/
#media (min-width: 48.6rem) {
/* Nav */
#nav-bar{
display:flex;
}
#nav {
float:right;
margin:0 5rem 0 0;
display: flex;
}
#nav li {
margin-right: 1em;
}
#mobile-nav {
display: none;
}
<div id="menu-items" class="menu-items">
×
...
...
...
</div>
<nav id="nav-bar">
<!--LOGO-->
<div id="logo"><img src="./img/logo.png" alt="" /></div>
<!--Mobile Nav-->
<div id="mobile-nav">
<span class="open-nav" onclick="openNav()">☰</span>
</div>
<!--Main Nav-->
<ul id="nav">
<li>
...
</li>
<li>
...
</li>
<li>
...
</li>
</ul>
</nav>
Toggling CSS classes is way more cleaner and easier than using JavaScript style attribute. You should use it that way :
var btn = document.querySelector("#responsive-menu");
var nav = document.querySelector("nav");
btn.onclick = function() {
nav.classList.toggle("expand");
}
nav {
display: none;
background-color: #ed0;
}
nav.expand {
display: block;
}
<button id="responsive-menu">Click me</button>
<nav>
Menu
</nav>
And to specify different CSS for some media size, use CSS media queries.
I've been going through problems in positioning navbar even after the fact that its responsive. Problem comes when zooming in and zooming out (except for Mozilla), and I got no choices than asking experts for a solution because I am a noob in coding.
Chrome zoom-out: https://s31.postimg.org/kjnbou0yj/zoom_out_chrome.png
Mozilla zoom-out (also perfect in zoom-in): https://s31.postimg.org/ud3lz1i3v/zoom_out_moz.png
Basically, I want to join my navbar with another div element so that it do not move from its position and I don't know how to use :target etc, and do not even know if target will solve my problem.
My need: I just need my navbar to stick to one size. With current settings, it is working PERFECTLY with MOZILLA ONLY. I don't know why it show blank space in chrome and other browsers when zoom-out and when zoom-in. Working fine with Chrome 100% zoom and working fine with Opera 100% zoom. The problem comes when zooming in or zooming out. Again, it is working perfectly for mozilla in zooming etc, no such problems with mozilla. And my navbar is responsive too.
My guess: I think that attaching this navbar with hidden div class could solve this problem. BUT I am a complete noob in coding and I can just guess.
Here is the code of my navbar:
ul.pnav {
position: relative;
border-top-left-radius: 15px;
border-top-right-radius: 15px;
border: none;
list-style-type: none;
width: 900px;
height: 55px;
margin: auto;
top: 281px;
left: 0;
right: 0;
padding: 0;
overflow: hidden;
background-color: #767676;
z-index: 9999;
}
#-moz-document url-prefix() {
ul.pnav {
top: 286px
}
}
ul.pnav li {float: left;}
ul.pnav li a {
display: inline-block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
transition: 3s;
font-size: 17px;
font-family: Arial;
font-weight: bold;
}
ul.pnav li a:hover {background-color: #111;}
ul.pnav li.icon {display: none;}
#media screen and (max-width:680px) {
ul.pnav li:not(:first-child) {display: none;}
ul.pnav li.icon {
float: right;
display: inline-block;
}
}
#media screen and (max-width:680px) {
ul.pnav.responsive {position: relative;}
ul.pnav.responsive li.icon {
position: absolute;
right: 0;
top: 0;
}
ul.pnav.responsive li {
float: none;
display: inline;
}
ul.pnav.responsive li a {
display: block;
text-align: left;
}
}
I have this in html as a code:
<ul class="pnav">
<li>Home</li>
<li>News</li>
<li>Contact</li>
<li>About</li>
<li class="icon">
☰
</li>
</ul>
This is div class to which I want to attach navbar.
<div class="fornavbar"></div>
I don't know how to proceed further, please help.
Look at this fiddle: https://jsfiddle.net/8qepe4gw/2/
In order for them to align together you just simply put them both inside of a common div like this (.container),
<div class="container">
<ul class="pnav">
<li>Home</li>
<li>News</li>
<li>Contact</li>
<li>About</li>
<li class="icon">☰</li>
</ul>
<div class="fornavbar"></div>
</div>
And then you assign a width to the .container, and then you can give both the .pnav and .fornavbar a width of 100% so they stretch all the way out inside of the container, as in they have the same width.
Now the reason why it only worked in firefox is probably because of this part of the code:
#-moz-document url-prefix() {
ul.pnav {
top: 286px
}
}
Because #-moz-document only targets firefox.
It's still gonna work in all browsers now though with the new code I added in the fiddle so you shouldn't have to worry about it, perhaps even delete that part of the CSS code(?).
I'm trying to put together a site that has a welcome-type screen followed by a header/navigation that scrolls to the top of the page and is then fixed, remaining at the top of the page as the user scrolls on. The solution I have works in most browsers, except in the desktop touch version of Chrome I can't stop the header/nav from bouncing around once it reaches the top. I've looked at at least 10 Stack Overflow questions that address this problem, and I've tried a lot of different tutorials and plugins but none of them seem to work for me. I know it's possible because the technique appears on http://laravel.com, and the header/nav is ROCK-SOLID when it reaches the top and becomes fixed. This is what I have now:
html {
height: 100%; }
body {
height: 100%; }
#welcome {
background-color: grey;
height: 100%; }
#header {
background-color: white;
box-shadow: 4px 4px 4px #888888;
height: 90px;
opacity: .93;
position: absolute;
width: 100%; }
#header.fixed {
position: fixed;
top: 0;
width: 100%; }
#nav {
position: absolute;
bottom: 30px;
right: 2%; }
#nav a {
color: black;
letter-spacing: 1px;
line-height: 1.25em;
padding-left: 17px;
text-decoration: none;
text-rendering: optimizelegibility;
text-transform: uppercase; }
#about {
height: 2000px; }
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<section id="welcome"></section>
<header id="header" class="container">
<nav id="nav">
One
Two
Three
Four
</nav>
</header>
<main>
<section id="about" class="container">
</section>
</main>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$(document).scroll(function() {
var top = $(document).scrollTop();
var viewport = $("#welcome").height();
$('#header').toggleClass("fixed", top >= viewport);
});
});
</script>
</body>
May be jquery toggle make it.
$(document).ready(function() {
$(document).scroll(function() {
var top = $(document).scrollTop();
var viewport = $("#welcome").height();
if (top >= viewport ) {
$('#header').addClass("fixed");
} else if ($('#header').hasClass('fixed')) {
$('#header').removeClass('fixed')}
});
});
http://jsfiddle.net/molo4nik11/zvom6o5w/
I think this is working solution.
http://jsfiddle.net/molo4nik11/zvom6o5w/3/
#header {
background-color: white;
box-shadow: 4px 4px 4px #888888;
height: 90px;
opacity: .93;
position: relative;
width: 100%;
}
#header.fixed {
position: fixed;
top: 0;
width: 100%;
}
It has been a long time, and this is no longer an issue, but at the time chrome was not able to keep this header in place without it appearing "jumpy". I was able to fix it by adding
-webkit-transform: translateZ(0);
to the .fixed class. Although this didn't have any bearing on the visual styles that were applied, using the transform property would cause chrome to treat it as a 3d element and devote more resources to it.
As I mentioned before, this doesn't seem to be an issue anymore, and I have since been able to remove this hack without the old problem recurring.