Show and Hide Interactive Web Content with JavaScript in 20 Minutes

Animation. Interactive web page content changes a detailed description based on what graphic design service/skill the user clicks.
Share on facebook
Share on twitter
Share on pinterest
Share on linkedin

Many popular websites allow users to interact with the webpage and toggle content without leaving or reloading. My own website uses this trick to allow users to click to read more information about my skills. An older version of my Process page also used the same trick to create an interactive timeline. Here’s the show/hide JavaScript trick you need to add to your web development portfolio.

For this show/hide JavaScript tutorial, I’m recreating the two-column interactive skills list shown on my homepage. It’s easily adaptable for multiple projects. On the left, users click a skill name to display a description on the right side. The trick is that only the description for the clicked skill shows while the others hide.

Brief UX Requirements for the Show/Hide JavaScript Content

Navigation is important. Although this interactive show/hide JavaScriptelement is simple, it must fulfill some basic UX requirements.

  1. Firstly, users should see clear responses to their actions to learn how to use the tool.
  2. Secondly, users should see clear status updates. The tool should remember which skill name the user clicks and highlight the active link in some way to share the user’s current location in the tool.

I accomplish this by adding obvious state changes to the skill links.

What We’re Using: Vanilla JavaScript

I’m using vanilla JavaScript for this JavaScript tutorial. Going vanilla has several advantages:

  • First, the web page can skip jQuery or plugin downloads to stay light-weight (fast and small).
  • Additionally, the vanilla JavaScript code snippet is less likely to conflict with other code on your WordPress website.
  • Finally, you have the option of adding the code right to the web page to edit everything all in the same place and reduce external calls.
Lara Lee Design | Show and Hide Interactive Web Content with Java Script in 20 Minutes, Learn More >

Here’s the Show/Hide JavaScript Code Snippet:

HTML Explanation

Create Two Columns in the HTML

The show and hide interactive web content needs two parts:

  • A navigational component that’s always visible
  • Additional content that toggles visibility

I opted to lay out these two parts side-by-side. If you allow the navigational element to stack and remain full-screen, ensure it remains visible above-the-fold and therefore easily accessible.

Create a container, a row, and two columns in the HTML.

Column one becomes the navigational component. In my example, this is the skill name list.

Column two becomes the descriptive component. In my example, this is the skill description list.

You can either ID these columns for easier CSS styling or simply use CSS selectors .column:first-child and .column:nth-child(2). However, neither are required for the JavaScript functions later, so it’s simply a matter of preference.

    <article>
      <div class="container">
        <div class="row">
          <div class="column col-50" id="skill-name-nav">
          <!-- Column One Content -->
          </div><!-- ./col-50 -->
          <div class="column col-50" id="skill-description-list">
          <!-- Column Two Content -->
          </div><!-- ./col-50 -->
        </div><!-- ./row -->
      </div><!-- ./container -->
    </article>

Fill Column One with Navigational Links

Create three <h3> with <a> inside.

Give each <h3> its own ID. These IDs will help JavaScript identify which link the user clicks later.

Similarly, give each nested <a> its own ID. The JavaScript doesn’t need this, but the URL bar will update the web page address with the ID of the anchor links here. Therefore, take advantage of the URL update to show keywords.

Finally, each <h3> will have one of two CSS classes: “active” or “inactive.” Choose one to assign the “active” and assign the other two “inactive.”

JavaScript can add these CSS classes once a user clicks a link anyway. Nevertheless, it’s a good idea to pre-populate the interactive web content, so the user doesn’t see a gaping blank space on page load. Adding these CSS classes now in the HTML will assist.

    <article>
      <div class="container">
        <div class="row">
          <div class="column col-50" id="skill-name-nav">
            <h2>Skills:</h2>
            <h3 id="skill-h-1" class="active-h3"><a href="#digital-strategy"><em>01</em> Digital Strategy</a></h3>
            <hr />
            <h3 id="skill-h-2" class="inactive-h3"><a href="#art-direction"><em>02</em> Art Direction</a></h3>
            <hr />
            <h3 id="skill-h-3" class="inactive-h3"><a href="#creative-design"><em>03</em> Creative Design</a></h3>
            <hr />
          </div><!-- ./col-50 -->
          <div class="column col-50" id="skill-description-list">
          <!-- Column Two Content -->
          </div><!-- ./col-50 -->
        </div><!-- ./row -->
      </div><!-- ./container -->
    </article>

