Javascript - Move active link to top of navigation if window-width <= 800px - javascript

I have a responsive navigation which is fixed at the top and goes from horizontal to vertical if screensize is <=800 px wide.
Now I'm trying to move the currently active link to the top of the navigation if the screen size is <=800 px wide, but I can't seem to find a way.
I tried Javascript but it won't keep the currently active link at the top since the page refreshes or changes when a link is clicked.
I tried to put the loop in an if-statement but that doesn't work, so I removed the if-statement.
I would really appreciate it if someone could help me solve this problem.
Here's the Javascript:
/*------------------------move active link to top------------------------*/
function moveLink(){
var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var list = document.getElementById('nav').childNodes;
for (var i = 0; i < list.length; i++) {
list[i].addEventListener('click',function()
{nav.insertBefore(this, nav.childNodes[0])});
}
}
Here's the navigation html:
<nav>
<ul id="nav" class="topNav">
<li><a onclick="moveLink()" href="/">Placeholder1</a></li>
<li><a onclick="moveLink()" href="Placeholder1.html">Placeholder1</a></li>
<li><a onclick="moveLink()" href="Placeholder1.html">Placeholder1</a></li>
<li><a onclick="moveLink()" class="active" href="licenses.html">Placeholder1 / FAQ</a></li>
<li><a onclick="moveLink()" href="Placeholder1.html">Placeholder1</a></li>
<li><a onclick="moveLink()" href="contact.php">Placeholder1</a></li>
<li class="icon"><a href="javascript:void(0);" onclick="myFunction()">
<img alt="open menu" src="graphics/menu.png" style="height: 30px; width: 30px;"></a>
</li>
</ul>
I have two stylesheets and the menu opens and closes via Javascript.
Here's my mobile css:
/*------------------------navigation------------------------*/
.topNav {
z-index: 1;
list-style-type: none;
margin: 0 auto;
padding: 0;
overflow: hidden;
position: fixed;
top: 0;
width: 100%;
font-size: 0px;
background-color: rgba(0,0,0,0.8);
box-shadow: 0px 0px 8px 0px rgba(0,0,0,0.75);
}
.topNav li {
display: inline;
}
.topNav li a {
font-size: 12px;
display: inline-block;
color: #fff;
text-decoration: none;
transition: color 0.2s ease-in-out;
line-height: 38px;
padding: 0px 0px 0px 20px;
}
.topNav li a:hover {
color: #777;
}
.topNav li a.active {
color: #999;
}
/*------------------------responsive navigation closed------------------------*/
.topNav li:not(:first-child) {
display: none;
}
.topNav li.icon {
float: right;
display: inline-block;
height: 38px;
vertical-align: middle;
transition: opacity 0.2s ease-in-out;
margin: 4px 5px 0px 0px;
width: 30px;
height: 30px;
padding-right: 20px;
}
.icon:hover {
opacity: 0.5;
}
/*------------------------responsive navigation opened------------------------*/
.topNav.responsive {
position: fixed;
top: 0px;
}
.topNav.responsive li.icon {
margin: 0 0 0 0;
position: absolute;
top: 4px;
right: 25px;
width: 30px;
height: 30px;
padding-right: 0px;
z-index: 1;
}
.topNav.responsive li.icon:hover {
opacity: 0.5;
}
.topNav.responsive li {
float: none;
display: inline;
}
.topNav.responsive li a {
display: block;
}
thanks in advance,
Ken

I think you could do this just using CSS using flexbox and order property.
#media (max-width: 800px) {
nav ul {
display: flex;
flex-direction: column;
}
.active {
order: -1;
}
}
order: -1 ensures that the list item will move to the top of the column.
I moved the class active to the li, instead of the a, to make this work a little easier.
codepen
snippet
body {
font-family: sans-serif;
}
nav {
background: grey;
padding: 20px;
}
nav ul {
list-style-type: none;
}
nav ul li {
display: inline-block;
margin-right: 8px;
}
nav ul li:last-child {
margin-right: 0;
}
nav ul li a {
text-decoration: none;
color: white;
}
#media (max-width: 800px) {
nav ul {
display: flex;
flex-direction: column;
}
.active {
order: -1;
}
}
<nav>
<ul id="nav" class="topNav">
<li><a onclick="moveLink()" href="/">BEATS</a></li>
<li><a onclick="moveLink()" href="sounds.html">SOUNDS</a></li>
<li><a onclick="moveLink()" href="services.html">SERVICES</a></li>
<li class="active"><a onclick="moveLink()" href="licenses.html">LICENSES / FAQ</a></li>
<li><a onclick="moveLink()" href="downloads.html">DOWNLOADS</a></li>
<li><a onclick="moveLink()" href="contact.php">CONTACT</a></li>
</ul>
</nav>

Related

NavBar Auto Toggling On

I am using the onclick method for turning my navbar on/off the problem that I'm having is when I adjust my screen size to mobile view my nav auto turns on.
I'm not very good at JavaScript. I have just started learning it so just fiddled around and absolutely nothing worked for me. Someone told me to put aria-expanded on my HTML so also tried that:
function closeNav() {
document.getElementById("nav_bar").style.height = "0%";
document.getElementById("open-btn").style.display = "inline-block";
document.getElementById("close-btn").style.display = "none";
}
function openNav() {
document.getElementById("nav_bar").style.height = "100%";
document.getElementById("open-btn").style.display = "none";
document.getElementById("close-btn").style.display = "inline-block";
}
body {
background: url(images/bg-img-01.jpg) no-repeat;
background-size: cover;
}
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#nav_bar {
background: radial-gradient( ellipse at top, rgba(196, 199, 200, 0.8), rgba(250, 255, 255, 0.02) 60%, rgba(0, 0, 0, 0) 1%);
position: fixed;
top: 0;
width: 100%;
}
#nav_bar>img {
display: none;
}
.nav {
background: none;
overflow: hidden;
display: flex;
margin-inline: auto;
flex-direction: row;
justify-content: space-around;
align-items: center;
list-style: none;
width: 65%;
left: 20%;
padding: 1.4em;
}
.list-item {
text-decoration: none;
color: #CBD5DF;
font-weight: bolder;
}
.list-item {
position: relative;
}
.list-item::before {
position: absolute;
content: "";
background-color: #535792;
height: 4px;
width: 0%;
top: 25px;
transition: all .3s ease-in;
}
.list-item:hover::before {
width: 100%;
}
.list-item:hover {
color: #C4C7C8;
}
#close-btn,
#open-btn {
display: none;
}
#media only screen and (max-width:768px) {
#nav_bar>img {
display: block;
position: absolute;
width: 10em;
left: 20%;
top: 10%;
}
#nav_bar {
width: 100%;
position: fixed;
z-index: 1;
top: 0;
overflow: hidden;
transition: 0.5s;
}
.nav {
position: relative;
display: flex;
flex-direction: column;
gap: 1.2rem;
top: 20%;
width: 100%;
text-align: center;
margin-top: 30px;
}
.list-item {
text-decoration: none;
display: block;
color: #ffdada;
font-size: 1.5rem;
transition: 0.3s;
}
#close-btn,
#open-btn {
display: block;
position: absolute;
right: 25px;
top: 20px;
font-size: 2rem;
color: #818181;
transition: all 0.3s;
}
#close-btn:hover {
color: #fff;
}
<body>
<div id="nav_bar">
<a href="#" id="close-btn">
<i aria-expanded="false" onclick="closeNav()" class="bi bi-x-lg"></i>
</a>
<img src="assests/images/moon.png" alt="" />
<div class="nav">
<a class="list-item" href="#">Home</a>
<a class="list-item" href="#">About Me</a>
<a class="list-item" href="#">Projects</a>
<a class="list-item" href="#">C.V</a>
<a class="list-item" href="#">Contact</a>
</div>
</div>
<a aria-expanded="false" href="#" id="open-btn" onclick="openNav()"><i class="bi bi-list"></i
></a>
<script src="assests/nav.js"></script>
</body>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
Make use of the classList.toggle function that adds/remove a class from the Navbar. In this example, I add or remove the class d-none that has the property: display: none in CSS. With that you can hide or show the navbar by pressing the same button with a single line of code:
const BUTTON = document.querySelector('#toggle_navBar');
const NAV = document.querySelector('nav');
BUTTON.addEventListener('click', function() {
NAV.classList.toggle('d-none');
});
body {
background: url(images/bg-img-01.jpg) no-repeat;
background-size: cover;
}
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
nav {
background: radial-gradient( ellipse at top, rgba(196, 199, 200, 0.8), rgba(250, 255, 255, 0.02) 60%, rgba(0, 0, 0, 0) 1%);
position: sticky;
top: 0;
width: 100%;
}
menu {
background: none;
overflow: hidden;
display: flex;
margin-inline: auto;
flex-direction: row;
justify-content: space-around;
align-items: center;
list-style: none;
width: 65%;
left: 20%;
padding: 1.4em;
}
nav li a {
text-decoration: none;
color: #CBD5DF;
font-weight: bolder;
position: relative;
}
nav li a::before {
position: absolute;
content: "";
background-color: #535792;
height: 4px;
width: 0%;
top: 25px;
transition: all .3s ease-in;
}
nav li a:hover::before {
width: 100%;
}
nav li a:hover {
color: #C4C7C8;
}
.d-none {
display: none;
}
<nav>
<img src="assests/images/moon.png" alt="" />
<menu>
<li><a class="list-item" href="#">Home</a></li>
<li><a class="list-item" href="#">About Me</a></li>
<li><a class="list-item" href="#">Projects</a></li>
<li><a class="list-item" href="#">C.V</a></li>
<li><a class="list-item" href="#">Contact</a></li>
</menu>
</nav>
<button id="toggle_navBar">Toggle NavBar</button>
A few changes I made were for semantic reasons. You should use semantic tags if possible and have accessibility in mind. Accessibility is also part of SEO-ratings!
I think the basic idea would be to have a button toggle some variable and then update the UI according to the value of that variable.
You can do this in several ways, but here is an example of a simple way to do it:
// Get your toggle button element
const toggle = document.querySelector(".nav-toggle");
// Get your nav element
const nav = document.querySelector(".nav");
// Create a variable to hold the state of your nav
let navIsOpen = false;
// Listen for clicks on your nav toggle button
toggle.addEventListener('click', () => {
// Update the nav state variable
navIsOpen = !navIsOpen;
// run a function that will update the nav "styles"
updateNav();
})
// This function will update the UI state according to the value of the navIsOpen variable. Here you can update all things you need, like your navbar, your toggle button, ...
function updateNav() {
navIsOpen
?
nav.classList.add('nav--is-open') :
nav.classList.remove('nav--is-open');
}
.nav {
margin-top: 1rem;
padding: 1rem;
background-color: lightgrey;
}
.nav--is-open {
background-color: purple;
color: white;
}
<button class="nav-toggle">Toggle nav</button>
<nav class="nav">
Your nav here
</nav>

