简体   繁体   中英

Using JS to toggle between two HTML Elements

Looking to make an interactive landing page, and I would like visitors to click on a HTML element, which then disappears and is replaced by another.

I've included the code below for your review, and the codepen link: https://codepen.io/riza-khan/pen/pMrWKw

The issue is that the toggle does not work and after multiple clicks both h4 and p tags completely disappear. I've tried switching where the place the .hide class in the CSS (which for some reason makes a difference, and I don't understand why).

 const switchElements = document.querySelectorAll('.switch'); for(const switchElement of switchElements) { switchElement.addEventListener('click', (e) => { e.target.classList.toggle('hide'); e.target.nextSibling.classList.toggle('hide') }) } 
 .main{ margin-top: 20px; display: grid; grid-template-columns: repeat(2,1fr); } .three-points { display: grid; grid-template-columns: 1fr 3fr; grid-template-rows: repeat(3,1fr); i { display:grid; justify-content: center; } h4 { display:grid; align-content: center; justify-content: start; border:solid; } } } .hide { display: none; } 
 <div class="main"> <div class="three-points"> <i class="fab fa-google fa-5x"></i><h4 class="switch">SEO Optomized</h4><p class="switch hide">Utilizing best practices to ensure page is ranked appopriately</p> <i class="fa fa-mobile fa-5x"></i><h4 class="switch">Responsive Design</h4><p class="switch hide">Lorem ipsum dolor sit amet consectetur, adipisicing elit. At autem culpa possimus facere. Recusandae.</p> <i class="fa fa-window-maximize fa-5x"></i><h4 class="switch">Elegant Themes</h4><p class="switch hide">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Sunt quis consequatur asperiores. Odit, voluptates nihil.</p> </div> </div> 

Ok so the issue is that the JS is looking for the nextSibling. After the first click, how can I use an if function to remove .hide from the previousSibling ?


The problem is in your CSS. The biggest problem is that the parentheses are unbalanced, so the .hide definition gets missed. Secondary issue is that the nested definitions are not CSS. They look like less or sass.