Fill Column Two with the Show/Hide Content

Create three <div>, one for each swappable content piece.

Then, assign each <div> its own ID.

Finally, give each a CSS class they all share to style a bunch at once.

    <article>
      <div class="container">
        <div class="row">
          <div class="column col-50" id="skill-name-nav">
            <h2>Skills:</h2>
            <h3 id="skill-h-1" class="active-h3"><a href="#digital-strategy"><em>01</em> Digital Strategy</a></h3>
            <hr />
            <h3 id="skill-h-2" class="inactive-h3"><a href="#art-direction"><em>02</em> Art Direction</a></h3>
            <hr />
            <h3 id="skill-h-3" class="inactive-h3"><a href="#creative-design"><em>03</em> Creative Design</a></h3>
            <hr />
          </div><!-- ./col-50 -->
          <div class="column col-50" id="skill-description-list">
            <div id="skill-description-1" class="skill-description">
              <h2 class="eyebrow-h2">Digital Strategy:</h2>
              <hr /> <span class="quote">Hope is not a strategy.</span>
              <div class="spacer"></div> I address digital needs with creative solutions that work for any timeline and budget. A thorough investigation begins every project to give you research-backed solutions uniquely fitted to your precise needs.
            </div>
            <div id="skill-description-2" class="skill-description">
              <h2 class="eyebrow-h2">Art Direction:</h2>
              <hr /> <span class="quote">The purpose of design is to inform and delight.*</span>
              <div class="spacer"></div> I invent the vision and follow-though on its execution. Creative briefs, branding, peer and competitor analysis, and proven industry best practices all inform my designs for results that grow with you.
              <div class="spacer"></div> <small>*Milton Glaser, the famous designer behind I♥NY, reflects on Horace</small>
            </div>
            <div id="skill-description-3" class="skill-description">
              <h2 class="eyebrow-h2">Creative Design:</h2>
              <hr /> <span class="quote">Brilliant display, the smart way.</span>
              <div class="spacer"></div> I create digital assets with graphic and web design, web development, and motion graphics. I thrive staring at a blank paper and love embedding visual language into my work to tell your story.
            </div>
          </div><!-- ./col-50 -->
        </div><!-- ./row -->
      </div><!-- ./container -->
    </article>

CSS Explanation

The column set-up is rather straightforward. I apply width styles and add flex to allow the columns to grow and constrain in the ways I want.

       body {
         font-family: "Montserrat", "Trebuchet MS", Helvetica, sans-serif;
         font-weight: 500;
         color: #6b7070;
       }

       article {
         width: 100%;
         max-width: 1080px;
         display: -webkit-box;
         display: -webkit-flex;
         display: -ms-flexbox;
         display: flex;
         margin-right: auto;
         margin-left: auto;
         position: relative;
         box-sizing: border-box;
         padding: 20px;
       }

       .row {
         width: 100%;
         display: -webkit-box;
         display: -webkit-flex;
         display: -ms-flexbox;
         display: flex;
       }

       .col-50 {
         width: 50%;
       }

Targeting the Columns

Earlier I wrote you can either ID these or use CSS selectors .column:first-child and .column:nth-child(2) based on preference. WordPress separated styles that could be otherwise condensed based on how the widgets work. However, I decided to keep both to demonstrate examples.

.column:first-child { }
/* or */
#skill-name-nav { }

.column:nth-child(2) { }
/* or */
#skill-description-list {}

First Column Styles for the Skill Name Navigational Component

       .column:first-child {
         background: #eb3b25;
         padding: 60px;
         position: relative;
         box-shadow: 0 0 40px rgba(0, 0, 0, 0.4);
       }

       #skill-name-nav {
         text-align: center;
       }

       #skill-name-nav h2 {
         text-align: center;
         margin-bottom: 40px;
         font-size: 12px;
         font-family: Montserrat;
         font-weight: 700;
         text-transform: uppercase;
         letter-spacing: .1em;
         color: #fff;
       }

       #skill-name-nav h3,
       .inactive-h3 {
         font-family: "Playfair Display", "Times Bold", Times, "Times New Roman Bold", "Times New Roman", serif;
         font-weight: 800 !important;
         margin-bottom: 60px;
         font-size: 28px;
         text-align: center;
         position: relative;
         bottom: 0;
         color: rgba(255, 255, 255, .5);
         transition: .5s ease all;
       }

       #skill-name-nav h3 em {
         font-size: 20px;
         position: relative;
         bottom: 4px;
       }

Second Column Styles for the Show/Hide JavaScript Content

       .column:nth-child(2) {
         position: relative;
         background: #fff;
         padding: 60px;
         box-shadow: 0 0 30px rgba(0, 0, 0, 0.1);
       }

       .spacer {
         display: block;
         height: 30px;
       }

       .skill-description {
         align-self: flex-start;
         line-height: 28px;
       }

       .eyebrow-h2 {
         font-size: 12px;
         font-family: 'Montserrat';
         font-weight: bold;
         text-transform: uppercase;
         letter-spacing: .1em;
         color: #6b7070;
       }

       .eyebrow-h2+hr {
         border: 1px solid #eb3b25;
         margin: 20px 0 40px;
         width: 50px;
       }

       .quote {
         font-size: 2em;
         font-family: 'Playfair Display';
         font-weight: 900;
         line-height: 1.25em;
         color: #2b3738;
       }

Differentiating Link States in the Show/Hide JavaScript Content

The link states deserve particular attention to address the UX issues above. New CSS styles differentiate the link states:

  • Inactive links are dull and plain
  • Active links are bright and flanked by em dashes
  • Hover/focus links are bright, lifted, and underlined by a <hr>

Also include :hover, :active, and :focus styles. They keep the links the most accessible across devices.

Additionally, consider style changes besides color alone, which some users find difficult to see. Consequently, I added em dashes to either side of active links as well as the lift + underline to hovered/focused links.

Screenshot. The show/hide JavaScript tool uses a variety of link styles to communicate interactivity. An inactive link is dull.
Inactive.
Screenshot. An inactive hovered/focused link is bright, underlined, and gives off a drop shadow in the show/hide JavaScript content.
Inactive + hover/focus.
Screenshot. An active link is bright, flanked by em dashes, and gives off a drop shadow.
Active.
Screenshot. An active hovered/focused link is bright, flanked by em dashes, underlined, and gives off a drop shadow.
Active + hover/focus.
       #skill-name-nav .inactive-h3 {
         font-family: "Playfair Display", "Times Bold", Times, "Times New Roman Bold", "Times New Roman", serif;
         font-weight: 800 !important;
         margin-bottom: 60px;
         font-size: 28px;
         text-align: center;
         position: relative;
         bottom: 0;
         color: rgba(255, 255, 255, .5);
         transition: .5s ease all;
       }

       #skill-name-nav a {
         font-weight: 800;
         box-shadow: none;
         text-decoration: none;
         color: rgba(255, 255, 255, 1);
       }

       #skill-name-nav .active-h3,
       #skill-name-nav .active-h3 a {
         color: rgba(255, 255, 255, 1);
       }

       #skill-name-nav .inactive-h3 a {
         color: rgba(255, 255, 255, .5);
       }

       #skill-name-nav h3:hover,
       #skill-name-nav h3:active,
       #skill-name-nav h3:focus,
       .active-h3 {
         bottom: 10px;
         color: rgba(255, 255, 255, 1.0);
         text-shadow: 0 0 20px rgba(0, 0, 0, 0.4);
       }

       #skill-name-nav .active-h3:before {
         content: "\2014  ";
         color: rgba(255, 255, 255, 1.0);
         font-weight: normal;
       }

       #skill-name-nav .active-h3:after {
         content: " \2014";
         color: rgba(255, 255, 255, 1.0);
         font-weight: normal;
       }

       #skill-name-nav h3:hover a,
       #skill-name-nav h3:active a,
       #skill-name-nav h3:focus a,
       #skill-name-nav .active-h3 a {
         color: rgba(255, 255, 255, 1.0);
       }

       #skill-name-nav hr,
       .inactive-hr {
         border: none;
         width: 0;
         margin: 0 auto;
         height: 2px;
         background-color: #eb3b25;
         position: relative;
         top: -30px;
         transition: .5s ease all;
       }

       #skill-name-nav h3:hover+hr,
       #skill-name-nav h3:active+hr,
       #skill-name-nav h3:focus+hr,
       .active-hr {
         background-color: #fff;
         width: 200px;
         text-shadow: 0 0 20px rgba(0, 0, 0, 0.4);
         top: -40px;
       }

