I am new to web development.I met a problem when designing a scrolling navigation bar.
I used a bootstrap grid and jquery for this. If I don't scroll down and just resize the window, then everything is fine. The navigation bar is resized and in the center of the window. But after I scroll down, the size of navigation bar will be fixed. Its size won't change when I make window larger(it will be smaller if I make window smaller, but not centered). This may caused by setting width: nav.width() in js file, but I don't know how to fix it.
This is a new account so I don't have enough reputation to upload images. I will try to describe it using words. For example, at beginning, the parent of navigation bar is 1140px, the width of navigation bar is 100%, so its size is 1140px. If I resize the window, let us say the width of its parent is 720px, then the navigation bar width is also 720px. Then if I scroll down, the callback function in js will run, it will set the width to 720px, which is a fixed value, thus it won't be responsible any more. Now, if I resize window to make its parent back to 1140px, the width of navigation bar is 720px rather than 1140. So how to fix this?
<div class="container">
<div class="row">
<div class="col-md-12">
<header id="home" style="height:300px">
<nav id="nav-wrap">
<ul id="nav" class="nav">
<li class="current">
Home
</li>
<li class="smotthscroll">
About
</li>
<li class="smotthscroll">
Portfolio
</li>
<li class="smotthscroll">
Skills
</li>
<li class="smotthscroll">
Contact
</li>
</ul>
</nav>
</header>
</div>
</div>
</div>
CSS
#nav-wrap {
font: 22px 'opensans-bold', sans-serif;
width: 100%;
margin: 0 auto;
left: 0;
top: 0;
}
ul#nav {
text-align: center;
padding: 0;
width: 100%;
background: rgba(0, 0, 0, 0.3);
z-index: 2;
}
ul#nav li {
height: 48px;
display: inline-block;
}
ul#nav li a {
color:white;
padding: 8px 13px;
display: inline-block;
text-align: center;
}
$(function() {
var nav = $('#nav');
var navHomeY = nav.offset().top;
var isFixed = false;
var navWrap = $('#nav-wrap');
var $w = $(window);
$w.scroll(function () {
var scrollTop = $w.scrollTop();
var shouldBeFixed = scrollTop > navHomeY;
if(shouldBeFixed && !isFixed) {
nav.css({
position: 'fixed',
width: nav.width()
});
isFixed = true;
}else if (!shouldBeFixed && isFixed) {
nav.css({
position: 'static'
});
isFixed = false;
}
});
});
Your problem most likely comes from this part.
var shouldBeFixed = scrollTop > navHomeY;
if(shouldBeFixed && !isFixed) {
nav.css({
position: 'fixed',
width: nav.width()
});
isFixed = true;
Try inversing or removing that part all together. It is saying if the navbar is not at the top, add a position of fixed to it as well as nav.width(), whatever you set that to equal - and this is precisely the opposite of what you want because it's what your problem is according to the question.
Related
I am working on a small site, where I am trying to learn how different navigation menus can interact with each other with html, css and js. My issue is that my top navigation bar does not interact correctly with my sidebar navigation. When i add the sticky class to my top navigation bar with js (= scrolling) and sidenavigation is open (= margin left on sidenavigation is 350px) my top navigation jumps out of the page. Is there a way to compensate for this?
Here is my js for fixed top navigation menu when scrolling:
let sectionMain = document.getElementById("section-main");
let navbar = document.getElementById("navbar");
let navPos = navbar.getBoundingClientRect().top;
window.addEventListener("scroll", e => {
let viewportHeight = window.innerHeight;
let scrollPos = window.scrollY;
if (scrollPos > navPos) {
navbar.classList.add('sticky');
sectionMain.classList.add('navbarOffsetMargin');
} else {
navbar.classList.remove('sticky');
sectionMain.classList.remove('navbarOffsetMargin');
}
});
window.addEventListener("scroll", e => {
let viewportHeight = window.innerHeight;
let scrollPos = window.scrollY;
if (scrollPos > navPos) {
sidenavid.classList.add('sticky');
} else {
sidenavid.classList.remove('sticky');
}
});
CSS for top navigation:
#navbar.sticky {
position: fixed;
top: 0;
box-shadow: 5px -1px 6px 5px #dad7d7;
clip-path: inset(-5px -5px -200px -0px);
background-color: #e3f4f1;
transition: 0.5s;
z-index: 1000;
}
As mentioned I also have a sidenavigation bar, that is opened/closed (width 0/350px) with a button:
function toggleNav() {
var element = document.getElementById("sidenavid");
if (element.style.width == "350px") {
element.style.width = "0px";
} else {
element.style.width = "350px";
}
var element = document.getElementById("main");
if (element.style.marginLeft == "350px") {
element.style.marginLeft = "0px";
} else {
element.style.marginLeft = "350px";
}
HTML:
<body>
<header>
<div id="sidenavid" class="sidenavclass">
<a href="#" class="closeicon">
<h1 class="h1-top" aria-hidden="true">h1 title</h1>
</a>
Menu
Menu
Menu
Menu
</div>
<div id="main">
<nav id="navbar">
<span onclick="toggleNav()">
<div class="navbar-brand">
<i onclick="toggleIcon(this)" class="fa fa-bars fa-2x"></i>
</div>
</span>
<ul class="nav-list" id="navlist">
<li class="nav-list-items">Home</li>
<li class="nav-list-items dropdown">Products
<div class="dropdown-content">
Product #1
Product #2
</div>
</li>
<li class="nav-list-items dropdown">Information
<div class="dropdown-content">
Courses
Tutorials
</div>
</li>
<li class="nav-list-items">Contact</li>
</ul>
</nav>
<section id="section-main">
<div class="article-container">
<article class="section-container">
<h1>This is the title of the section</h1>
<p class="section-text">
Here is the main section text in a paragraph tag that is supposed to xyz
</p>
</article>
</div>
</section>
<section id="section-main">
<div class="article-container">
<article class="section-container">
<h1>This is the title of the section</h1>
<p class="section-text">
Here is the main section text in a paragraph tag that is supposed to xyz
</p>
</article>
</div>
</section>
</div>
</header>
<script src="https://kit.fontawesome.com/9beebcdd4b.js" crossorigin="anonymous"></script>
<script src="js/scripts.js"></script>
</body>
My top navigation bar does not seem to work with my side bar, as it is pushed out of the viewport when it is scrolling (class sticky is added) and side bar is open (width of sidenav 350px. I tried compensating by adding following if statement to my code, but it does not seem to work as intended.
var element = document.getElementById("navbar");
if (main.style.marginLeft == "350px" || navbar.classList.contains('sticky')) {
element.style.width = "calc(100% - 350px)";
} else {
element.style.width = "100%";
}
Here is full jsfiddle: https://jsfiddle.net/louvalman/xf8kwrv9/6/ (site only works in full screen so far)
Thanks in advance to anyone willing to help out a newbie!
I think it is pretty funny you add a class called sticky but it sets the position value of the #navbar to fixed.
If you would set the position to sticky instead of fixed you would already almost get the result that you are after.
The only thing to change is then to add a space between the content of the navbar using justify-content: space-between. You can use this instead of the margin auto on the nav list class you've set.
#navbar {
display: inline-flex;
align-items: center;
justify-content: space-between;
width: 100%;
position: relative;
}
#navbar.sticky {
position: sticky;
top: 0;
box-shadow: 5px -1px 6px 5px #dad7d7;
clip-path: inset(-5px -5px -200px 0px);
background-color: #e3f4f1;
transition: 0.5s;
z-index: 1000;
}
I have a slideToggle(); menu which is positioned absolutely on the bottom of the page. The slideToggle(); is going to show big content and sometimes this ends up being taller than the viewport.
My question is, how do I prevent the menu to:
1 - Not going on the top of the logo as they are both on the sidebar of my website
2 - When it reaches a height taller than the viewport, this will be scrollable
To explain myself better, I'd like the content of my menu, once is shown by slideToggle(); and whenever is taller than the viewport's height minus logo's height, to stop right below my logo and to continue expanding downwards if that's the case, and that I am able to scroll it down despite its position:absolute.
Does anyone have an idea on how I can achieve that? Please have a look at the snippet.
$( "#click" ).click(function() {
$( ".content" ).slideToggle();
});
.logo {
background: #11a1d6;
margin: 10px;
height: 100px;
width: 300px;
}
.list {
width: 200px;
position: absolute;
bottom: 20px;
}
.content {
background: #082965;
height: 10000px;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="logo"></div>
<ul class="list">
<li id="click">
Click me
<div class="content"></div>
</li>
</ul>
You would need an additional wrapper for your .content that has overflow-y: hidden and height set to the max height available. To determine this height you need a function that runs after your DOM is loaded and adds this to your .content-wrapper:
function setContentMaxHeight() {
let containerHeight = $('.container').height()
let logoMargin = $('.logo').offset().top;
let logoHeight = $('.logo').height();
let listHeight = $('.list').height();
let listMargin = 20;
let maxHeight = containerHeight - ( 2 * logoMargin ) - logoHeight - ( 2 * listMargin) - listHeight;
$('.content-wrapper').css({
'height': maxHeight + 'px'
});
}
$(document).ready(function(){
setContentMaxHeight();
window.onresize = setContentMaxHeight; // detect the window resize and rerun the function
});
working fiddle
enter image description hereI am having issues while implementing Sidebar with mouse scrolling. If i drag the scroll manually with mouse, the sidebar leaves some white space and not able to map with the page height.
$(window).on('scroll resize', function() {
var marginTop = $(window).scrollTop();
var marginFooter = $('#divFooter').height();
var limit = $("#divMain").height() - $("#navMenu").height();
if (marginTop < limit) {
$("#navMenu").css("margin-top", marginTop);
}
});
#navMenu {
padding-left: 0;
padding-right: 0;
float: left;
height: 100%;
z-index: 10001;
}
#divMain {
padding: 0 20px;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="navMenu">
<ucl:ucNavMenu ID="ucNavMenu" runat="server" />
</div>
<div class="clearfix visible-xs-block"></div>
//div for entire page content inculding page header menu
<div id="divMain"> content </div>
I have created a sticky scroll bar but when I scroll down it shows some glitch and put the scroll bar back to top again (Resolution 1920x1080). It works fine on smaller resolution.
Javascript:
$(document).ready(function() {
// Cache selectors for faster performance.
var $window = $(window),
$mainMenuBar = $('#mainMenuBar'),
$mainMenuBarAnchor = $('#mainMenuBarAnchor');
// Run this on scroll events.
$window.scroll(function() {
var window_top = $window.scrollTop();
var div_top = $mainMenuBarAnchor.offset().top;
if (window_top > div_top) {
// Make the div sticky.
$mainMenuBar.addClass('stick');
$mainMenuBarAnchor.height($mainMenuBar.height());
}
else {
// Unstick the div.
$mainMenuBar.removeClass('stick');
$mainMenuBarAnchor.height(0);
}
});
});
HTML
<div id="top" style="width: 100%; height: 100px; background: #ccc; margin: 0;">Top Panel</div>
<div id="mainMenuBarAnchor"></div>
<div id="mainMenuBar" style="width: 100%; height: 50px; background: #999; margin: 0;">Sticky Panel</div>
<div id="content" style="width: 100%; height: 630px; background: #ccc; margin: 0;">
Content Panel
<br/>
<br/>
This panel will not jump when the sticky panel becomes stuck.
</div>
CSS
.stick {
position: fixed;
top: 0;
}
Here is the snap of the scroll bar which I cannot scroll down using mouse roller. The scroll bar needs to be dragged down explicitly
http://i67.tinypic.com/16i7c5y.png
Here is a fiddle for you to see https://jsfiddle.net/mnaveed76/jsm3quk9/9/
Update:
The problem occurs in Firefox browser only.
I have a drop down menu that sits inside a header that is set to position: fixed. When viewed on a mobile device, I want the header to remain fixed, but when the menu is activated, jQuery dynamically changes the header's position to relative. That works fine (see code below), but there are a few problems that I need to fix. If the menu-toggle link is clicked again (closing the menu), the header does not return to its previous state "relative". Is there a way to do this? I also notice a flicker, so let's say you scroll half way down the page, then click on the menu to open it, the page sort of jumps and does not scroll back to the top where the menu is located inside the header as it should. I would prefer a pure CSS solution, but that seems impossible. I COULD set the rules so that if it's less than 499 pixels wide, the header gets positions "relative", but then usability fails, as a user will have to scroll up to the top of the page to access the drop down menu.
Any help would be greatly appreciated.
Here is my code:
HTML
<header role="banner" class="secondary">
<em>Menu</em> <span aria-hidden="true"></span>
<nav id="nav" role="navigation">
<ul class="menu set">
<li class="subnav">
Link
<ul class="sub-menu">
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</li>
</ul>
</nav>
</header>
CSS
header[role="banner"] {
width: 100%;
background: #fff;
display: block;
margin: 0 auto;
padding: 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.25);
z-index: 10000;
}
#media all and (min-width: 500px) {
header[role="banner"] {
position: fixed;
top: 0;
left: 0;
clear: both;
height: auto;
display: block;
}
}
#media all and (max-width: 499px) {
header[role="banner"] {
position: fixed;
}
}
JAVASCRIPT
$(document).ready(function() {
$('body').addClass('js');
var $menu = $('#nav'),
$menulink = $('.menu-toggle'),
$menuTrigger = $('.subnav > a');
$menulink.click(function(e) {
e.preventDefault();
$menulink.toggleClass('active');
$menu.toggleClass('active');
});
var add_toggle_links = function() {
if ($('.menu-toggle').is(":visible")){
if ($(".toggle-link").length > 0){
}
else{
$('.subnav > a').before('<span class="toggle-link">Open</span>');
$('.toggle-link').click(function(e) {
var $this = $(this);
$this.toggleClass('active').siblings('ul').toggleClass('active');
});
}
}
else{
$('.toggle-link').empty();
}
}
add_toggle_links();
$(window).bind("resize", add_toggle_links);
});
$(document).ready(function() {
$('.menu-toggle').click(function() {
if ($( document ).width() < 499)
$('header[role="banner"]').css('position', 'relative');
});
});
So you don't actually have any js code in there that will switch the position of your header between fixed and relative.
What I would do is maybe toggleClass on your header.
$(document).ready(function() {
$('.menu-toggle').click(function() {
if ($( document ).width() < 499){
$('header[role="banner"]').toggleClass('active');
}
});
});
Then in your css
header[role="banner"] {
position: fixed;
}
header[role="banner"].active {
position: relative;
}
The screen jump you're getting is probably from changing the position from fixed to relative, because relative will add the header back to the normal page flow. So to fix this, you could also toggle the class of whatever is below your header, so when active, it has a margin-top of 0, and when inactive, it has a margin-top equal to the height of the header.