Add/remove class from div's when link is clicked - javascript

I have one page web app with 5 link's navigation and 5 sections. The structure is this:
<div class="main-nav">
<ul>
<li>Home</li>
<li>About</li>
<li>Skills</li>
<li>Contact</li>
<li>P.S.</li>
</ul>
</div>
<div class="home-section">
<div class="home-section--greeting">
<p>Hi, I'm</p>
<p>T. Green</p>
</div>
</div>
<div class="about-section zoomOut">
</div>
<div class="skills-section zoomOut">
</div>
<div class="contact-section zoomOut">
</div>
<div class="ps-section zoomOut">
</div>
Every section is behind the home-section on page load. The sections are stacked on top of eachother with 100vh and position absolute. Also, every section EXCEPT the home-section has zoomOut class with transform: scale(0.8).
What I want to do is the following: when a link from the nav is clicked, I want the corresponding section to zoom-in and the active section to zoom-out, meaning the zoomOut class should be removed and the new section will slowly fade in (I will tackle the opacity and all animations, don't worry).
I want to do this in pure Javascript so, no jQuery/framework comments and pointers, please.
Also, I assembled a little jsfiddle so you could go to straight experimenting, if you may: https://jsfiddle.net/h7wturbf/1/
Thanks in advance!

Here is a plain javascript sample, using addEventListener, querySelector and querySelectorAll to catch and target links/sections
I added a zoomIn class to simplify how to toggle the sections
window.addEventListener('load', function() {
var links = document.querySelectorAll('.main-nav a');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(e) {
var divtarget = e.target.href.split('#')[1];
document.querySelector('.zoomIn').classList.remove('zoomIn');
document.querySelector('.' + divtarget).classList.add('zoomIn');
})
}
})
html,
body {
height: 100%;
font-family: 'Yanone Kaffeesatz', sans-serif;
}
.zoomOut {
transform: scale(0);
}
.zoomIn {
transform: scale(0.8);
}
.home-section {
height: 100vh;
background-color: yellow;
}
.home-section .home-section--greeting {
display: inline-block;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 62px;
color: #005168;
}
.about-section {
position: absolute;
height: 100vh;
top: 0;
width: 100%;
background-color: dodgerblue;
}
.skills-section {
position: absolute;
height: 100vh;
top: 0;
width: 100%;
background-color: rebeccapurple;
}
.contact-section {
position: absolute;
height: 100vh;
top: 0;
width: 100%;
background-color: aqua;
}
.ps-section {
position: absolute;
height: 100vh;
top: 0;
width: 100%;
background-color: forestgreen;
}
.main-nav {
position: fixed;
top: 50%;
transform: translate(0, -50%);
font-size: 21px;
left: 0px;
z-index: 999;
}
.main-nav ul li {
margin: 8px 0 8px 0;
list-style-type: none;
}
.main-nav ul li a {
text-decoration: none;
color: #4F96AA;
transition: color 0.2s ease-in;
}
.main-nav ul li a:hover {
color: #65AABD;
}
.main-nav ul li a.about:active ~ #about-section {
display: none;
}
<div class="main-nav">
<ul>
<li>Home
</li>
<li>About
</li>
<li>Skills
</li>
<li>Contact
</li>
<li>P.S.
</li>
</ul>
</div>
<div class="home-section zoomOut zoomIn">
<div class="home-section--greeting">
<p>Hi, I'm</p>
<p>T. Green</p>
</div>
</div>
<div class="about-section zoomOut">
</div>
<div class="skills-section zoomOut">
</div>
<div class="contact-section zoomOut">
</div>
<div class="ps-section zoomOut">
</div>

You should first bind onclick Event handler to those elements that can be clicked. Once the element is clicked, you could remove the class using :
this.classList.remove('class-name');

Related

How to toggle off eventlistener

