Hiding HTML Content with javascript via class names

My code has 7 nav links all with the same class, and because the html is quite long, I want to be able to hide contents until the link is clicked, and also have the content disappear when another nav link is clicked; allowing space for the next. I would prefer the answer in vanilla js, as that is what i am learning now. Here is a link to my pen please:Codepen

I started typing, started getting creative… how familiar are you with javascript? have you used document.querySelectorAll(...) yet? Have you done event listeners?

1 Like

All you need is Vertical Tabs based on the way you want your contents to be displayed.

1 Like

The easiest way for you to achieve this is to hide every section, and then afterwards immediately show the section you want to be visible.

So first you would need to prepare your HTML so that you can select the areas you want to hide. Right now each of your sections is just a header followed by a paragraph element. You’ll want to wrap each of those inside an element with a unique ID, while also giving each of them a shared class name so you can easily hide them all at once.

<nav>
    <ul>
        <li><a href="#">Section One</a></li>
        <li><a href="#">Section Two</a></li>
        <li><a href="#">Section Three</a></li>
    </ul>
</nav>
<div id="section-one" class="hideable-section">
    <!-- Notice these sections have unique
         IDs, but shared class names. -->
    <h1>Section One</h1>
    <p>Lorem ipsum get some coffee.</p>
</div>
<div id="section-two" class="hideable-section">
    <h1>Section Two</h1>
    <p>Lorem ipsum drink that coffee.</p>
</div>
<div id="section-three" class="hideable-section">
    <h1>Section Three</h1>
    <p>No coffee no life.</p>
</div>

Next let’s make a function that hides all the sections.

/* JavaScript */
var hideEverything = function hideEverything() {
    var hideableSections = document.querySelectorAll('.hideable-section');
    /* document.querySelectorAll() will return a JavaScript object
       containing all nodes which match the query. Since you are
       passing '.hideable-section' the returned object will contain
       all elements with that class. */
    var keyArray = Object.keys(hideableSections);
    /* Object.keys() returns an array of the keys in an object. In this case
       it will return an array of [0,1,2] (assuming the sections I've provided
       in this example).*/
    keyArray.forEach(function(key){
        hideableSections[key].style.display = 'none';
    });
    /* forEach() is a method that can be called on any array. It
       loops through the array and executes the provided callback 
       function passing as the first parameter each item in the array. 
       Since this is a list of keys, we can use each one as a key on the
       hideableSections JavaScript obect and set the styles from there.*/
}

The above function is probably the hardest bit of this whole thing, as it requires an understanding of how to iterate over objects in JavaScript. You don’t have to use the method I used. It’s just the one I like. You could just as easily do this with a classic for loop based on the length of the object.

Here is an example of the hideEverything function but with a classic for loop.

var hideEverything = function hideEverything() {
    var hideableSections = document.querySelectorAll('.hideable-section');
    for (var i = 0; i < hideableSections.length; i++) {
        hideableSections[i].style.display = 'none';
    }
}

Next, we’ll want to make a function that shows whatever element Id it is provided. We’ll also have the function execute our new hideEverything() function first, so that the other sections will be hidden before showing the one that we want.

/* JavaScript */
var showSectionWithId = function showSectionWithId(id) {
    hideEverything(); /* This will hide all of the sections with
                         the class .hideable-section */
    var element = document.getElementById(id); /* Grab the element
                                                  you want and assign
                                                  it to a variable. */
    element.style.display = 'block'; /* Setting 'display' to 'block' 
                                        will make it visible. */
}

Next we’ll want to set up the page how you want it to look when it loads. There are two ways you could do this. You could set things up with CSS.

/* CSS */
.hideable-section {
    display: none;
}

#section-one {
    display: block;
}

However, you could not do this with CSS and instead just call showSectionWithId('section-one') from within your JavaScript on page load. One advantage of doing it the JavaScript way is that if for some reason JavaScript is unavailable or disabled, the page will still show all of the content. That having been said, these days in modern web design it isn’t something that you need to worry about that much. The example I will provide at the end will do it the JavaScript way.

Finally, we’ll need to add our function to the onclick attribute of each of our links.

<li><a href="#" onclick="showSectionWithId('section-one')">Section One</a></li>
<li><a href="#" onclick="showSectionWithId('section-two')">Section Two</a></li>
<li><a href="#" onclick="showSectionWithId('section-three')">Section Three</a></li>

Notice that for each one we’re passing in the Id of the section that we want to show.

And you’re done. Here is the full example on CodePen.

1 Like

Hi, I think you can do this with pure CSS and HTML, here is the pen I’ve made for myself some time ago, using the radio input method. Maybe this will be useful to you, somehow.

You will still need some JS to add listeners for those navs onclick to make it auto scroll to the top everytime the content is changed, tho.

4 Likes

Yea the document.querySelectorAll(…) did not work, or rather I did not get it right. As for event listeners i haven’t quite gotten there yet.
Thanks for your advice tho I will keep typing and keep learning

Thanks boss I will look into that. It was also outlined by a guy on stack overflow, so i guess i am going to have to ditch my anchor tags

Thanks will look through your pen. Happy for the input

Taking out the extra time to help me and still explain in so much detail is inspiring sir. Thank you so much. I’ve been away but will dissect the entire codebase you sent, today. I will alert you when i’m done. I do hope to pair program with you sometime if you can spare the time.
Cheers

Could you throw some light on the syntax from line 44 to 47?Preformatted text
#tab1:checked ~ header .tab1 label,
#tab2:checked ~ header .tab2 label,
#tab3:checked ~ header .tab3 label,
#tab4:checked ~ header .tab4 label

Neat CSS by the way

Hello, you should check out this document for understanding sibling combinators.

Basically, those lines mean to change the currently “active” tab label style (currently “checked” radio input), to better distinguish of them.

1 Like

Hello Micheal I have tried to rebuild your js code. I got the first one working, but the second option with the for loop, hides all the content.

I got the first one working, but the second option with the for loop, hides all the content.

That’s what it is meant to do. This function,

var hideEverything = function hideEverything() {
    var hideableSections = document.querySelectorAll('.hideable-section');
    Object.keys(hideableSections).forEach(function(key){
        hideableSections[key].style.display = 'none';
    });
}

and this function

var hideEverything = function hideEverything() {
    var hideableSections = document.querySelectorAll('.hideable-section');
    for (var i = 0; i < hideableSections.length; i++) {
        hideableSections[i].style.display = 'none';
    }
}

both hide all the content. Just in two different ways.

After you hide everything, then you need to show the part of the page you want to show. Look again at the showSectionWithId function I provided.

var showSectionWithId = function showSectionWithId(id) {
    hideEverything();
    document.getElementById(id).style.display = 'block';
}

First it runs hideEverything (it doesn’t matter how everything is hidden, just that everything is hidden) and then afterwards it sets a single element to have display: block.

Here is a working CodePen using the for loop method for hiding everything.

Thanks it is clearer now