Search code examples
javascripthtmlcss

I'm having trouble with a second set of buttons/tabs, where when I click the other set of buttons it replaces the whole section the first set controls


In my code right now there's two sets of buttons. One controls the like, main area, and in one of the tabs for the main area it shows a box meant to hold an image. There's also an area to the side that switches with tabs.

For some reason, my second set of images causes the area to go blank, displaying nothing and removing the box. How do I fix this? Where did I go wrong? I honestly have no clue what's up with this.

I tried messing with the naming conventions and altering the javascript very lightly a few times, but, admittedly I don't know javascript much at all yet so there wasn't much I knew to do.

I'm guessing that I misplaced the tabs div in the HTML but I tried moving it around and it didn't change anything at all. I'm so lost on this I've spent two days getting no work done because I just don't know what's going on with the issue.

function Tabs(evt, tabName) {
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }
  document.getElementById(tabName).style.display = "block";
  evt.currentTarget.className += " active";

}

document.getElementById("defaultOpen").click();
#wrapper {
  width: 100%;
  height: 100%;
  display: inline-block;
}

#main {
  color: red;
  background-color: pink;
  width: 52%;
  height: 30rem;
  margin-top: 3rem;
  margin-inline: auto;
  border: 6px solid;
  border-color: brown;
  border-radius: 15% / 38px;
  padding: 4px;
}

#content {
  color: rgb(0, 0, 0);
  background-color: beige;
  width: 96%;
  height: 27rem;
  position: relative;
  top: 1.4rem;
  margin-inline: auto;
  border: 4.5px solid brown;
  border-radius: 15% / 30px;
  overflow: auto;
  scrollbar-width: none;
}

#profileimage {
  background-color: pink;
  width: 16rem;
  height: 25rem;
  border: 2.5px solid brown;
  border-radius: 15% / 15px;
  position: relative;
  top: 0.4rem;
}

#references {
  color: red;
}

.flex-container {
  display: flex;
  flex-wrap: wrap;
  margin: 0 auto;
}

.box {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: calc(25% - 10px);
  margin: 5px;
}

img {
  width: 100%;
}

.tab {
  position: relative;
  text-align: center;
  top: 4.5rem;
}

.tab button {
  background-color: burlywood;
  padding: 4px;
  width: 10rem;
  font-size: 1.8rem;
  border: 6px solid brown;
  border-radius: 10% / 8px;
  cursor: pointer;
  color: rgb(176, 103, 66);
}

.tab2 {
  position: absolute;
  text-align: center;
  top: 0.5rem;
  left: 22rem;
}

.tab2 button {
  background-color: burlywood;
  width: 8rem;
  font-size: 18px;
  border: 3.5px solid brown;
  border-radius: 10% / 8px;
  cursor: pointer;
  color: rgb(176, 103, 66);
}

.tab button:hover {
  background-color: rgb(191, 147, 89);
  color: rgb(144, 58, 32);
  border: 6px solid brown;
  border-radius: 10% / 8px;
}

.tab button:active {
  background-color: rgb(153, 73, 51);
  color: rgb(70, 21, 6);
  border: 4px solid brown;
  border-radius: 10% / 8px;
}

.tabcontent {
  display: none;
  padding: 6px 12px;
  border-top: none;
}
<div id="wrapper">
  <div class="tab">
    <button class="tablinks" onclick="Tabs(event, 'profile')" id="defaultOpen">Profile</button>
    <button class="tablinks" onclick="Tabs(event, 'ref')">Ref Sheet</button>
  </div>

  <div id="main">
    <div id="content">
      <div id="profile" class="tabcontent">
        <div id="profileimage"></div>
        <div class="tab2" id="buttons2">
          <button class="tablinks" onclick="Tabs(event, 'about')" id="defaultOpen">About</button>
          <button class="tablinks" onclick="Tabs(event, 'extra')">Extra</button>
        </div>
        <div id="about" class="tabcontent">hello</div>
      </div>
      <div id="ref" class="tabcontent">
        <div id="references" class="flex-container">
          <div class="box">
            <img src="https://t3.ftcdn.net/jpg/03/45/05/92/360_F_345059232_CPieT8RIWOUk4JqBkkWkIETYAkmz2b75.jpg">
          </div>
          <div class="box">
            <img src="https://t3.ftcdn.net/jpg/03/45/05/92/360_F_345059232_CPieT8RIWOUk4JqBkkWkIETYAkmz2b75.jpg">
          </div>
          <div class="box">
            <img src="https://t3.ftcdn.net/jpg/03/45/05/92/360_F_345059232_CPieT8RIWOUk4JqBkkWkIETYAkmz2b75.jpg">
          </div>
          <div class="box">
            <img src="https://t3.ftcdn.net/jpg/03/45/05/92/360_F_345059232_CPieT8RIWOUk4JqBkkWkIETYAkmz2b75.jpg">
          </div>
          <div class="box">
            <img src="https://t3.ftcdn.net/jpg/03/45/05/92/360_F_345059232_CPieT8RIWOUk4JqBkkWkIETYAkmz2b75.jpg">
          </div>
          <div class="box">
            <img src="https://t3.ftcdn.net/jpg/03/45/05/92/360_F_345059232_CPieT8RIWOUk4JqBkkWkIETYAkmz2b75.jpg">
          </div>
        </div>
      </div>
    </div>
  </div>