const button = document.getElementById("hamburger");
const list = document.getElementById("list");
button.addEventListener("click", () => {
list.classList.toggle('show');
});
margin: 0;
padding: 0;
box-sizing: border-box;
}
html{
scroll-behavior: smooth;
}
ul{
list-style-type: none;
}
.list{
list-style-type: none;
display: none;
}
.list.show{
position: fixed;
display: block;
inset: 0 0 0 0;
z-index: 99;
text-align: center;
background-color: hsl(0 0% 0% / 0.6);
padding: min(43vh, 20rem) 2rem;
}
header{
display: flex;
justify-content: space-between;
}
.hamburger{
width: 50px;
height: 50px;
background-color: red;
cursor: pointer;
position: absolute;
z-index: 999;
}
h1{
margin: 20rem 0;
}
.contents{
position: absolute;
left: 50%;
top: 120%;
transform: translate(-50%, -50%);
}
<header>
<div class="hamburger" id="hamburger"></div>
<ul class="list" id="list">
<li>HOME</li>
<li>SERVICES</li>
<li>ABOUT</li>
<li>MENU</li>
</ul>
</header>
<div class="contents">
<h1 id="home">HOME</h1>
<h1 id="services">SERVICES</h1>
<h1 id="about">ABOUT</h1>
<h1 id="menu">MENU</h1>
</div>
I am trying to toggle off the eventlistener, when any of the navigation links are clicked. Once it scrolls to the link using the link reference in the html, I want the 'show' to toggle off, So its going to scroll to the link and toggle off the evebtlistener.
I've tried using the if else and some other html special class, Please can anyone help me solve this
Can you try adding a shared-class to the navigation items and then use document.querySelectorAll to add a click event listener to them? Something like -
<ul class="list" id="list">
<li>HOME</li>
<li>SERVICES</li>
<li>ABOUT</li>
<li>MENU</li>
</ul>
And then -
const navItems = document.querySelectorAll('nav-item')
navItems.forEach((navItem) => {
navItem.addEventListener('click', () => {
list.classList.remove("show")
})

Javascript help: "slide-revealing" menu

Current setup (plain HTML/CSS):
I've currently got this plain HTML/CSS setup, which is basically using a checkbox with no opacity, with labels acting as buttons (which they in fact are not).
Codepen: https://codepen.io/MikaTheDesigner/pen/MWVYGoz
Video of my current HTML/CSS-demo (and the result goal): https://i.imgur.com/ha3NL0V.mp4
<div class="nav">
<input class="menuBtn" type="checkbox">
<label class="menuLabel open">Menu</label>
<label class="menuLabel close">Close</label>
<div class="nav menuBox transitionBox menuTransition"></div>
<div class="nav menuBox BG">
<nav>
<ul>
<li><a>Option 1</a></li>
<li><a>Option 2</a></li>
<li><a>Option 3</a></li>
</ul>
</nav>
</div>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.nav {
pointer-events: none;
position: fixed;
z-index: 100;
width: 100vw;
height: 100vh;
}
.nav > .menuBtn {
cursor: pointer;
width: 122.43px;
height: 122.43px;
margin: 0 0 0 3rem;
pointer-events: initial;
position: absolute;
z-index: 99;
opacity: 0;
}
.nav > .menuBtn:checked ~ .menuLabel.open {opacity: 0;}
.nav > .menuBtn:checked ~ .menuLabel.close {opacity: 100%;}
.nav > .menuBtn:checked ~ .menuBox.transitionBox {left: 100%;}
.nav > .menuBtn:checked ~ .menuBox.BG {left: 0;}
.nav > .menuLabel {
color: black;
font-size: 1.5rem;
position: absolute;
z-index: 98;
margin: 3rem 0 0 3rem;
text-align: center;
transition: all 0.2s ease-in-out;
}
.nav > .menuLabel.open {
text-shadow: 0 0 2rem rgba(0,0,0,.5);
width: 122.43px;
}
.nav > .menuLabel.close {
opacity: 0;
}
.nav > .menuBox.transitionBox {
background-color: black;
width: 200%;
height: 100%;
position: absolute;
z-index: 100;
left: -200%;
transition: all 2000ms;
}
.nav > .menuBox.BG {
background: linear-gradient(to bottom, white, black);
background-size: cover;
width: 100%;
height: 100%;
pointer-events: auto;
position: absolute;
z-index: 96;
left: -100%;
transition-delay: 500ms !important;
transition: all 200ms;
}
.nav > .menuBox.BG > nav {
position: absolute;
z-index: 97;
width: 100%;
height: 100%;
}
.nav > .menuBox.BG > nav > ul {
list-style: none;
padding: 122.43px 3rem 3rem calc(6rem + 122.43px);
}
.nav > .menuBox.BG > nav > ul li {
color: white;
font-size: 2rem;
line-height: 2rem;
margin-bottom: 1.5rem;
}
.nav > .menuBox.BG > nav > ul li > a {
color: inherit;
display: block;
text-decoration: none;
transition: all 0.2s ease-in-out;
width: max-content;
}
.nav > .menuBox.BG > nav > ul li > a:hover {cursor: pointer;}
Goal:
My goal is for the menu to act in the exact same way, when clicking the labels .menulabel.open and .menuLabel.close, but using javascript instead of plain HTML/CSS.
I would change these current labels to a-tags or p-tags and using onClick-functions, when I get the javascript working.
Like linked at the top of the thread, this is my goal, but using javascript to make it react, and not using a plain checkbox:
https://i.imgur.com/ha3NL0V.mp4
What have I tried so far?
Besides the plain HTML/CSS-solution I have tried setting up, which I wouldn't argue is the right way to make the menu, I have also tried setting this script up in my HTML-document, inwhich does not seem to work as I want it to:
function openNav() {
document.getElementsByClassName("menuTransition").style.left = "100%";
document.getElementsByClassName("menuBox").style.left = "0";
}
function closeNav() {
document.getElementsByClassName("menuTransition").style.left = "-200%";
document.getElementsByClassName("menuBox").style.left = "-100%";
}
(the javascript was supposed to just style the two elements when clicking on one of the a-tags the exact same way the CSS reacts, when checking the checkbox and "activating" the menu)
<div class="nav">
<a class="menuLabel open" onClick="openNav()">Menu</a>
<div class="nav menuBox transitionBox menuTransition"></div>
<div class="nav menuBox BG">
<a class="menuLabel close" onClick="closeNav()">Close</a>
<nav>
<ul>
<li><a>Option 1</a></li>
<li><a>Option 2</a></li>
<li><a>Option 3</a></li>
</ul>
</nav>
</div>
</div>
(basically the same HTML as above, just removing the labels and replacing them with a-tags)
You can use a single class and toggle that class on the click of a button, something like this:
function myFunction() {
var element = document.getElementById("myDIV");
element.classList.toggle("mystyle");
}
.mystyle {
width: 100%;
padding: 25px;
background-color: coral;
color: white;
font-size: 25px;
box-sizing: border-box;
}
<button onclick="myFunction()">Try it</button>
<div id="myDIV">
This is a DIV element.
</div>
document.getElementsByClassName("menuBox") return an array object .
you need to add the index , such as document.getElementsByClassName("menuBox")[0]

UL Background doesn`t show when i add position absolute

I want to build a hamburger menu and I don't know why when I add position absolute to my UL(links-list) his background doesn`t show.It only shows the links and the border-bottom. I will post maybe someone will spot the issue.
Thank you in advance.
I will write here something because I need to have more words to post the question.
.header {
width: 100%;
display: block;
height: 0;
z-index: 1;
.header-content {
display: block;
.logo {
display: none;
}
.links-list {
display: block;
position: absolute;
top: 0;
left: 0;
z-index: 2;
margin: 0;
width: 100%;
background: #505050;
height: 0;
.close {
display: block;
& a {
padding: 0 .5rem;
}
}
& li {
border-bottom: 1px solid #404040;
}
}
}
}
.open {
height: auto !important;
}
#burger-menu {
display: block;
height: 40px;
width: 100%;
background: url(/Core/img/burger.png)no-repeat 98% center;
background-size: 70px;
background-color: red;
}
<header class="header ">
<div class="container">
<div class="header-content">
<a href="#" id="burger-menu">
</a>
<img src="/Core/img/logo1.jpg" class="logo" alt="logo" />
<ul class="links-list">
<li class="close"><i class="fas fa-times"></i></li>
<li>Home</li>
<li>Bio</li>
<li>Training</li>
<li>Academy</li>
<li>Gallery</li>
<li>Store</li>
<li>Contact</li>
</ul>
<div class="overlay"></div>
</div>
</div>
</header>
It's because you have height: 0 on .links-list. When positioning elements absolutely, in most, if not all, cases you need to make sure the height has a positive value so the background has an area to draw on.

JQuery create expanding div on navigation

Take this snippet:
.container {
width: 150px;
height: 100px;
}
.test {
color: white;
background-color: red;
width: 100%;
height: 25%;
transition: height ease 1s;
}
.test:hover {
height: 100%;
}
<div class="container">
<div class="test">Hover Here</div>
</div>
A simple div inside a container which expands to 100% when hovered over. What I am trying to make is very simular to this, but in a navigation menu (similar to http://www.mineplex.com/).
When a user hovers over the container div (not the main box itself) I need the main div to expand from 0% to 100% in height.
I have tried using JQuery to solve this using a ".hovered" class with no luck. How can one code this?
Any help is much appreciated. Thanks!
Here's a demonstration:
Similarities between both the code snippets:
The containers make use of flex display to make a responsive navbar container, with each of its items spanning a width of 20% (which can be adjusted).
Each of the items (with relative positioning) has two sub containers (with absolute positioning), the first being overlay which we're making use for getting the blue transitioning background(z-index:1) and the second which has a fixed text on the front (z-index:2).
Now, the z-index makes sure that the overlay will be transitioned at the back and text will be fixed in the front, another thing to keep in mind is since we're transitioning it from the bottom up, we set the bottom:0 on the overlay class as well as height:0%;.
On hovering , we transition the height from 0% to 100%.
Differences between both the code snippets:
In the first snippet, we're transitioning each item on hover by making use of .items:hover .overlay.
Whereas in the second snippet, we're transitioning every item when the container is hovered instead of individual items by using .container:hover > *.items> .overlay ( ">" is a direct child selector ).
First: Hovering each item individually to expand the overlay.
.container {
width: 100%;
display: flex;
height: 80px;
background: gray;
justify-content: center;
align-items: center;
}
.items {
flex: 0 1 20%;
height: 100%;
margin-right: 5px;
position: relative;
overflow: hidden;
}
.overlay {
position: absolute;
background: blue;
z-index: 1;
width: 100%;
height: 0%;
bottom: 0;
transition: all 0.5s ease-in-out;
}
.item-text {
position: absolute;
text-align: center;
color: white;
z-index: 2;
width: 100%;
height: 100%;
top: 0;
}
.items:hover .overlay {
height: 100%;
}
<div class="container">
<div class="items">
<div class="overlay"></div>
<div class="item-text">Home</div>
</div>
<div class="items">
<div class="overlay"></div>
<div class="item-text">About</div>
</div>
<div class="items">
<div class="overlay"></div>
<div class="item-text">Contact</div>
</div>
<div class="items">
<div class="overlay"></div>
<div class="item-text">Other</div>
</div>
</div>
Second: When the user hovers over the container, expanding all the overlays.
.container {
width: 100%;
display: flex;
height: 80px;
background: gray;
justify-content: center;
align-items: center;
}
.items {
flex: 0 1 20%;
height: 100%;
margin-right: 5px;
position: relative;
overflow: hidden;
}
.overlay {
position: absolute;
background: blue;
z-index: 1;
width: 100%;
height: 0%;
bottom: 0;
transition: all 0.5s ease-in-out;
}
.item-text {
position: absolute;
text-align: center;
color: white;
z-index: 2;
width: 100%;
height: 100%;
top: 0;
}
.container:hover > *.items> .overlay {
height: 100%;
}
<div class="container">
<div class="items">
<div class="overlay"></div>
<div class="item-text">Home</div>
</div>
<div class="items">
<div class="overlay"></div>
<div class="item-text">About</div>
</div>
<div class="items">
<div class="overlay"></div>
<div class="item-text">Contact</div>
</div>
<div class="items">
<div class="overlay"></div>
<div class="item-text">Other</div>
</div>
</div>
ul{
list-style-type: none;
margin-left: 0;
padding-left: 0;
display: flex;
}
ul li{
border: 1px solid #d3d3d3;
text-align: center;
height: 100px;
width: 100px;
margin-right: 4px;
}
ul li a{
color: #000000;
text-decoration: none;
position: relative;
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
ul li a:after{
content: '';
position: absolute;
background: lightblue;
left: 0;
bottom: 0;
height: 0%;
width: 100%;
z-index: -1;
}
ul li a:hover:after{
animation: bounce 1s ease-in-out forwards;
}
#keyframes bounce {
0% {height: 0%}
20% { height: 100%}
55% { height: 95%}
100% {height: 100%}
}
<ul>
<li>Lorem, ipsum.</li>
<li>Saepe, asperiores!</li>
<li>Vitae, expedita?</li>
<li>Dicta, quo.</li>
<li>Sed, et.</li>
</ul>
i wrote some code
//html
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
//This is sass
ul {
list-style:none;
background:red;
li {
display:inline-block;
padding:10px;
position:relative;
&:before {
position: absolute;
content: "";
width: 100%;
height: 0%;
left: 0;
bottom: 0;
background:blue;
transition: height ease-in-out 0.5s;
}
a {
z-index:2;
position:relative;
color:white;
}
&:hover {
&:before {
height: 100%;
}
}
}
}

Responsive menu viewport height

I added a menu to my responsive website that pops up as soon as the viewport is 714px width or less.
When you click the button a menu slides out from the side across the page. The issue that I can't seem to solve is that I want the menu to be the height of the current viewport without allowing people to scroll down.
Here's a fiddly of what the menu looks like right now:
https://jsfiddle.net/baqcfjt1/1/
<div class="site-container-menu">
<div class="site-pusher">
<header class="header">
MENU
<nav class="menu">
Link 1
<strong>Link 2</strong>
Link 3
Link 4
</nav>
</header>
<div class="site-content">
<div class="container-menu">
<section id="header">
<div class="headerlogo"><img src="image" /></div>
<div class="headerlogosmall"><img src="image" /></div>
</section>
<section class="main">
-content-
</section>
</div>
</div>
<div class="site-cache" id="site-cache"></div>
</div>
</div>
CSS
.header {
z-index: -10;
position: absolute;
}
/* RESPONSIVE */
#media only screen and (max-width: 714px) {
.container-menu {
overflow: hidden;
*zoom: 1;
}
/* HEADER */
.header__logo {
font: inherit;
font-weight: 700;
padding: 0 25px;
float: left;
}
/* MENU */
.site-pusher,
.site-container-menu {
height: 100%;
}
.site-container-menu {
overflow: hidden;
}
.site-pusher {
-webkit-transition-duration: 0.3s;
transition-duration: 0.3s;
-webkit-transform: translateX(0px);
transform: translateX(0px);
}
.site-content {}
.header {
position: static;
height: 66px;
line-height: 62px;
color: rgba(228, 91, 65, 1.00);
background-color: #fff;
}
.header__icon {
position: relative;
display: block;
float: left;
padding-left: 3em;
font: inherit;
font-weight: 400;
font-size: 20px;
height: 66px;
cursor: pointer;
}
.header__icon:after {
content: '';
position: absolute;
display: block;
width: 1rem;
height: 0;
top: 16px;
left: 15px;
box-shadow: 0 10px 0 1px rgba(228, 91, 65, 1.00), 0 16px 0 1px rgba(228, 91, 65, 1.00), 0 22px 0 1px rgba(228, 91, 65, 1.00);
}
.menu {
position: absolute;
left: 0;
top: 0;
bottom: 0;
background-color: #fff;
/* overflow-y: scroll;
-webkit-overflow-scrolling: touch;*/
width: 250px;
-webkit-transform: translateX(-250px);
transform: translateX(-250px);
overflow: hidden;
}
.menu a {
display: block;
padding-top: 2em;
padding-bottom: 2em;
color: #666666;
height: 25%;
text-align: center;
line-height: 40px;
border-bottom: 1px solid #d9d9d9;
}
.menu a:hover {
color: #e45b41;
}
.with--sidebar .site-pusher {
-webkit-transform: translateX(250px);
transform: translateX(250px);
}
.with--sidebar .site-cache {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.6);
z-index: 9999;
}
}
$(document).ready(function() {
(function($) {
$('#header__icon').click(function(e) {
e.preventDefault();
$('body').toggleClass('with--sidebar');
});
$('#site-cache').click(function(e) {
$('body').removeClass('with--sidebar');
});
})(jQuery);
});
This can be achieved using viewport-percentage length units: https://developer.mozilla.org/en/docs/Web/CSS/length#Viewport-percentage_lengths
One option would be to use the vh css unit and specify that the body has height:100vh
https://jsfiddle.net/r61n4y0v/
I added:
body{
height:100vh;
}
to the CSS file.
You should also check the vh unit's browser compatibility, before using it. You can check here:
http://caniuse.com/#feat=viewport-units
If you'd like to be more specific with the height:100vh; rule, you can remove the overflow:hidden from .site-container-menu and add height:100vh to .menu directly:
https://jsfiddle.net/6won6stx/
Your menu links have both a height defined height:25% and padding...this is not advised as it can lead to unexpected behaviour. It would be better to replace:
<nav class="menu">
Link 1
<strong>Link 2</strong>
Link 3
Link 4
</nav>
With:
<nav class="menu">
<ul>
<li>Link 1</li>
<li><strong>Link 2</strong></li>
<li>Link 3</li>
<li>Link 4</li>
</ul>
</nav>
and remove the height:25% from the a element and add height:25vh to the li elements.
https://jsfiddle.net/s5gbk7y1/
I've also made a few other changes such as changing the line-height property on the menu links to 25vh.
Take a look at the latest fiddle and let me know if it helps!

Categories

Resources