Nothing’s Hiding After Completing the CSS

After completing the styles, you’ve probably noticed all three descriptions are showing. They should be! Because not every user enables JavaScript in their web browsers, your interactive web content needs a non-JavaScript back-up. Therefore, the natural behavior here is showing, not hiding.

Vanilla JavaScript Explanation

The JavaScript code is the most likely part to stump front-end web developers. I’ve labeled the code snippet with comments to help you navigate the JavaScript.

Hide All but One of the Service Descriptions on Page Load

Since all the hidden content is shown by default (remember the no JavaScript back-up?), the first thing a JavaScript-enabled browser needs to do is to hide the inactive descriptions.

I prefer to initialize a function before executing it, because it makes sense to know what you’re going to do before you can do it. However, JavaScript permits web developers to do the reverse as well.

Add function hideSkills().

       //Store a function that loops through each service list item and hides it
       function hideSkills() {

       };

Within it, create a simple for loop. The for loop scans the web page for all the elements with the CSS class “skill-description.” As the loop finds each one, it hides the service description by changing the CSS display: block to display: none.

       //Store a function that loops through each service list item and hides it
       function hideSkills() {
         for (var i = 0; i < document.getElementsByClassName("skill-description").length; i++) {
           document.getElementsByClassName("skill-description")[i].style.display = "none";
         };
       };

Then execute the hideSkills() function.

       //Store a function that loops through each service list item and hides it
       function hideSkills() {
         for (var i = 0; i < document.getElementsByClassName("skill-description").length; i++) {
           document.getElementsByClassName("skill-description")[i].style.display = "none";
         };
       };

       //On page load, hide all the service descriptions...
       hideSkills();

If you preview the web page now, all the service descriptions disappear and users see a blank piece of content. This function will be useful later to “reset” the tool whenever a user clicks a link.

Now, add a line of JavaScript to show the first description only. Remember JavaScript counts starting at 0. So the first description in number [0] in the loop’s array, and the second description is [1], and the third [2].

       //Store a function that loops through each service list item and hides it
       function hideSkills() {
         for (var i = 0; i < document.getElementsByClassName("skill-description").length; i++) {
           document.getElementsByClassName("skill-description")[i].style.display = "none";
         };
       };

       //On page load, hide all the service descriptions...
       hideSkills();

       //...Except the first
       document.getElementsByClassName("skill-description")[0].style.display = "block";

Initialize a Function that Deactivates All the Links

This is the second function to “reset” the tool on a click. Whereas the first function, hideSteps(), hides the descriptive content, this function will dull the navigational content to make the links appear deactivated.

Add a function deactivate(). Within it, call each <h3> by ID and set the CSS class to “inactive.”

       //Store a function that deactivates service headlines
       function deactivate() {
         document.getElementById("skill-h-1").className = "inactive-h3";
         document.getElementById("skill-h-2").className = "inactive-h3";
         document.getElementById("skill-h-3").className = "inactive-h3";
       };

Find the Link the User Clicked, Activate It, and Show Its Description

First, gather all the <h3> links into a group that the JavaScript can loop through in its search for the click. Create a variable, make it an array, and fill it with the names of the <h3> link IDs.

       //Collect IDs into an iterable array
       var headlineArray = [
         "skill-h-1", //equal to headlineArray[0]
         "skill-h-2", //equal to headlineArray[1]
         "skill-h-3", //equal to headlineArray[2]
       ];