</div>


Solution

  • I had some issues with your nesting. I solved it by adding a wrapper and data attributes (data-target)

    Also the code can be much simpler using toggle and delegation

    Thanks to McCrossan for the :scope, that is useful

    document.getElementById('wrapper').addEventListener('click', (e) => {
      const btn = e.target.closest('button.tablinks');
      if (!btn) return;
      
      const targetId = btn.dataset.target;
      const currentTab = document.getElementById(targetId);
      if (!currentTab) return;
      
      // Use the parent of the target tab as the container.
      const container = currentTab.parentElement;
      
      // Only toggle direct children of that container.
      container.querySelectorAll(':scope > .tabcontent').forEach(tab => {
        tab.classList.toggle('active', tab === currentTab);
      });
    });
    #wrapper {
      width: 100%;
      height: 100%;
      display: inline-block;
    }
    
    #main {
      color: red;
      background-color: pink;
      width: 52%;
      height: 30rem;
      margin-top: 3rem;
      margin-inline: auto;
      border: 6px solid;
      border-color: brown;
      border-radius: 15% / 38px;
      padding: 4px;
    }
    
    #content {
      color: rgb(0, 0, 0);
      background-color: beige;
      width: 96%;
      height: 27rem;
      position: relative;
      top: 1.4rem;
      margin-inline: auto;
      border: 4.5px solid brown;
      border-radius: 15% / 30px;
      overflow: auto;
      scrollbar-width: none;
    }
    
    #profileimage {
      background-color: pink;
      width: 16rem;
      height: 25rem;
      border: 2.5px solid brown;
      border-radius: 15% / 15px;
      position: relative;
      top: 0.4rem;
    }
    
    #references {
      color: red;
    }
    
    .flex-container {
      display: flex;
      flex-wrap: wrap;
      margin: 0 auto;
    }
    
    .box {
      flex-grow: 1;
      flex-shrink: 1;
      flex-basis: calc(25% - 10px);
      margin: 5px;
    }
    
    img {
      width: 100%;
    }
    
    .tab {
      position: relative;
      text-align: center;
      top: 4.5rem;
    }
    
    .tab button {
      background-color: burlywood;
      padding: 4px;
      width: 10rem;
      font-size: 1.8rem;
      border: 6px solid brown;
      border-radius: 10% / 8px;
      cursor: pointer;
      color: rgb(176, 103, 66);
    }
    
    .tab2 {
      position: absolute;
      text-align: center;
      top: 0.5rem;
      left: 22rem;
    }
    
    .tab2 button {
      background-color: burlywood;
      width: 8rem;
      font-size: 18px;
      border: 3.5px solid brown;
      border-radius: 10% / 8px;
      cursor: pointer;
      color: rgb(176, 103, 66);
    }
    
    .tab button:hover {
      background-color: rgb(191, 147, 89);
      color: rgb(144, 58, 32);
      border: 6px solid brown;
      border-radius: 10% / 8px;
    }
    
    .tab button:active {
      background-color: rgb(153, 73, 51);
      color: rgb(70, 21, 6);
      border: 4px solid brown;
      border-radius: 10% / 8px;
    }
    
    .tabcontent {
      padding: 6px 12px;
      border-top: none;
      display: none;
    }
    
    .tabcontent.active {
      display: block;
    }
    <div id="wrapper">
      <!-- Outer tabs -->
      <div class="tab">
        <button class="tablinks active" data-target="profile">Profile</button>
        <button class="tablinks" data-target="ref">Ref Sheet</button>
      </div>
    
      <div id="main">
        <div id="content">
          <!-- Outer tab content: Profile -->
          <div id="profile" class="tabcontent active">
            <div id="profileimage"></div>
            <!-- Inner tab buttons -->
            <div class="tab2" id="buttons2">
              <button class="tablinks active" data-target="about">About</button>
              <button class="tablinks" data-target="extra">Extra</button>
            </div>
            <!-- Wrap inner tab content in its own container -->
            <div class="inner-tab-container">
              <div id="about" class="tabcontent active">About</div>
              <div id="extra" class="tabcontent">Extra content</div>
            </div>
          </div>
    
          <!-- Outer tab content: Ref Sheet -->
          <div id="ref" class="tabcontent">
            <div id="references" class="flex-container">
              <div class="box">
                <img src="https://t3.ftcdn.net/jpg/03/45/05/92/360_F_345059232_CPieT8RIWOUk4JqBkkWkIETYAkmz2b75.jpg">
              </div>
              <!-- (other image boxes) -->
            </div>
          </div>
        </div>
      </div>
    </div>