I have an accordion list and my task was to implement a smooth tabs open/close function for dynamic content without a set height.
The forEach method works perfectly.
The smooth open/close function (setHeight in JS snippet)also works fine, but only for the first tab.
In other tabs this function does not work and the opening does not happen as we would like it to.
I've already racked my brains.
How can I combine the forEach method and the "setHeight" function so that nothing breaks?
const accItems = document.querySelectorAll('.accordion__item');
accItems.forEach((item) => {
const icon = item.querySelector('.accordion__icon');
const content = item.querySelector('.accordion__content');
item.addEventListener('click', () => {
if (item.classList.contains('open')) {
item.classList.remove('open');
icon.classList.remove('open');
content.classList.remove('open');
} else {
const accOpen = document.querySelectorAll('.open');
accOpen.forEach((open) => {
open.classList.remove('open');
});
item.classList.add('open');
icon.classList.add('open');
content.classList.add('open');
}
if (content.clientHeight) {
content.style.height = 0;
} else {
let accText = item.querySelector('.acc-text');
content.style.height = accText.clientHeight + "px";
}
});
});
body {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #1f1f1f;
background: #f2f2f2; }
html {
font-size: 62.5%; }
h5 {
margin: 0; }
p {
margin: 0; }
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: auto;
max-width: 140rem; }
.section-accordion {
display: flex;
align-items: center;
max-width: 134rem;
margin: auto; }
.accordion-image {
width: 630px;
height: 450px;
background: url("https://eternel.maitreart.com/wp-content/uploads/2021/07/creat-home-1.jpg");
background-repeat: no-repeat;
background-size: cover; }
.accordion {
width: 63rem;
height: auto;
margin-left: 8rem; }
.accordion__item {
border-top: 1px solid #a8a6a4;
overflow: hidden;
transition: height .5s;
padding-bottom: 1rem; }
.accordion__item:last-child {
border-bottom: 1px solid #a8a6a4; }
.accordion__item--header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 2rem 1rem 1rem 1rem;
cursor: pointer; }
.accordion__item.open {
width: 100%; }
.accordion__title {
font-family: 'Lora';
font-size: 2.4rem;
line-height: 1.2;
font-weight: 400;
text-transform: uppercase; }
.accordion__icon {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 2rem;
height: 2rem;
transition: transform .5s ease; }
.accordion__icon span:first-child {
transform: rotate(90deg) translateX(1px);
width: 1.4rem;
height: .1rem;
background: currentColor; }
.accordion__icon span {
display: block;
width: 1.4rem;
height: .1rem;
background: currentColor;
cursor: pointer; }
.accordion__icon.open {
transform: rotate(45deg); }
.accordion__content {
font-family: 'Roboto', sans-serif;
font-size: 1.6rem;
line-height: 1.62;
font-weight: 400;
padding: 0 1rem 0 1rem;
height: 0;
transition: height .5s;
overflow: hidden; }
.accordion__content.open {
margin-bottom: 1.2rem;
height: 100%; }
<div class="container">
<section class="section-accordion">
<div class="accordion-image"></div>
<div class="accordion">
<div class="accordion__item open">
<div class="accordion__item--header">
<h5 class="accordion__title">Visual direction</h5>
<div class="accordion__icon open">
<span></span>
<span></span>
</div>
</div>
<div class="accordion__content open">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__item--header">
<h5 class="accordion__title">Event production</h5>
<div class="accordion__icon">
<span class="accordion__icon--first"></span>
<span class="accordion__icon--second"></span>
</div>
</div>
<div class="accordion__content">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__item--header">
<h5 class="accordion__title">Brand creation</h5>
<div class="accordion__icon">
<span class="accordion__icon--first"></span>
<span class="accordion__icon--second"></span>
</div>
</div>
<div class="accordion__content">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__item--header">
<h5 class="accordion__title">Design concept</h5>
<div class="accordion__icon">
<span class="accordion__icon--first"></span>
<span class="accordion__icon--second"></span>
</div>
</div>
<div class="accordion__content">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course.
Assistance travelling so especially do prosperous appearance mr no celebrated.
Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
</div>
</div>
It does not seem that you need setHeight which is the one that messes the display
Here is a delegated version
const accordionItems = document.querySelectorAll(".accordion__item");
document.querySelector('.accordion').addEventListener('click', (e) => {
const item = e.target.closest(".accordion__item");
if (!item) return
accordionItems.forEach(acItem => {
if (acItem !== item) {
acItem.classList.remove('open');
acItem.querySelector('.accordion__icon').classList.remove('open');
acItem.querySelector('.accordion__content').classList.remove('open');
}
});
const icon = item.querySelector('.accordion__icon');
const content = item.querySelector('.accordion__content');
item.classList.toggle("open")
const isOpen = item.classList.contains("open");
icon.classList.toggle("open", isOpen);
content.classList.toggle('open', isOpen);
});
body {
margin: 0;
padding: 0;
box-sizing: border-box;
color: #1f1f1f;
background: #f2f2f2;
}
html {
font-size: 62.5%;
}
h5 {
margin: 0;
}
p {
margin: 0;
}
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: auto;
max-width: 140rem;
}
.section-accordion {
display: flex;
align-items: center;
max-width: 134rem;
margin: auto;
}
.accordion-image {
width: 630px;
height: 450px;
background: url("https://eternel.maitreart.com/wp-content/uploads/2021/07/creat-home-1.jpg");
background-repeat: no-repeat;
background-size: cover;
}
.accordion {
width: 63rem;
height: auto;
margin-left: 8rem;
}
.accordion__item {
border-top: 1px solid #a8a6a4;
overflow: hidden;
transition: height .5s;
padding-bottom: 1rem;
}
.accordion__item:last-child {
border-bottom: 1px solid #a8a6a4;
}
.accordion__item--header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 2rem 1rem 1rem 1rem;
cursor: pointer;
}
.accordion__item.open {
width: 100%;
}
.accordion__title {
font-family: 'Lora';
font-size: 2.4rem;
line-height: 1.2;
font-weight: 400;
text-transform: uppercase;
}
.accordion__icon {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 2rem;
height: 2rem;
transition: transform .5s ease;
}
.accordion__icon span:first-child {
transform: rotate(90deg) translateX(1px);
width: 1.4rem;
height: .1rem;
background: currentColor;
}
.accordion__icon span {
display: block;
width: 1.4rem;
height: .1rem;
background: currentColor;
cursor: pointer;
}
.accordion__icon.open {
transform: rotate(45deg);
}
.accordion__content {
font-family: 'Roboto', sans-serif;
font-size: 1.6rem;
line-height: 1.62;
font-weight: 400;
padding: 0 1rem 0 1rem;
height: 0;
transition: height .5s;
overflow: hidden;
}
.accordion__content.open {
margin-bottom: 1.2rem;
height: 100%;
}
<div class="container">
<section class="section-accordion">
<div class="accordion-image"></div>
<div class="accordion">
<div class="accordion__item open">
<div class="accordion__item--header">
<h5 class="accordion__title">Visual direction</h5>
<div class="accordion__icon open">
<span></span>
<span></span>
</div>
</div>
<div class="accordion__content open" id="content__wrapper">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__item--header">
<h5 class="accordion__title">Event production</h5>
<div class="accordion__icon">
<span class="accordion__icon--first"></span>
<span class="accordion__icon--second"></span>
</div>
</div>
<div class="accordion__content" id="content__wrapper">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__item--header">
<h5 class="accordion__title">Brand creation</h5>
<div class="accordion__icon">
<span class="accordion__icon--first"></span>
<span class="accordion__icon--second"></span>
</div>
</div>
<div class="accordion__content" id="content__wrapper">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
<div class="accordion__item">
<div class="accordion__item--header">
<h5 class="accordion__title">Design concept</h5>
<div class="accordion__icon">
<span class="accordion__icon--first"></span>
<span class="accordion__icon--second"></span>
</div>
</div>
<div class="accordion__content" id="content__wrapper">
<p class="acc-text">Carried nothing on am warrant towards. Polite in of in oh needed itself silent course. Assistance travelling so especially do prosperous appearance mr no celebrated. Wanted easily in my called formed suffer. Songs hoped sense.
</p>
</div>
</div>
</div>
</div>
</section>
</div>
cleaned up js to make it more readable:
const accItems = document.querySelectorAll('.accordion__item');
function handleItemClick(e, i) {
if (e) e.preventDefault();
const actives = document.getElementsByClassName("open");
while (actives.length)
actives[0].classList.remove('open');
accItems[i].classList.add("open");
}
accItems.forEach((item, i) =>
item.addEventListener("click", (e) => handleItemClick(e, i))
);
Handling height with just css:
I made icon and content children of .open
.accordion {
width: 63rem;
height: auto;
margin-left: 8rem; }
.accordion__item {
border-top: 1px solid #a8a6a4;
overflow: hidden;
transition: height .5s;
padding-bottom: 1rem; }
.accordion__item:last-child {
border-bottom: 1px solid #a8a6a4; }
.accordion__item--header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 2rem 1rem 1rem 1rem;
cursor: pointer; }
.open .accordion__item {
width: 100%; }
.accordion__title {
font-family: 'Lora';
font-size: 2.4rem;
line-height: 1.2;
font-weight: 400;
text-transform: uppercase; }
.accordion__icon {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 2rem;
height: 0;
transition: transform .5s ease; }
.accordion__icon span:first-child {
transform: rotate(90deg) translateX(1px);
width: 1.4rem;
height: .1rem;
background: currentColor; }
.accordion__icon span {
display: block;
width: 1.4rem;
height: .1rem;
background: currentColor;
cursor: pointer; }
open .accordion__icon {
transform: rotate(45deg);
height: 2rem; }
.accordion__content {
font-family: 'Roboto', sans-serif;
font-size: 1.6rem;
line-height: 1.62;
font-weight: 400;
padding: 0 1rem 0 1rem;
height: 0;
transition: height .5s;
overflow: hidden; }
.open .accordion__content {
margin-bottom: 1.2rem;
height: 100%; }
Related
I made the header menu of my website become a sidebar with the screen width. Everything was working fine, the menu could be toggled by clicking the icon. But then i noticed the majority of websites had this property that the menu would close if the user clicks anywhere in the screen. I tryed everything i could but everythime i add the event listener to the code (to remove the class that makes the menu visible), the onclick event that adds the class stops working.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Portfolio.</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght#300;400;700&display=swap" rel="stylesheet">
<link rel="apple-touch-icon" sizes="180x180" href="Favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="Favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="Favicon/favicon-16x16.png">
<link rel="shortcut icon" href="Favicon/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="Favicon/site.webmanifest">
<link rel="stylesheet" href="https://unpkg.com/boxicons#latest/css/boxicons.min.css">
<link rel="stylesheet" href="style.css">
<script src="script.js" defer></script>
</head>
<body>
<!-- Header -->
<header id="header">
<div id="container">
<nav id="nav-bar">
Portfolio.
<ul id="nav-menu">
<div id="nav"><li><a id="link" href="#about-me">Sobre mim</a></li></div>
<div id="nav"><li><a id="link" href="#experience">Experiência</a></li></div>
<div id="nav"><li><a id="link" href="#projects">Projetos</a></li></div>
<div id="nav"><li><a id="link" href="#habilities">Competências</a></li></div>
<div id="nav"><button id="resume-btn">Currículo</button></li></div>
</ul>
<div class="menu-icon">
<h3 onclick="handleMenuToggle()">☰</h3>
</div>
</nav>
</div>
</header>
<!-- Sections -->
<main>
<section id="hero"> <!-- Main section -->
<div id="hero-txt">
<h2>
Seja bem vindo, eu sou
</h2>
<h1>
Yan Calvo
</h1>
<p>
Estudante de Ciência da computação e desenvolvedor web
</p>
<div class="social">
<i class='bx bxl-linkedin' ></i>
<i class='bx bxl-github' ></i>
</div>
</div>
</section>
<section id="about-me"> <!-- About section -->
<div id="txt-container" class="container reveal fade-left">
<h2>Sobre mim</h2>
<p>
Sou estudante de Ciência da computação, também
focado em aprender tecnologias de forma
independente. No momento me encontro dedicado a
aprimorar as minhas habilidades através da
experiência profissional e contato com outros
profissionais dedicados.<br><br>
O que mais me entusiasma em trabalhar com programação é poder projetar e criar coisas que tenham propósito e resolvam problemas reais.
Apoiar-se na pesquisa e percepção do cliente, encontrar as formas certas e dinâmicas de resolver determinados problemas, aprender com o processo e, em seguida, iterar e melhora-lo é a chave para um ótimo design.
</p>
</div>
<div class="container reveal fade-left">
<h4 id="quote">
“<br>
Knowledge has to be improved, challenged, and increased constantly, or it vanishes.<br>
”
</h4>
<h5>― Peter Drucker</h5>
</div>
</section>
<section id="experience"> <!-- Experience section -->
<div id="txt-container" class="container reveal fade-right">
<h2>Onde trabalhei </h2>
<p>
Ainda em busca de oportunidades profissionais
</p>
</div>
</section>
<section id="projects"> <!-- Projects section -->
<div id="txt-container" class="container reveal fade-left">
<h2>Projetos</h2>
<p>Trabalhos pessoais</p>
</div>
<div id="portfolio-content" class="container reveal fade-left">
<div class="col">
<img src="Img/work3.jpg">
<div class="layer">
<h3>Web Design</h3>
<h5>Popup</h5>
</div>
</div>
<div class="col">
<img src="Img/work3.jpg">
<div class="layer">
<h3>Web Design</h3>
<h5>Popup</h5>
</div>
</div>
<div class="col">
<img src="Img/work3.jpg">
<div class="layer">
<h3>Web Design</h3>
<h5>Popup</h5>
</div>
</div>
<div class="col">
<img src="Img/work3.jpg">
<div class="layer">
<h3>Web Design</h3>
<h5>Popup</h5>
</div>
</div>
<div class="col">
<img src="Img/work3.jpg">
<div class="layer">
<h3>Web Design</h3>
<h5>Popup</h5>
</div>
</div>
<div class="col">
<img src="Img/work3.jpg">
<div class="layer">
<h3>Web Design</h3>
<h5>Popup</h5>
</div>
</div>
</div>
</section>
<section id="habilities"> <!-- Contact section -->
<div id="txt-container" class="container reveal fade-right">
<h2>Competências</h2>
<div id="habilities-container">
<div id="hability-icons-container"></div>
<img id="hability-icon" src="Img/icons8-javascript-144.png" alt="">
<img id="hability-icon" src="Img/icons8-html-5-144.png" alt="">
<img id="hability-icon" src="Img/icons8-css3-144.png" alt="">
<img id="hability-icon" src="Img/icons8-git-144.png" alt="">
<img id="hability-icon" src="Img/icons8-github-128.png" alt="">
<div id="habilities-description"></div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer id="footer">
<div id="footer-copyright">
<h6>Projetado por Yan Calvo</h6>
</div>
<div id="social">
<h6>Email para contato: yancalvo#gmail.com</h6>
</div>
</footer>
</body>
</html>
CSS:
* {
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
scroll-padding-top: 70px;
}
body {
position: relative;
background-color: #ece7e1;
}
html, body {
overflow-x: hidden;
}
/* Header */
header {
position: fixed;
top: 0;
width: 100%;
background-color: rgba(27,26,33,255);
z-index: 200;
}
#container {
width: 1800px;
margin: auto;
}
#nav-bar {
width: 95%;
margin: auto;
min-height: 70px;
display: flex;
justify-content: space-between;
align-items: center;
}
#nav-brand {
color: white;
text-decoration: none;
font-size: 30px;
}
#nav-menu {
display: flex;
justify-content: space-between;
align-items: center;
}
#nav {
margin: auto 30px;
}
.menu-icon {
display: none;
}
#link {
margin-right: 15px;
color: white;
text-decoration: none;
transition: color 0.15s;
}
#link:hover {
color: gray;
font-style: italic;
}
#resume-btn {
width: 100px;
font-weight: bold;
font-size: 15px;
color: rgba(27,26,33,255);
background-color: #ece7e1;
border-radius: 23.5px;
border-style: solid;
border-color: #ece7e1;
padding: 10px;
cursor: pointer;
transition: color 0.15s, border-color 0.15s, width 1.0s;
}
#resume-btn:hover {
width: 150px;
}
/* Sections */
main {
padding-top: 70px;
}
section {
padding: 0px 100px;
}
#hero {
position: relative;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
grid-gap: 4rem;
}
.social a {
color: white;
width: 35px;
height: 35px;
border-radius: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
background: rgba(27,26,33,255);
font-size: 17px;
margin-right: 22px;
margin-bottom: 30px;
margin-top: 20px;
}
.social a:hover{
transform: scale(1.1);
transition: .5s;
}
#about-me {
background-color: #191919;
min-height: 500px;
padding-top: 40px;
margin-bottom: 100px;
display: grid;
grid-template-columns: repeat(2, 2fr);
grid-gap: 2rem;
white-space: normal;
}
#experience {
min-height: 300px;
padding-top: 40px;
margin-bottom: 100px;
display: flex;
justify-content: center;
text-align: center;
white-space: normal;
}
#projects {
background-color: #191919;
min-height: 800px;
padding-top: 40px;
margin-bottom: 100px;
display: flex;
flex-direction: column;
text-align: center;
align-items: center;
grid-gap: 2rem;
}
#portfolio-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(160px, auto));
grid-gap: 2rem;
align-items: center;
margin-top: 5rem;
text-align: center;
cursor: pointer;
}
.layer{
background: transparent;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
border-radius: 12px;
transition: all .40s;
}
.layer:hover{
background: linear-gradient(rgba(0,0,0,0.5) 0%, #191919);
}
.layer h3{
position: absolute;
width: 100%;
font-size: 25px;
font-weight: 500;
color: white;
bottom: 0;
left: 50%;
transform: translateX(-50%);
opacity: 0;
transition: all .40s;
margin-bottom: 7px;
}
.layer:hover h3{
bottom: 52%;
opacity: 1;
}
.layer h5{
position: absolute;
width: 100%;
font-size:17px;
font-weight: 500;
color: white;
bottom: 0;
left: 50%;
transform: translateX(-50%);
opacity: 0;
transition: all .40s;
}
.layer:hover h5{
bottom: 48%;
opacity: 1;
}
.col {
position: relative;
}
.col img {
max-width: 100%;
width: 550px;
height: auto;
object-fit: cover;
border-radius: 12px;
}
#habilities {
min-height: 500px;
width: 90%;
margin-left: auto;
margin-right: auto;
display: flex;
justify-content: center;
text-align: center;
}
li {
list-style: none;
}
h1 {
font-size: 90px;
color: rgba(27,26,33,255);
margin: 10px 0px 25px;
}
h2 {
font-size: 30px;
margin-bottom: 60px;
}
#about-me h2,
#projects h2
{
color: #ece7e1;
}
#experience h2,
#habilities h2 {
color: #191919;
}
#habilities-container {
display: flex;
flex-direction: column;
align-items: ;
}
#hability-icon {
width: 144px;
height: 144px;
transition: all 0.8s;
}
#hability-icon:hover {
height: 155px;
width: 155px;
}
h6 {
font-size: 20px;
color: white;
}
h4 {
font-size: 40px;
color: #ece7e1;
font-style: italic;
}
h5 {
color: rgba(27,26,33,255);
}
p {
color: gray;
text-align: justify;
}
#footer {
background-color: #191919;
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px 100px;
}
.reveal {
position: relative;
opacity: 0;
}
.reveal.active {
opacity: 1;
}
.active.fade-left {
animation: fade-left 0.5s ease-in;
}
.active.fade-right {
animation: fade-right 0.5s ease-in;
}
#keyframes fade-left {
0% {
transform: translateX(-100px);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
#keyframes fade-right {
0% {
transform: translateX(100px);
opacity: 0;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
#media(max-width:1800px) {
#container {
width: 100%;
}
}
#media only screen and (max-width: 1015px) {
#nav-menu {
position: fixed;
top: 70px;
right: -100%;
display: block;
background-color: rgba(27,26,33,255);
margin: 0;
height: 100%;
-webkit-box-shadow: 1px 6px 0px 6px rgba(0,0,0,0.13);
-moz-box-shadow: 1px 6px 0px 6px rgba(0,0,0,0.13);
box-shadow: 1px 6px 0px 6px rgba(0,0,0,0.13);
width: 250px;
transition: all 0.3s ease;
}
#nav-menu.show-nav {
right: 0;
}
#nav {
text-align: center;
margin: 20px auto;
}
.menu-icon {
color: white;
display: block;
margin: auto 0;
padding: 0 20px;
font-size: 30px;
cursor: pointer;
}
#brush-img {
display: none;
}
#about-me {
display: flex;
flex-direction: column;
}
}
Javascript:
//Toggle sidebar
const navContainer = document.getElementById('nav-menu')
function handleMenuToggle() {
navContainer.classList.add('show-nav')
}
document.onclick = function(e) {
if (e.target.id !== 'nav-menu' && e.target.id !== 'show-nav') {
navContainer.classList.remove('show-nav')
}
}
//Scroll animation
function reveal() {
var reveals = document.querySelectorAll(".reveal");
for (var i = 0; i < reveals.length; i++) {
var windowHeight = window.innerHeight;
var elementTop = reveals[i].getBoundingClientRect().top;
var elementVisible = 150;
if (elementTop < windowHeight - elementVisible) {
reveals[i].classList.add("active");
} else {
reveals[i].classList.remove("active");
}
}
}
window.addEventListener("scroll", reveal);
I just cannot make it work, i'm probably missing something or making some ugly mistakes in the structure of the code.
By taking a look at : this question you could try to do it this way : create a navbar sublcass called like :
navbar.open , and assign it these css properties :
/* If you use an id use #id_name or .classname if you use a class
*/
#id_of_navbar.open {
right: 0;
}
/* OR
.classname.open {
right: 0;
}
*/
And then add to your javascript :
var yournavbar = document.getElementById("id_of_navbar")
//Close menu when document is clicked anywhere
document.onclick = function () {
yournavbar.classList.remove("open");
};
And if you want your navbar to close if you click a part of it, just add this function :
//stop propagation on the side nav element
yournavbar.onclick = function(e) {
e.stopPropagation()
}
I tried that solution and it worked for me so I really hope it helps! Let me know if you are still trying to make it work without success despite this solution.
I'm trying to create a progress circle, and get the progress value based on HTML data (data-start and data progress), but there is an error.
The code works fine on one element, but the problem occurs when creating a loop for all elements.
Uncaught Type Error: Cannot read properties of undefined (reading 'start')"
let progressBar = document.getElementsByClassName(".circular-progress");
let valueContainer = document.getElementsByClassName(".value-container");
let progressValue = valueContainer.dataset.start;
let progressEndValue = valueContainer.dataset.progress;
var twoSum = function() {
for (var i = 0; i < progressValue.length; i++) {
for (var j = 0; j < progressEndValue.length; j++) {
let progress = setInterval(() => {
i++;
valueContainer.textContent = `${[i]}%`;
progressBar.style.background = `conic-gradient(
#4d5bf9 ${[i] * 3.6}deg,
#cadcff ${[i] * 3.6}deg
)`;
if (progressValue == progressEndValue) {
clearInterval(progress);
}
}, 30);
}
}
};
.skill .container {
display: grid;
align-items: center;
}
.skill-grid {
display: grid;
grid-template-columns: 190px 190px;
grid-template-rows: 190px 190px;
justify-content: center;
column-gap: 2.5rem;
row-gap: 100px;
margin-right: 2rem;
position: relative;
}
.skill-card {
background-color: var(--white);
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
flex: 1 1 6rem;
/* padding: 3rem 4rem; */
border-radius: 0.5rem;
transition: transform ease-in-out 0.3s;
}
.skill-card p {
font-size: 1rem;
font-weight: 600;
text-align: center;
padding-top: 10px;
}
.circular-progress {
position: relative;
height: 100px;
width: 100px;
border-radius: 50%;
display: grid;
place-items: center;
}
.circular-progress:before {
content: "";
position: absolute;
height: 90%;
width: 90%;
background-color: #ffffff;
border-radius: 50%;
}
.value-container {
position: relative;
font-family: var(--main-font);
font-size: 1.3rem;
color: var(--bs-primary);
font-weight: 600;
}
<section class="skill">
<div class="container">
<div class="skill-grid">
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="90">0</div>
</div>
<p>UI Design</p>
</div>
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="80">0</div>
</div>
<p>UI Design</p>
</div>
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="60">0%</div>
</div>
<p>UI Design</p>
</div>
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="50">0%</div>
</div>
<p>UI Design</p>
</div>
</div>
</div>
</section>
You can easily simplify your code:
Better use the querySelectorAll() (and it's single element counterpart querySelector() selection method, since it provides a more versatile css-like selector syntax.
As commented by #Peter B getElementsByClassName()
selects multiple elements (besides it's expect the raw class name without trailing "." dots)
thus, you need to loop through all elements and process each item.
// find all progress circles
let progressBars = document.querySelectorAll(".circular-progress");
progressBars.forEach((progressBar) => {
// select child value container
let valueContainer = progressBar.querySelector(".value-container");
let progressValue = valueContainer.dataset.start;
let progressEndValue = valueContainer.dataset.progress;
let i = 0;
// increment progress angles
let progress = setInterval(() => {
i++;
valueContainer.textContent = `${[i]}%`;
progressBar.style.background = `conic-gradient(
#4d5bf9 ${i * 3.6}deg,
#cadcff ${i * 3.6}deg
)`;
// stop animation
if (i >= progressEndValue) {
clearInterval(progress);
}
}, 10);
});
.skill .container {
display: grid;
align-items: center;
}
.skill-grid {
display: grid;
grid-template-columns: 190px 190px;
grid-template-rows: 190px 190px;
justify-content: center;
column-gap: 2.5rem;
row-gap: 100px;
margin-right: 2rem;
position: relative;
}
.skill-card {
background-color: var(--white);
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
flex: 1 1 6rem;
/* padding: 3rem 4rem; */
border-radius: 0.5rem;
transition: transform ease-in-out 0.3s;
}
.skill-card p {
font-size: 1rem;
font-weight: 600;
text-align: center;
padding-top: 10px;
}
.circular-progress {
position: relative;
height: 100px;
width: 100px;
border-radius: 50%;
display: grid;
place-items: center;
}
.circular-progress:before {
content: "";
position: absolute;
height: 90%;
width: 90%;
background-color: #ffffff;
border-radius: 50%;
}
.value-container {
position: relative;
font-family: var(--main-font);
font-size: 1.3rem;
color: var(--bs-primary);
font-weight: 600;
}
<section class="skill">
<div class="container">
<div class="skill-grid">
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="90">0</div>
</div>
<p>UI Design</p>
</div>
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="80">0</div>
</div>
<p>UI Design</p>
</div>
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="60">0%</div>
</div>
<p>UI Design</p>
</div>
<div class="skill-card">
<div class="circular-progress">
<div class="value-container" data-start="0" data-progress="50">0%</div>
</div>
<p>UI Design</p>
</div>
</div>
</div>
</section>
In the above example we're selecting the outer progress circle elements.
Since the text labels are just child elements, we can select them within the loop.
I have looked at the other questions that have been answered, tried them out myself and I still couldn't click on my burger and have the slide out menu. I was following a tutorial and it was turning out fine until I got to the JavaScript section of it. I'm not really too sure what I am doing wrong here. Looked around in the forum and tried all the solutions I could find for it to still not work.
const navSlide = () => {
const burger = document.querySelector('.burger');
const nav = document.querySelector('.navigation');
burger.addEventListener('click', () => {
nav.classList.toggle('nav-active');
});
}
const app = () => {
navSlide();
}
*{
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
.townlogo{
display: flex;
justify-content: center;
margin-top: 20px;
mix-blend-mode: multiply;
}
nav{
display: flex;
justify-content: space-around;
align-items: center;
min-height: 8vh;
background-color: white;
margin-bottom: 20px;
}
ul.navigation{
display: flex;
justify-content: space-around;
width: 40%;
align-items: center;
margin-top: 20px;
background-color: (white);
font-family: athelas, serif;
font-weight: 400;
font-style: normal;
letter-spacing: 1px;
}
ul.navigation li{
list-style: none;
}
ul.navigation a{
color: black;
text-decoration: none;
}
.burger{
display: none;
cursor: pointer;
}
.burger div{
width: 25px;
height: 3px;
background-color: black;
margin: 5px;
}
li a:hover{
color: rgb(190 30 45);
}
.indexbody{
height: 100%;
margin: 0;
font-size: 17px;
font-family: athelas, serif;
font-weight: 400;
font-style: normal;
line-height: 1.8em;
color: rgb(65 57 61);
}
.img1, .img2{
position: relative;
opacity:0.70;
background-position: center;
background-size:cover;
background-repeat: no-repeat;
background-attachment: fixed; /*Can be adjusted for mobile viewing*/
}
.img1{
background-image: url('../Images/lantern.jpg');
min-height: 600px;
}
.img2{
background-image: url('../Images/cookingcropped.jpg');
min-height: 400px;
}
.section{
text-align: center;
padding:50px 80px;
}
.section-mission{
background-color: rgb(65 57 61);
color:white;
}
.section-vision{
background-color: rgb(65 57 61);
color:white;
}
.menutext{
position: absolute;
font-size: 40px;
top: 50%;
width: 100%;
text-align: center;
color: white;
letter-spacing: 3px;
text-shadow: 3px 3px 3px black ;
}
.menutext .border{
border-style: solid;
border-width: 4px;
padding: 8px;
color: white;
box-shadow: 3px 3px 3px black;
text-decoration: none;
}
a.viewmenu:link{
text-decoration: none;
}
a.viewmenu:visited{
text-decoration: none;
}
a.viewmenu:hover{
background-color: transparent;
}
a.viewmenu:active{
text-decoration: none;
}
/*rectangle div contains copyright footer section*/
.rectangle{
text-align: center;
font-family: athelas, serif;
font-weight: 400;
font-style: normal;
font-size: 14px;
border-left: 520px solid rgb(190 30 45) ;
border-right: 520px solid rgb(190 30 45) ;
margin-top: 20px;
margin-bottom: 20px;
}
#media screen and (max-width: 1024px){
.navigation{
width: 50%;
}
}
#media screen and (max-width: 768px){
body{
overflow-x: hidden;
}
.navigation{
position: absolute;
right: 0px;
height: 92vh;
top: 8vh;
background-color: (white);
display: flex;
flex-direction: column;
align-items: center;
width: 50%;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.navigation li{
opacity: 0;
}
.burger{
display: block;
}
}
.nav-active{
transform: translateX(0%);
}
.rectangle{
text-align: center;
font-family: athelas, serif;
font-weight: 400;
font-style: normal;
font-size: 14px;
border-left: 200px solid rgb(190 30 45) ;
border-right: 200px solid rgb(190 30 45) ;
margin-top: 20px;
margin-bottom: 20px;
}
<!DOCTYPE html>
<html lang="en">
<head> <!--Header containing title,meta,and links-->
<title>ctowncuisine</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://use.typekit.net/qsw5hiv.css">
<link rel="stylesheet" href="CSS/style.css"> <!--link reference to CSS stylesheet-->
</head>
<body>
<nav>
<div class="townlogo"> <!--Technically the header of the page, but used in the body for consistency-->
<img src="Images/townlogo.jpg" alt="chinese restaurant logo">
</div>
<ul class="navigation"> <!--section for top navigation bar-->
<li>Home</li>
<li>Menu</li>
<li>Contact</li>
<li><span>Reserve Table</span></li>
</ul>
<div class="burger" id="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
<div class="line4"></div>
</div>
</nav>
<div class="indexbody"></div>
<div class="img1"></div> <!--lantern.html image class-->
<a class="viewmenu" href="menu.html"> <!--Linking border text with href-->
<div class="menutext">
<span class="border ">
View Our Menu
</span>
</div>
</a>
<section class="section section-mission">
<h2 class="mission">Our Mission</h2> <!--This is the second heading containing: Our Mission section-->
<p>To bring quality, style and the wish for good fortune to all of our guests. We provide a high-end experience through Chinese cuisine.
</p> <!--Paragraph containing the mission statement of TOWN-->
</section>
<div class="img2"> <!--div classifying second image: cookingcropped.html-->
<span class="border">
</span>
</div>
<section class="section section-vision">
<h2 class="vision">Vision</h2> <!--header 2 containing a class for CSS: Vision-->
<p> <span style="color: rgb( 213 162 141);">TOWN</span> combines a variety of chinese cuisine to excite and delight our customers.
Our vision for the future is to create experiential dining that is more than just a night out.<br> We aim to bring quality and luxury across all aspects of our brand.
The approach of <span style="color: rgb( 213 162 141);">TOWN</span> is to develop our brand with the understanding of both our culture and consumer insights.<br> Within our vision always lives the promise of inspiring creativity, conversation and quality.
Our audience is a high-end clientele who values a dining experience.<br>The age range of our customers are from early 30s-60s. We would like them to come back for both personal dining and events.
</p>
</section>
<footer>
<div class="rectangle"> <!--This section is the footer-->
© 2022 ctowncuisine.com designed by <span>Mariah Mendoza</span>
</div>
</footer>
<script> src="./js/app.js"</script>
</body>
</html>
It‘s hard to help because your code does not work yet. The burger has no size so we cannot click it.
Otherwise, your positioning and transition seems fine. But you’re hiding all menu items with opacity: 0. Since the menu is white, you will not see anything.
The current code has some accessibility issues, meaning it does not work well with assistive technology, which people with disabilities rely on. I improved them and I’ll explain them further down.
const navSlide = () => {
const burger = document.querySelector('.burger');
const nav = document.querySelector('.navigation');
burger.addEventListener('click', () => {
if (nav.classList.toggle('nav-active')) {
// now it’s active
burger.setAttribute('aria-expanded', true);
nav.setAttribute('aria-hidden', false);
} else {
burger.setAttribute('aria-expanded', false);
nav.setAttribute('aria-hidden', true);
}
});
}
const app = () => {
navSlide();
}
.navigation {
list-style-type: none;
}
.navigation a {
display: block;
padding: .5em;
}
#media screen and (max-width: 1024px) {
.navigation {
width: 50%;
}
}
#media screen and (max-width: 768px) {
body {
overflow-x: hidden;
}
.navigation {
position: absolute;
right: 0px;
height: 92vh;
top: 8vh;
background-color: (white);
display: flex;
flex-direction: column;
align-items: center;
width: 50%;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.burger {
display: block;
width: 40px;
}
.burger .line {
display: block;
background-color: black;
height: .2em;
margin: .4em 0;
}
.nav-active {
transform: translateX(0%);
}
}
<nav>
<div class="townlogo">
<!--Technically the header of the page, but used in the body for consistency-->
<img src="Images/townlogo.jpg" alt="Town">
</div>
<button class="burger" id="burger" aria-expanded="false" aria-controls="navigation" onclick="navSlide()">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</button>
<ul class="navigation" id="navigation">
<!--section for top navigation bar-->
<li>Home</li>
<li>Menu</li>
<li>Contact</li>
<li>Order Online</li>
</ul>
</nav>
newbie here...
I am working on some simple project where I am trying to simulate bank app.
Thing is that when I click on send money button, I want to take value from input value, and then subtract this value from my whole account balance.
Really simple, but after first transaction I get value which I want, but after second time I get innerText displaying "Nan" instead of some number value.
Here it is javascript file, if you can see from this why I get error.
Also here it is html and css if you don't understand what I am talking about.
////////////////// TOTAL MONEY FROM CARDS ///////////////////////
const totalMoney = document.querySelector(`.totalMoney`);
const allcards = document.querySelectorAll(`.cards`);
let totalMoneyAccount = 0;
allcards.forEach((kartica) => {
let novacNaKartici = kartica.querySelector(`.novacNaKartici`).innerText;
novacNaKartici = parseInt(novacNaKartici);
totalMoneyAccount += novacNaKartici;
totalMoney.innerText = ` ${replika2} $`;
});
//////////////////////////// TRANSFER MONEY TO SOMEONE /////////////////////////////
const reciver = document.querySelector(`input[name='recivier']`);
let amount = document.querySelector(`input[name='amount']`);
const sendMoneyBtn = document.querySelector(`.sendBtn`);
const transakcijeParent = document.querySelector(`.transakcije`);
sendMoneyBtn.addEventListener(`click`, () => {
amount = parseInt(amount.value);
totalMoneyAccount = totalMoneyAccount - amount;
updateProfile(totalMoneyAccount);
});
function updateProfile(totalMoneyAccount) {
totalMoney.innerHTML = totalMoneyAccount;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD#20..48,100..700,0..1,-50..200"
/>
<link rel="stylesheet" href="style.css" />
<title>Bank app</title>
</head>
<body>
<div class="container">
<div class="profile">
<div class="header">
<span class="material-symbols-outlined"> notifications </span>
<span class="material-symbols-outlined"> search </span>
</div>
<div class="person">
<img src="/img/cost1.jpg" alt="" />
<p>Random user</p>
<span class="totalMoney" style="font-size: 20px;"></span>
</div>
<div class="menu">
<div class="account flex">
<span class="material-symbols-outlined"> manage_accounts </span>
<p>Accounts</p>
</div>
<div class="transactions flex">
<span class="material-symbols-outlined"> receipt_long </span>
<p>Transactions</p>
</div>
<div class="bonus flex">
<span class="material-symbols-outlined"> star </span>
<p>Bonus</p>
</div>
<div class="invest flex">
<span class="material-symbols-outlined"> trending_up </span>
<p>Investments</p>
</div>
<div class="logOut flex">
<span class="material-symbols-outlined"> logout </span>
<p>Log Out</p>
</div>
</div>
</div>
<div class="main">
<div class="left">
<div class="naslov">
<p>Cards</p>
<span class="material-symbols-outlined">
add_circle
</span>
</div>
<div class="allCards">
<div class="cards changeJustify">
<div class="singleCard">
<img src="/img/visa.png" alt="" class="changeImg"/>
</div>
<div class="opis">
<p style="color: grey; font-size:20px">VISA</p>
<p style="color: black; font-size:16px" class="balance1 changeBalance">Balance:</p>
</div>
<div class="balance">
<span class="material-symbols-outlined changeSpan dots">
more_vert
</span>
<span style="font-size: 22px; color:grey(59, 59, 59);" class="novacNaKartici">2500$</span>
</div>
</div>
<div class="cards changeJustify">
<div class="singleCard ">
<img src="/img/american.jpg" alt="" class="changeImg"/>
</div>
<div class="opis ">
<p style="color: grey; font-size:20px">VISA</p>
<p style="color: grey; font-size:16px" class="balance1 changeBalance">Balance:</p>
</div>
<div class="balance ">
<span class="material-symbols-outlined changeSpan dots" >
more_vert
</span>
<span style="font-size: 22px; color:black;" class="novacNaKartici">3500$</span>
</div>
</div>
</div>
<p style="font-size: 30px;
color: grey;
font-weight: bold;">Transactions</p>
<div class="transakcije">
</div>
</div>
</div>
<div class="right">
<p style="font-size: 30px;
color: grey;
font-weight: bold;">Transfer money</p>
<div class="transfer">
<label for="recivier">Transfer to</label>
<input type="text" placeholder="antonio3101" name="recivier">
<label for="amount">Amount</label>
<input type="number" placeholder="$300..." name="amount">
<button class="sendBtn">Send</button>
</div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
body {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: sans-serif;
}
.container {
width: 100vw;
height: 100vh;
display: flex;
background-color: #f1f2f6;
}
.profile {
height: 100vh;
width: 20%;
background-color: #1d1c57;
display: flex;
flex-direction: column;
color: white;
}
.profile .header {
display: flex;
padding: 30px;
align-items: center;
justify-content: space-between;
color: #7979a6;
}
.profile .header span {
font-size: 26px;
}
.profile .header span:hover {
color: white;
}
.profile .person {
margin-top: 40px;
display: flex;
flex-direction: column;
align-items: center;
}
.profile .person img {
width: 150px;
height: 150px;
border-radius: 50%;
}
.profile .person p {
font-size: 26px;
color: #c6c5d8;
}
.profile .menu {
margin-top: 100px;
padding: 20px;
background-color: #262467;
border-radius: 30px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
height: 100%;
position: relative;
font-size: 22px;
color: #7c7eaa;
}
.profile .flex {
margin-left: 20px;
display: flex;
align-items: center;
gap: 20px;
}
.profile .flex:hover {
margin-left: 40px;
color: white;
transition: ease-in-out;
}
.logOut {
position: absolute;
bottom: 50px;
}
/*-------------------------- KARTICE ----------------------------------------- */
.main .naslov {
color: grey;
font-size: 30px;
font-weight: bold;
}
.naslov {
display: flex;
align-items: center;
justify-content: space-between;
}
.naslov span {
font-size: 32px;
}
.naslov span:hover {
color: black;
}
.main .left {
display: flex;
flex-direction: column;
margin-left: 30px;
}
.main .left .cards {
background-color: #ffffff;
padding: 20px;
display: flex;
padding: 20px;
border-radius: 20px;
}
.cards {
margin-top: 10px;
}
.cards .singleCard {
display: flex;
width: 100%;
}
.allCards {
display: flex;
flex-direction: column;
}
.cards .singleCard img {
width: 250px;
padding-right: 10px;
}
.cards .opis p {
margin: 0;
padding: 0;
margin-left: 10px;
}
.cards .opis {
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.cards .balance {
margin-left: 30px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
/*------------------------------- CHANGE CARD -------------------------------- */
.changeImg {
height: 50px;
object-fit: cover;
}
.changeSpan {
display: none;
}
.changeJustify {
display: flex;
align-items: center;
}
.changeBalance {
display: none;
}
/*-------------------------- TRANSAKCIJE ----------------------------------------- */
.transakcije {
background-color: white;
display: flex;
flex-direction: column;
padding: 10px;
}
.single-transaction {
display: flex;
margin-left: 10px;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid grey;
}
.single-transaction img {
height: 60px;
width: 60px;
border-radius: 50%;
object-fit: cover;
}
.single-transaction .destination {
font-size: 16px;
color: rgb(73, 73, 73);
font-weight: bold;
}
.single-transaction .amount {
color: rgb(30, 149, 30);
font-weight: bold;
font-size: 16px;
}
.single-transaction:last-child {
border-bottom: 0;
}
/*-------------------------- RIGHT SECTIONS ----------------------------------------- */
/*-------------------------- TRANSFER MONEY ----------------------------------------- */
.right {
display: flex;
flex-direction: column;
margin-left: 100px;
}
.right .transfer {
background-color: #1d1c57;
padding: 50px 20px;
border-radius: 10px;
margin-left: 10px;
margin-right: 20px;
}
.right .transfer input {
height: 30px;
font: 24px;
margin-left: 10px;
}
.right .transfer label {
margin-left: 20px;
color: white;
}
.right .transfer button {
padding: 10px 15px;
color: black;
background-color: white;
border-radius: 5px;
border: 0;
margin-left: 20px;
margin-right: 20px;
}
You are overwriting your amount variable (which points to an input element) with the value inputted into said input.
Hence, after the first click you no longer have a reference to the input element: your code tries to read the value property of the integer amount of the last transaction. This results in the following evaluation: parseInt(amount.value) -> parseInt(undefined) -> NaN.
Change this code:
sendMoneyBtn.addEventListener(`click`, () => {
amount = parseInt(amount.value);
totalMoneyAccount = totalMoneyAccount - amount;
updateProfile(totalMoneyAccount);
});
to something like this:
sendMoneyBtn.addEventListener(`click`, () => {
const amountValue = parseInt(amount.value);
totalMoneyAccount = totalMoneyAccount - amountValue;
updateProfile(totalMoneyAccount);
});
Credit to #JohnnyMopp for noticing it first.
I currently am trying to code a website to animate moving across the x-axis to access different sections of the page (page content in 'tab-content'). I have a navbar that has different headers, this is fixed, I want the user to click on each header and be taken to that section. I managed to take the user to the desired section/div with some JS code however, there isn't any animation it defaults to the selected section/div just suddenly being on screen. How do I animate with pure JS or CSS. I need the clicking of the header to move (motion) the user to that div. I'm new to web dev.
here some of my code
HTML
<div class="main-info">
<div class="nav-container">
<div class="nav-bar">
<ul>
<li data-tab-target="#show" class="tab">Show</li>
<li data-tab-target="#about" class="tab">About</li>
<li data-tab-target="#lookbook" class="tab">Lookbook</li>
<li data-tab-target="#process" class="tab">Process</li>
</ul>
</div>
<div class="info overlay">
<div class="text">
MA
Coming Soon
BA
</div>
Back
</div>
</div>
<div class="tab-content">
<div id="show" data-tab-content class="active">
<p>VIDEO</p>
</div>
<div id="about" data-tab-content>
<p>About</p>
</div>
<div id="lookbook" data-tab-content>
<p>Lookbook</p>
</div>
<div id="process" data-tab-content>
<p>Process</p>
</div>
</div>
</div>
CSS
.main-info {
background-color: transparent;
height: 100vh;
overflow: hidden;
}
.nav-container {
position: fixed;
}
.nav-bar {
width: 80vw;
height: 10vh;
left: 10vw;
position: absolute;
top: 5vh;
}
.nav-bar ul {
text-transform: uppercase;
list-style: none;
margin: 0;
padding: 0;
display: flex;
justify-content: space-around;
}
.tab a {
font-family: Helvetica, sans-serif;
font-weight: bold;
font-size: 1rem;
color: black;
text-decoration: none;
}
.tab:hover {
cursor: pointer;
opacity: 0.6;
}
.tab.active {
background-color: whitesmoke;
}
.info {
width: 90vw;
height: 10vh;
/* border: 1px solid red; */
left: 5vw;
position: absolute;
top: 80vh;
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.info a {
font-family: Helvetica, sans-serif;
font-weight: bold;
font-size: 1.1rem;
color: black;
text-decoration: none;
border: 1px solid teal;
}
.text {
width: 30%;
display: flex;
justify-content: space-between;
}
.tab-content {
border: 1px solid teal;
position: absolute;
left: 0;
top: 0;
height: 100vh;
z-index: -11;
display: flex;
flex: row nowrap;
justify-content: flex-start;
}
[data-tab-content] {
border: 1px solid blueviolet;
background-color: violet;
font-size: 3rem;
color: blue;
scroll-behavior: smooth;
display: none;
width: 100vw;
height: 100vh;
}
.active[data-tab-content] {
display: block;
}
JS
const tabs = document.querySelectorAll('[data-tab-target]');
const tabContents = document.querySelectorAll('[data-tab-content]')
// loop through the list to find the one tab mouse clicked
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const target = document.querySelector(tab.dataset.tabTarget)
tabContents.forEach(tabContent => {
tabContent.classList.remove('active')
})
tabs.forEach(tab => {
tab.classList.remove('active')
});
tab.classList.add('active')
target.classList.add('active');
});
});
You almost got it. Instead of setting the scroll-behavior on the elements that are inside a scrollable element, put it on either the element that has a scrollbar.
.tab-content {
scroll-behavior: smooth;
}
Or on the top most element to have all elements move with a smooth scrolling animation.
:root {
scroll-behavior: smooth;
}