Navbar scroll effect not working when having background color

I have a navbar having a gradient type background(slightly black, to transparent).
I wanted the navbar to turn completely black when scrolling, and I wrote the necessary JavaScript code, but the color changes only when I remove that background color gradient from the CSS, otherwise, it doesn't work. Is there a solution for this?
HTML Code:
<section id="header" class="headerr">
<img src="images/logo.png" class="logo">
<div>
<ul id="navbar">
<li><a class="active" href="why.html">Why Snap Smile</a></li>
<li>Solutions</li>
<li>Pricing</li>
<li>About</li>
<li>Gallery</li>
<li><i class="fa-solid fa-headset fa-2x"></i></li>
</ul>
</div>
CSS code:
body {
font-family: 'Montserrat', sans-serif;
width: 100%;
margin: 0;
background-color: #121212;
}
/* Header Section */
#header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 80px;
background: rgb(0,0,0);
background: linear-gradient(180deg, rgba(0,0,0,0.6629026610644257) 0%, rgba(9,9,121,0) 57%);
z-index: 999;
position: sticky;
top: 0;
left: 0;
}
.headerr__black{
background-color: #121212;
}
#navbar {
display: flex;
align-items: center;
justify-content: space-between;
}
#navbar li {
list-style: none;
padding: 0 20px;
position: relative;
}
#navbar li a {
text-decoration: none;
font-size: 1rem;
font-weight: 600;
color: #ffffff;
transition: 200ms ease-in-out;
}
#navbar li a:hover,
#navbar li a.active {
color: #e50914;
}
#navbar li a.active::after,
#navbar li a:hover::after {
content: "";
width: 30%;
height: 3px;
background: #e50914;
position: absolute;
bottom: -6px;
left: 20px;
}
.logo {
width: 10rem;
}
JavaScript Code:
const nav=document.getElementById('header');
window.addEventListener('scroll',function(){
if(window.scrollY >= 100){
nav.classList.add('headerr__black');
}
else{
nav.classList.remove('headerr__black');
}
});
I think this may happen because #header selector (id selector) has a higher priority than .header__black (class selector).
Can you try to update your style, so the .headerr__black styles have higher priority ? For example:
/*
* Now the selector specificity is {id} + {class},
* Which is higher than just {id} for #header
*/
#header.headerr__black {
background-color: #121212;
}
Doc - https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

How to make the menubar work like a proper menubar without bootstrap?

How do you a menubar work properly menubar with the functions:
*Clicking on hamburger-icon will display the nav-links.
*Clicking on nav-links will hide the menubar.
(without using bootstrap, but doing it from scratch)
I understand that many have asked this question. I have looked at many different solutions, with JS and Jquery, and I have encountered several problems because I really dont understand JS or Jquery fully.
This is how far I´ve gotten. Go to my website hung.no so you can see the problem. On my website, you should minimize the window to get to the hamburger bar. Then you should click on that bar. After that click on one of the nav-links. It closes, but when you try to click on the hamburger bar again, it does not work.
//Navbar collapses to menubar
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
//Jquery code ON MY WEBSITE. I cannot display it here.
//This is the source
//<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
//$(document).ready(function(){
// $(".nav-link").click(function(){
// $(".nav-toggle").hide();
// });
//});
//$(document).ready(function(){
// $(".nav-show").click(function(){
// $(".nav-toggle").show();
// });
//});
/*mobile navbar*/
.topnav .icon {
display: none;
}
.topnav {
overflow: hidden;
background-color: #fff;
width: 100%;
position: fixed;
z-index: 1000;
}
.topnav a {
float: right;
display: block;
color: #000;
padding: 10px 10px;
text-decoration: none;
font-size: 12px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav .icon {
display: none;
}
#media screen and (max-width: 700px) {
.topnav a:not(:first-child) {display: none;}
.topnav a.icon {
float: right;
display: block;
}
#myNavbar{
display: none;
}
}
#media screen and (max-width: 700px) {
.topnav.responsive {
position: fixed;
width: 100%;
top: 0;
}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none!important;
display: block;
text-align: left;
}
.mob-font-size{
font-size: 22px;
width: 100%;
}
.mob-logo-size{
width: 177px;
height: 260px;
}
}
/*dekstop navbar*/
#myNavbar{
position: fixed;
width: 100%;
background: white;
border-style: solid;
border-width: 0 0 1px 0;
border-color: #E8E8E8;
z-index: 9999;
}
.float-right-nav{
padding: 8px 15px;
float: right;
}
#myNavbar ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
}
li a {
display: block;
color: #000;
text-align: center;
text-decoration: none;
}
div.container
{
margin: 0 auto;
padding: 6px 3em;
text-align: center;
}
div.container a
{
color: #000;
text-decoration: none;
font: 12px Raleway-medium;
margin: 0px 20px;
padding: 5px 5px;
position: relative;
z-index: 1;
cursor: pointer;
}
<!--desktop navbar-->
<div id="myNavbar">
<div class="container">
<ul>
<li style="float:left"><img src="svg/navlogo.svg" alt=""></li>
<li class="float-right-nav"><span class="medium">KONTAKT</span></li>
<li class="float-right-nav"><span class="medium">PRIS</span></li>
<li class="float-right-nav"><span class="medium">GARANTIER</span></li>
<li class="float-right-nav"><span class="medium">OM MEG</span></li>
</ul>
</div>
</div>
<!--Mobile navbar the classes nav-link and nav-toggle is used in the Jquery code located in the Javascript-section in this Code Snippet-->
<div class="topnav" id="myTopnav">
<a style="float:left" href="#home"><img src="svg/navlogo.svg" alt="" height="20" width="18"></a>
<a class="nav-link nav-toggle"href="#Kontakt"><span class="medium">KONTAKT</span></a>
<a class="nav-link nav-toggle"href="#Pris"><span class="medium">PRIS</span></a>
<a class="nav-link nav-toggle"href="#Garantier"><span class="medium">GARANTIER</span></a>
<a class="nav-link nav-toggle"href="#Ommeg"><span class="medium">OM MEG</span></a>
☰
</div>
I see a problem in your javascript function "myFunction"
When you click a first time, you append class "resposive", but when you click again the flow moves to "else" and then it remove "responsive" so you are removing that behaviour.
If you remove that flow then the nav works fine.

CSS horizontal submenu

I'm working on the navigation bar for a website and currently the main menu is complete. However, the "Services" and "Products" buttons need to each have their own sub-menu. The sub-menu should normally be hidden from view and appears when the user mouse-overs on the respective button.
Here is a fiddle with the desired result. Obviously, I'd rather not use any javascript if possible.
The idea I had initially was to have sub-menu have position: absolute with a z-index value lower than that of the main-menu, so that it can slide underneath the main-menu. However, doing so messes up with the width if I give it width: 100% and since my site is responsive, I avoid static widths.
I also tried doing with relative positioning, but that doesn't work either.
Another thing I don't like with that approach is that the markup for the main menu and sub-menu get split. Is it possible to get the above result, but with this markup?
<nav>
<ul class="nav">
<li role="presentation" class="active">Home</li>
<li role="presentation">Services
<ul>
<li role="presentation">Link 1
<li role="presentation">Link 2
</ul>
</li>
<li role="presentation">Products
<ul>
<li role="presentation">Link 3
<li role="presentation">Link 4
</ul>
</li>
<li role="presentation">About</li>
<li role="presentation">Contact</li>
</ul>
</nav>
Here is my code:
CSS
body {
font-size: 0;
}
.bodyframe {
display: inline-block;
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.6);
}
.div_container {
max-width: 1460px;
width: 100%;
display: inline-block;
margin: 0 auto;
}
header {
width: 100%;
height: 49px;
}
.nav {
display: block;
position: relative;
list-style: none;
background: #304770;
z-index: 10;
}
.nav li {
display: inline-block;
background-color: #304770;
margin: 0 5px;
}
.nav li a {
padding: 12px 15px;
font-size: 18px;
color: #EFEFEF;
display: block;
}
.nav li.active a {
color: orange;
}
.nav li.active a:before {
width: 100%;
}
.nav li a:hover {
background-color: #304770;
color: orange;
transition: color 0.25s;
}
.nav li a:before {
content: "";
display: block;
position: absolute;
left: 0;
bottom: 0;
height: 3px;
width: 0;
background-color: orange;
-webkit-transition: width 0.2s;
transition: width 0.2s;
}
.nav li:nth-last-of-type(1) a:after {
display: none;
}
.nav li a:hover:before {
width: 100%;
}
.nav li a:after {
content: "";
display: block;
position: absolute;
right: -8px;
top: 21px;
height: 6px;
width: 6px;
background: #ffffff;
opacity: .5;
}
.subnav {
list-style-type: none;
display: block;
position: relative;
top: -49px;
margin: 0;
z-index: 1;
background-color: #ccc;
-webkit-transition: top 0.2s;
}
.subnav li {
display: inline-block;
background-color: #ccc;
margin: 0 5px;
}
.subnav li a {
padding: 8px 10px;
font-size: 14px;
color: #EFEFEF;
display: block;
}
HTML
<div class="bodyframe div_container">
<header>
<nav>
<ul class="nav">
<li role="presentation" class="active">Home</li>
<li role="presentation">Services</li>
<li role="presentation">Products</li>
<li role="presentation">About</li>
<li role="presentation">Contact</li>
</ul>
</nav>
<ul class="subnav">
<li>Test</li>
<li>1243</li>
</ul>
</header>
</div>
If you only need the submenu to mimic the one in the example, without using jQuery, using the second chunk of HTML with the CSS you supplied you could do:
nav:hover~ul {
top: 0px;
}
This shows the next ul element, in this case the subnav, whenever the nav is hovered over ("~" selector means select the ul element preceded by nav:hover).
However, if you want to do something more dynamic... id suggest just using JS/jQuery as well

how to align list dropdown

I have a dropdown in menu. But it drops not the way I need.
but I need it to be aligned as a menu item. like in here:
could it be done simply with css?
html
<li class="dropdown">
<a data-toggle="dropdown" class="dropdown-toggle" href="#">Account<b class="caret" style="float: right;"></b></a>
<ul class="dropdown-menu">
<li>Account Info</li>
<li>Billing Settings</li>
<li><a href="{% url 'dev_logout' %}" >Sign out</a></li>
</ul>
</li>
css:
.dropdown-menu {
background-color: black;
min-width: 100px;
width: 160px;
}
.dropdown-menu > li {
align: center;
}
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus {
color: #cfeffd;
background-color: #333333;
background-image: none;
filter: none;
}
.dropdown-toggle {
min-width: 100px;
width: 125px;
}
.caret {
marging-left: 30px;
}
You can make it by setting position:relative to ".dropdown" and position: absolute to ".dropdown-menu" and his width to 100%.
li {
padding: 10px 20px;
}
.dropdown {
position: relative;
display: block;
background-color: #ff0;
width: 120px;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: block;
width: 100%;
padding: 0;
margin: 0;
list-style: none;
background-color: gray;
}
Here is a working example :
http://jsfiddle.net/5CB4Q/3/
Assign the DropDownList a CssClass like DDLStyle.
select.DDLStyle{text-align:middle;}
This works in most modern browsers, but not in IE.

Categories

Resources