Then create a for loop.

       //Collect IDs into an iterable array
       var headlineArray = [
         "skill-h-1", //equal to headlineArray[0]
         "skill-h-2", //equal to headlineArray[1]
         "skill-h-3", //equal to headlineArray[2]
       ];

       //Go through each headline one at a time
       for (var i = 0; i < headlineArray.length; i++) {

       };

Tell the loop to find each <h3> named in the array and give it an event listener listening for clicks.

       //Collect IDs into an iterable array
       var headlineArray = [
         "skill-h-1", //equal to headlineArray[0]
         "skill-h-2", //equal to headlineArray[1]
         "skill-h-3", //equal to headlineArray[2]
       ];

       //Go through each headline one at a time
       for (var i = 0; i < headlineArray.length; i++) {
         //Listen for a click on each headline                  document.getElementById(headlineArray[i]).addEventListener("click", function() {

         }, false);
       };

In the event listener, open an unnamed function that describes what to do when it hears a click.

Start by resetting the tool: run functions hideSkills() and deactivate().

       //Collect IDs into an iterable array
       var headlineArray = [
         "skill-h-1", //equal to headlineArray[0]
         "skill-h-2", //equal to headlineArray[1]
         "skill-h-3", //equal to headlineArray[2]
       ];

       //Go through each headline one at a time
       for (var i = 0; i < headlineArray.length; i++) {
         //Listen for a click on each headline
         document.getElementById(headlineArray[i]).addEventListener("click", function() {
           //If ANY of the headlines are clicked, hide ALL
           hideSkills();
           deactivate();
         }, false);
       };

Next, remember the link that was clicked and save it as a variable.

       //Go through each headline one at a time
       for (var i = 0; i < headlineArray.length; i++) {
         //Listen for a click on each headline
         document.getElementById(headlineArray[i]).addEventListener("click", function() {
           //If ANY of the headlines are clicked, hide ALL
           hideSkills();
           deactivate();
           //Record the ID of the clicked icon
           var headlineClicked = this.getAttribute("id");

         }, false);
       };

Finally—this is the part where it all happens—create a series of if else statements that ask if each <h3> was clicked and if it was to display that link’s matching description. If no clicks were detected, display a console message useful for debugging.

       //Go through each headline one at a time
       for (var i = 0; i < headlineArray.length; i++) {
         //Listen for a click on each headline
         document.getElementById(headlineArray[i]).addEventListener("click", function() {
           //If ANY of the headlines are clicked, hide ALL
           hideSkills();
           deactivate();
           //Record the ID of the clicked icon
           var headlineClicked = this.getAttribute("id");

           //Test which headline was clicked and only display the clicked headline's matching description
           if (headlineClicked == "skill-h-1") {
             document.getElementById("skill-h-1").className = "active-h3";
             document.getElementById("skill-description-1").style.display = "block";
             document.getElementsByTagName("h3")[0].style.color = "#fff";
           } else if (headlineClicked == "skill-h-2") {
             document.getElementById("skill-h-2").className = "active-h3";
             document.getElementById("skill-description-2").style.display = "block";
             document.getElementsByTagName("h3")[1].style.color = "#fff";
           } else if (headlineClicked == "skill-h-3") {
             document.getElementById("skill-h-3").className = "active-h3";
             document.getElementById("skill-description-3").style.display = "block";
             document.getElementsByTagName("h3")[2].style.color = "#fff";
           } else {
             console.log("No headline was clicked.");
           };
         }, false);
       };

Here’s the all the code to the show/hide JavaScript trick once more:

For more show/hide JavaScript tricks using just vanilla JS code, check out Chris Ferdinandis tutorial at Go Make Things discussing show(), hide(), and toggle().

Check out my other JavaScript tutorial:

Lara Lee Design | How To Code A Filterable Image Gallery With JavaScript, Learn More

How To Code A Filterable Image Gallery With JavaScript