Hi please check the logic below to hide/show the h and p tag back and forth. Also to toggle on click event in p tag

 var switchElements = document.getElementsByClassName("switch"); var i; for (i = 0; i < switchElements.length; i++) { switchElements[i].addEventListener("click", function() { this.classList.toggle("active"); if(this.classList.contains("hide")){ // hide on <p> tag click this.style.display = "none"; this.previousSibling.style.display = "block"; }else{ this.style.display = "none"; var content = this.nextElementSibling; if (content.style.display === "block") { content.style.display = "none"; } else { content.style.display = "block"; } } }); } 
 .main{ margin-top: 20px; display: grid; grid-template-columns: repeat(2,1fr); } .hide { display: none; } .three-points { display: grid; grid-template-columns: 1fr 3fr; grid-template-rows: repeat(3,1fr); i { display:grid; justify-content: center; } h4 { display:grid; align-content: center; justify-content: start; border:solid; } } 
 <div class="main"> <div class="three-points"> <i class="fab fa-google fa-5x"></i><h4 class="switch">SEO Optomized</h4><p class="switch hide">Utilizing best practices to ensure page is ranked appopriately</p> <i class="fa fa-mobile fa-5x"></i><h4 class="switch">Responsive Design</h4><p class="switch hide">Lorem ipsum dolor sit amet consectetur, adipisicing elit. At autem culpa possimus facere. Recusandae.</p> <i class="fa fa-window-maximize fa-5x"></i><h4 class="switch">Elegant Themes</h4><p class="switch hide">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Sunt quis consequatur asperiores. Odit, voluptates nihil.</p> </div> </div> 

I believe the issue is due to the fact that you are adding the event listener to all elements immediately. Instead, try adding and removing the event listener dynamically as required. You should add the .hide class to all elements in HTML except the first (default shown) element. I have tested the below:

const switchElements = document.querySelectorAll('.switch');
let activeElement = 0

let cycleElements = function() {
    switchElements[activeElement].removeEventListener('click', cycleElements)
    switchElements[activeElement].classList.add('hide')

    if (activeElement >= switchElements.length - 1) {
        activeElement = 0
    } else {
        activeElement++
    }

    switchElements[activeElement].addEventListener('click', cycleElements)
    switchElements[activeElement].classList.remove('hide')
}

switchElements[activeElement].addEventListener('click', cycleElements)

Add classes like below:

<div class="main">
<div class="three-points">
    <i class="fab fa-google fa-5x"></i><h4 class="switch">SEO Optomized</h4><p class="switch hide">Utilizing best practices to ensure page is ranked appopriately</p>
    <i class="fa fa-mobile fa-5x"></i><h4 class="switch hide">Responsive Design</h4><p class="switch hide">Lorem ipsum dolor sit amet consectetur, adipisicing elit. At autem culpa possimus facere. Recusandae.</p>
    <i class="fa fa-window-maximize fa-5x"></i><h4 class="switch hide">Elegant Themes</h4><p class="switch hide">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Sunt quis consequatur asperiores. Odit, voluptates nihil.</p>
</div>
</div>

EDIT START:

Not sure if I want to start another question for this but I would like to know why moving the CSS class .hide breaks the below code:

Thanks,

EDIT END:

Figured it out.

Had to add another Eventlistener that listened for a click on the

tag. Code is below:

HTML:

<div class="main">

<div class="three-points">

  <i class="fa fa-google fa-5x"></i><h4 class="switch">SEO Optomized</h4><p class="back hide">Utilizing best practices to ensure page is ranked appopriately</p>
  <i class="fa fa-mobile fa-5x"></i><h4 class="switch">Responsive Design</h4><p class="back hide">Lorem ipsum dolor sit amet consectetur, adipisicing elit. At autem culpa possimus facere. Recusandae.</p>
  <i class="fa fa-window-maximize fa-5x"></i><h4 class="switch">Elegant Themes</h4><p class="back hide">Lorem ipsum, dolor sit amet consectetur adipisicing elit. Sunt quis consequatur asperiores. Odit, voluptates nihil.</p>

</div>

</div>

CSS:

.main {


    margin-top: 20px;
    display: grid;
    grid-template-columns: repeat(2,1fr);



    .three-points {

        .hide {

            display: none;
        }


        display: grid;
        grid-template-columns: 1fr 3fr;
        grid-template-rows: repeat(3,1fr);

            i {
                display:grid;
                justify-content: center;
            }

            h4 {
                display:grid;
                align-content: center;
                justify-content: start;
                border:solid;
            }
    }
}

JS:

const switchElements = document.querySelectorAll('.switch');

for(const switchElement of switchElements) {
    switchElement.addEventListener('click', (e) => {

        e.target.classList.add('hide');
        e.target.nextSibling.classList.remove('hide');

    })
}

const backElements = document.querySelectorAll('.back');

for (const backs of backElements) {
    backs.addEventListener('click', (e) => {
        e.target.classList.add('hide');
        e.target.previousSibling.classList.remove('hide');
    })
}

Ok, I wouldn't say this is a legit answer, since I'm not solving this question with JS.

But reality is, there's always multiple ways to solve (or you might call it a hack) a problem.

This is the approach I use quite a few times on production, and doesn't require a single line of javascript.

I'm not reuse your code, but write my own to keep it as simple as it is, but the idea is easy enough to apply on your case.

if you want to keep them opened, the radio can be changed to checkbox.

 label { display: block; border: 1px solid red; } input { display: none; } div { visibility: hidden; } input:checked ~div { visibility: visible; } 
 <label for="radio1"> <input type="radio" id="radio1" name="toggler"> toggle 1 <div> this is the first content </div> </label> <label for="radio2"> <input type="radio" id="radio2" name="toggler"> toggle 2 <div> this is the second content </div> </label> <label for="radio3"> <input type="radio" id="radio3" name="toggler"> toggle 3 <div> this is the third content </div> </label> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM